“携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第13天,点击查看活动详情”
1.前言
通过Go执行shell命令在网上有很多方式,但是在调试的时候往往发现这些方式存在或多或少的问题,最终在这里找到一些目前感觉最佳的方式,出错后的提示信息足够完整。
2.代码示例
这里以修改ip的命令为例:
package main
import (
"fmt"
"os/exec"
)
func main() {
cmd := exec.Command("ifconfig", "ens33", "40.40.40.155",
"netmask", "255.255.255.0")
output, err := cmd.CombinedOutput()
if err != nil {
fmt.Println(fmt.Sprint(err) + ": " + string(output))
}
fmt.Println(string(output))
}
当编译后直接运行时报错:
exit status 255: SIOCSIFADDR: 不允许的操作
SIOCSIFFLAGS: 不允许的操作
SIOCSIFNETMASK: 不允许的操作
SIOCSIFADDR: 不允许的操作
SIOCSIFFLAGS: 不允许的操作
SIOCSIFNETMASK: 不允许的操作
这样我们就可以大致猜测出来是运行权限的问题,然后使用root权限运行程序即可解决,使用一些其它的方式给到的错误都是什么exit 1或者exit 255之类的状态值,不方便调试。
3. execute command failed:exit status 1
如果你在使用一些其它方式调用shell时发现:
execute command failed:exit status 1
参考这里也给出了另一种写法:
stackoverflow.com/questions/1…
4. 代码
cmd := exec.Command("find", "/", "-maxdepth", "1", "-exec", "wc", "-c", "{}", "\\")
var out bytes.Buffer
var stderr bytes.Buffer
cmd.Stdout = &out
cmd.Stderr = &stderr
err := cmd.Run()
if err != nil {
fmt.Println(fmt.Sprint(err) + ": " + stderr.String())
return
}
fmt.Println("Result: " + out.String())
5. 区别
从名字就可以大致猜出来,run、CombinedOutput分别是命令执行后的运行以及组合的结果,所以CombinedOutput会将错误信息和执行结果组合起来,所以如果报错的话通过CombinedOutput可以打印出错误信息,而运行run的话则需要单独捕获错误信息进行打印(还有一个cmd.Output,感兴趣的可以试一下)。