go - 使用 Stdout 和 Stderr 的线程安全操作(exec.Cmd)

标签 go stdout

我有代码,它以正确的方式工作,但它不是线程安全的 https://play.golang.org/p/8EY3i1Uk_aO在这些行中,比赛发生在这里。

stdout := cmd.Stdout.(*bytes.Buffer).String()
stderr := cmd.Stderr.(*bytes.Buffer).String()

我是这样重写的

readout, _ := cmd.StdoutPipe()
readerr, _ := cmd.StderrPipe()

链接 https://play.golang.org/p/htbn2zXXeQk

我不喜欢这里使用 MultiReader 并且我无法将数据 stdout 与 stderr 分开

r, _ := bufio.NewReader(io.MultiReader(readout, readerr)).ReadString('\n')

第二个例子也不起作用(在代码中有注释)。我希望 stdout 不会为空(就像这里的 https://play.golang.org/p/8EY3i1Uk_aO )

如何使逻辑像第一个例子一样,但它应该是线程安全的?

最佳答案

您必须在单独的 goroutine 中泵送 cmd.Stdoutcmd.Stderr 直到它们关闭,例如,就像您对 cmd.Stdin< 所做的那样(但当然是在其他方向)。否则会有死锁的风险 - 进程被阻塞等待写入 stdout/stderr,并且您的程序被阻塞等待进程完成。

或者,如@JimB 所说,只需将字符串缓冲区分配给 cmd.Stdoutcmd.Stderr,它们将在进程运行时被填充。

func invoke(cmd *exec.Cmd) (stdout string, stderr string, err error) {
    stdoutbuf, stderrbuf := new(strings.Builder), new(strings.Builder)
    cmd.Stdout = stdoutbuf
    cmd.Stderr = stderrbuf
    err = cmd.Start()
    if err != nil {
        return
    }
    err = cmd.Wait()
    return stdoutbuf.String(), stderrbuf.String(), err
}

现场演示:

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

关于go - 使用 Stdout 和 Stderr 的线程安全操作(exec.Cmd),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68116457/

相关文章:

python - 无法从 (Python) subprocess.check_output() 获取标准输出/标准错误

python - `print()` 在某些控制台中是否会延迟,而 `stdout.flush` 不会延迟?

config - 使用 Logstash 1.4 将字符串打印到标准输出?

github - 如何使 godoc 链接到 github 上的源代码

unit-testing - 如何使用 mock 来模拟httpclient

go - 为什么在 json.Unmarshal() 之后我得到一个空结构?

go - 重定向Go中子进程的stdout管道

go - 如何在 Bazel 中将 Google API 与 Go 结合使用

mongodb - mgo collection.Find(nil).All(&users) 不工作

c - 当函数声明为传统风格时,为什么输出不正确?