Go:通过os.exec执行命令时如何防止管道阻塞?

问题描述 投票:-1回答:2

在Go版本1.14.2中,以下是一些示例代码,这些代码说明了通常的方法:生成命令,通过stdin向其馈送数据,然后捕获其stdout和stderr。它利用管道,但是如果在过程完成之前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 pipe buffer exec
2个回答
2
投票

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

https://play.golang.org/p/RUDZsJnmJ1C


1
投票

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

var stderrBytes []byte
go func() {
  stderrBytes, _ = ioutil.ReadAll(stderr)
}()

err = cmd.Start()
stdoutBytes, err := ioutil.ReadAll(stdout)
© www.soinside.com 2019 - 2024. All rights reserved.