在Golang中运行exec.Command时,如何调试“退出状态1”错误?

huangapple go评论81阅读模式
英文:

How to debug "exit status 1" error when running exec.Command in Golang

问题

当我运行下面的代码时:

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

然而,这并不有助于调试错误的确切原因。

如何获取更详细的信息?

英文:

When I run the code below:

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

I am getting this error:

> exit status 1

However this is not helpful to debug the exact cause of the error.

How to get more detailed information?

答案1

得分: 153

解决方案是使用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())

运行上述代码,将清楚地显示问题所在:

exit status 1: find: -exec: no terminating ";" or "+"

编辑:

在上面的代码中,我们期望在出现错误时,消息将被打印到stderr,并且命令将返回非零错误代码。这在大多数情况下是标准的。

然而,正如@snorberhuis在下面提到的,有些命令将错误打印到stdout。其他命令可能会将错误打印到stderr,但返回错误代码为0(此时err将为nil)。而且,stderr中的消息并不一定意味着有错误(ffmpeg工具经常这样做)。

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

英文:

The solution is to use the Stderr property of the Command object. This can be done like this:

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

Running the above code, would make it clear what the issue is:

> exit status 1: find: -exec: no terminating ";" or "+"

Edit:

In the code above, we expect that in case of error, the messages will be printed to stderr and the command will return a non-zero error code. This is more or less standard.

However, as mentioned below by @snorberhuis, some commands print the errors to stdout. Other commands might print to stderr but return an error code of 0 (in which case err will be nil). And having messages in stderr doesn't necessarily mean there's an error (ffmpeg tools do this a lot).

So basically you might need to tweak the code above to accommodate the commands you expect.

答案2

得分: 59

如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

英文:

As Laurent mentioned, you can override the Stderr file descriptor to capture the stderr output for a better error message. I personally prefer to use the CombinedOutput method for a command if doing something relatively simple:

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

Here's a play.golang.org link for the above example: http://play.golang.org/p/z8k9zO755P

huangapple
  • 本文由 发表于 2013年8月10日 15:32:18
  • 转载请务必保留本文链接:https://go.coder-hub.com/18159704.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定