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

标签 shell go

我正在尝试在 Golang 中运行一个命令,但看起来它丢失了退出代码,因为错误为 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 在那里,但我不认为 no such file or directory 指的是那个)。

我做错了什么?

谢谢

更新:结果我弄错了。事实上,我尝试了两个命令,出于某种原因,我确定失败的是我上面提到的那个,而第二个命令以不同于 0 的状态代码退出。代码按预期工作并且错误不为零在退出代码 != 0 的情况下。很抱歉。

最佳答案

似乎您应该能够通过 exec.ExitError 获取它,参见 exec package .请注意,您可能需要 Go 1.12。这是一个可运行的示例(但它不会在 go playground 上为您提供真实的输出):

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 标准库也应该支持管道:

It wraps os.StartProcess to make it easier to remap stdin and stdout, connect I/O with pipes, and do other adjustments.

( exec package )

关于shell - Golang exec.Command 在退出代码不为零时返回 nil 错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57030918/

相关文章:

go - 无法分配给结构字段/分配给 nil 映射中的条目

memory-management - 在 GO 中处理大内存块

go - 在 Golang 中使用全局列表变量。接收 "Use of package list without selector"

ruby - Chef shell脚本交互

作为 cron 作业失败的 Ruby 脚本

linux - 如何在提示用户在 shell 脚本中输入时捕获并采取行动?

linux - 如何使用shell脚本打印解析Json

函数 slice 参数与全局变量的性能?

go - 我可以传递构建命令标志并读取内部代码吗?

shell - 如何从较低级别的函数中止 fish 脚本?