[英]Getting output from `exec.Cmd` in “real-time”
This question is similar to Golang - Copy Exec output to Log except it is concerned with the buffering of output from exec
commands. 这个问题类似于Golang-将Exec输出复制到Log,除了它与
exec
命令的输出缓冲有关。
I have the following test program: 我有以下测试程序:
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
, which the above refers to, simply contains: 上面提到的
inf_loop.py
仅包含:
print "hello"
while True:
pass
The go program hangs when I run it and doesn't output anything, but if I use os.Stdout
instead of out
then it outputs "hello" before it hangs. 当我运行go程序时,它会挂起并且不输出任何内容,但是如果我使用
os.Stdout
而不是out
那么它将在挂起之前输出“ hello”。 Why is there a discrepancy between the two io.Writer
s and how can it be fixed? 为什么两个
io.Writer
之间存在差异,并且如何解决?
Some more diagnostic information: 一些更多的诊断信息:
inf_loop.py
then "hello" is output from both programs, as expected. inf_loop.py
删除循环后,两个程序将按预期输出“ hello”。 yes
as the program instead of the python script and outputting len(p)
in outstream.Write
then there is output, and the output is usually 16384 or 32768. This indicates to me that this is a buffering issue, as I originally anticipated, but I still don't understand why the outstream
structure is being blocked by buffering but os.Stdout
isn't. yes
作为程序而不是python脚本并在outstream.Write
输出len(p)
,将输出,输出通常为16384或32768。这向我表明这是一个缓冲问题,正如我最初预期的那样,但我还是不明白为什么outstream
结构被阻止通过缓冲,但os.Stdout
不是。 One possibility is that the behaviour is the result of the way that exec
passes the io.Writer
directly to os.StartProcess
if it is an os.File
(see source for details), otherwise it creates an os.Pipe()
between the process and the io.Writer
, and this pipe may be causing the buffering. exec
传递io.Writer
直接os.StartProcess
如果它是一个os.File
(见源的详细信息),否则它创建一个os.Pipe()
的处理之间和io.Writer
,并且此管道可能正在引起缓冲。 However, the operation and possible buffering of os.Pipe()
is too low-level for me to investigate. os.Pipe()
的操作和可能的缓冲级别太低,我无法研究。 Python buffers stdout by default. Python默认情况下会缓冲stdout。 Try this program:
试试这个程序:
import sys
print "hello"
sys.stdout.flush()
while True:
pass
or run Python with unbuffered stdout and stderr: 或使用无缓冲的stdout和stderr运行Python:
cmd := exec.Command("python", "-u", "foo.py")
Note the -u flag. 注意-u标志。
You see different results when using cmd.Stout = os.Stdout
because Python uses line buffering when stdout is a terminal. 使用
cmd.Stout = os.Stdout
时会看到不同的结果,因为当stdout为终端时,Python使用行缓冲。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.