退出代码不为零时,Golang exec.Command返回nil错误

时间:2019-07-14 20:28:19

标签: shell go

我正在尝试在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,对不起。

1 个答案:

答案 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与管道连接以及进行其他调整。

exec package