【发布时间】:2015-06-24 00:38:35
【问题描述】:
这个问题与Golang - Copy Exec output to Log 类似,只是它与exec 命令的输出缓冲有关。
我有以下测试程序:
package main
import (
"fmt"
"log"
"os/exec"
)
func main() {
cmd := exec.Command("python", "inf_loop.py")
var out outstream
cmd.Stdout = out
if err := cmd.Start(); err != nil {
log.Fatal(err)
}
fmt.Println(cmd.Wait())
}
type outstream struct{}
func (out outstream) Write(p []byte) (int, error) {
fmt.Println(string(p))
return len(p), nil
}
inf_loop.py,上面提到的,只是包含:
print "hello"
while True:
pass
go 程序在我运行时挂起并且不输出任何内容,但如果我使用os.Stdout 而不是out,那么它会在挂起之前输出“hello”。为什么两个io.Writers 之间存在差异,如何解决?
更多诊断信息:
- 当循环从
inf_loop.py中删除时,两个程序都会输出“hello”,正如预期的那样。 - 当使用
yes作为程序而不是python脚本并在outstream.Write中输出len(p)然后有输出,输出通常是16384或32768。这向我表明这是一个缓冲问题,正如我最初预期的那样,但我仍然不明白为什么outstream结构被缓冲阻塞但os.Stdout不是。一种可能性是该行为是exec将io.Writer直接传递给os.StartProcess(如果它是os.File)的结果(有关详细信息,请参阅source),否则它会在两者之间创建os.Pipe()进程和io.Writer,这个管道可能会导致缓冲。但是,os.Pipe()的操作和可能的缓冲级别太低,我无法调查。
【问题讨论】: