【问题标题】:Go: How to prevent pipes from blocking when executing a command via os.exec?Go:通过 os.exec 执行命令时如何防止管道阻塞?
【发布时间】:2020-05-13 20:13:37
【问题描述】:

在 Go 版本 1.14.2 中,以下是一些示例代码,说明了生成命令、通过标准输入向其提供数据、然后捕获其标准输出和标准错误的常用方法。它使用了管道,但是如果 stdout 或 stderr 管道的缓冲区在进程完成之前已满(此示例中省略了错误处理),这可能会导致程序阻塞...

func ExecExample(cmd *exec.Cmd, input *[]byte) {
    stdout, err := cmd.StdoutPipe()
    stderr, err := cmd.StderrPipe()
    stdin, err := cmd.StdinPipe()
    err = cmd.Start()
    stdin.Write(*input)
    stdin.Close()
    stdoutBytes, err := ioutil.ReadAll(stdout)
    stderrBytes, err := ioutil.ReadAll(stderr)
    waitErr := cmd.Wait()
}

如何在 Go 中重构此示例代码,以使 stdout 和 stderr 管道永远不会阻塞?

另外,请注意,我正在寻找一种方法来分别捕获 stdout 和 stderr 输出。我不希望它们结合在一起。

提前谢谢你。

【问题讨论】:

  • 在 Go 中做并发事情的方法是使用 goroutines。但是为什么不像examples 中的assign io.Writers to Stdout and Stderr(它会自动为你处理goroutines)呢?
  • 我正试图弄清楚如何做到这一点。我是Go新手,所以请原谅我的无知。确切地说,我将在 cmd.Stdout 和 cmd.Stderr 中放入什么来为它们分配 io.Writers,以及在程序完成后我将如何捕获字节?
  • 文档中的链接示例正是这样做的。
  • 谢谢大家。我最初错过了链接的示例,现在我更好地理解了 goroutines。

标签: go pipe buffer exec


【解决方案1】:

让 exec 包为您完成工作。

var stdout, stderr bytes.Buffer
cmd.Stdout = &stdout
cmd.Stderr = &stderr
cmd.Stdin = bytes.NewReader(*input)
err := cmd.Run()
stdoutBytes := stdout.Bytes()
stderrBytes := stderr.Bytes()

exec 包创建和管理将数据泵入和输出子进程所需的 goroutine。

Run it in the playground.

【讨论】:

    【解决方案2】:

    在 goroutine 中读取一个(或两个)流:

    var stderrBytes []byte
    go func() {
      stderrBytes, _ = ioutil.ReadAll(stderr)
    }()
    
    err = cmd.Start()
    stdoutBytes, err := ioutil.ReadAll(stdout)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-04-22
      • 2017-05-12
      • 1970-01-01
      • 2013-06-17
      • 2010-10-09
      • 2010-10-08
      • 2016-09-16
      • 1970-01-01
      相关资源
      最近更新 更多