我正在尝试在Golang中运行命令,但由于err为nil,它似乎丢失了退出代码:
func runCommand() []byte, error {
cmd := exec.Command("/bin/bash", "-c", "KUBECONFIG=/tmp/.kube/config helm version")
cmd.Stdin = os.Stdin
cmd.Stderr = os.Stderr
stdOut, err := cmd.StdoutPipe()
if err != nil {
return nil, err
}
if err := cmd.Start(); err != nil {
return nil, err
}
bytes, err := ioutil.ReadAll(stdOut)
if err != nil {
return nil, err
}
if err := cmd.Wait(); err != nil {
return nil, err
}
fmt.Println(string(bytes))
return bytes, nil
}
即使命令以退出代码!= 0返回,此返回nil。
如果我输入:
$> /bin/bash -c KUBECONFIG=/tmp/.kube/config helm version
$<
$> echo $?
$< 0
如果我输入:
$> /bin/bash -c 'KUBECONFIG=/tmp/.kube/config helm version'
$< ...connection refused
$> echo $?
$< 1
所以我试图将命令用单引号引起来:
cmd := exec.Command("/bin/bash", "-c", "'KUBECONFIG=/tmp/.kube/config helm version'")
但是我得到:
/bin/bash: KUBECONFIG=/tmp/.kube/config helm version: No such file or directory
(不必说/tmp/.kube/config在那,但是我不认为没有这样的文件或目录是指它)。
我在做什么错了?
谢谢
更新:事实证明我错了。实际上,我尝试了两个命令,并且由于某种原因,我确定一个失败的原因是我上面提到的那个,而第二个命令退出时的状态代码不同于0。该代码按预期工作,并且err不为nil如果退出代码!= 0,对不起。
答案 0 :(得分:1)
似乎您应该可以使用exec.ExitError
来获得它,请参阅exec package。请注意,您可能需要Go 1.12。这是一个可运行的示例(但在去操场上它不会为您提供现实的输出):
package main
import (
"fmt"
"io/ioutil"
"os"
"os/exec"
)
func main() {
cmd := exec.Command(`/bin/bash`, `-c`, `FOO=bar ls /foo`)
cmd.Stdin = os.Stdin
cmd.Stderr = os.Stderr
stdOut, err := cmd.StdoutPipe()
if err != nil {
fmt.Println("Error 1")
}
if err := cmd.Start(); err != nil {
fmt.Println("Error 2")
}
bytes, err := ioutil.ReadAll(stdOut)
if err != nil {
fmt.Println("Error 3")
}
if err := cmd.Wait(); err != nil {
fmt.Println("Error 4")
if exitError, ok := err.(*exec.ExitError); ok {
fmt.Printf("Exit code is %d\n", exitError.ExitCode())
}
}
fmt.Println(string(bytes))
}
在我的系统上打印:
$ go run main.go
ls: cannot access '/foo': No such file or directory
Error 4
Exit code is 2
如果这对您不起作用,也许值得遵循@JimB的建议并直接调用Helm? Go标准库也应支持管道:
它包装了os.StartProcess,以便更轻松地重新映射stdin和stdout,将I / O与管道连接以及进行其他调整。