如何在运行 Golang 的 exec. Command 时调试“ exit status 1”错误

当我运行以下代码时:

cmd := exec.Command("find", "/", "-maxdepth", "1", "-exec", "wc", "-c", "{}", "\\")
var out bytes.Buffer
cmd.Stdout = &out
err := cmd.Run()
if err != nil {
fmt.Println(err)
return
}
fmt.Println("Result: " + out.String())

我得到了这个错误:

出口状态1

但是,这对调试错误的确切原因没有帮助。

如何获得更详细的信息?

73331 次浏览

解决方案是使用 Command 对象的 Stderr属性:

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())

运行上面的代码,可以明确问题所在:

退出状态1: find:-exec: 不终止“ ;”或“ +”

编辑:

在上面的代码中,我们预计在出现错误的情况下,消息将被打印到 stderr,命令将返回非零错误代码。这或多或少是标准的。

然而,正如下面@norberhuis 提到的,一些命令将错误打印到 stdout。其他命令可能打印到 stderr,但返回0的错误代码(在这种情况下,err将是 nil)。在 stderr 中包含消息并不一定意味着存在错误(ffmpeg 工具经常这样做)。

因此,基本上您可能需要调整上面的代码以适应您所期望的命令。

正如 Laurent 所提到的,您可以覆盖 Stderr 文件描述符来捕获 Stderr 输出以获得更好的错误消息。我个人更喜欢使用 CombinedOutput方法来执行相对简单的命令:

cmd := exec.Command("find", "/", "-maxdepth", "1", "-exec", "wc", "-c", "{}", "\\")
output, err := cmd.CombinedOutput()
if err != nil {
fmt.Println(fmt.Sprint(err) + ": " + string(output))
return
}
fmt.Println(string(output))

下面是上面示例的 play.golang.org 链接: http://play.golang.org/p/z8k9zO755P