繁体   English   中英

从“ exec.Cmd”中实时获取输出

[英]Getting output from `exec.Cmd` in “real-time”

这个问题类似于Golang-将Exec输出复制到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.Writer之间存在差异,并且如何解决?

一些更多的诊断信息:

  • inf_loop.py删除循环后,两个程序将按预期输出“ hello”。
  • 当使用yes作为程序而不是python脚本并在outstream.Write输出len(p) ,将输出,输出通常为16384或32768。这向我表明这是一个缓冲问题,正如我最初预期的那样,但我还是不明白为什么outstream结构被阻止通过缓冲,但os.Stdout不是。 一种可能性是,该行为是该方法的结果exec传递io.Writer直接os.StartProcess如果它是一个os.File (见的详细信息),否则它创建一个os.Pipe()的处理之间和io.Writer ,并且此管道可能正在引起缓冲。 但是, os.Pipe()的操作和可能的缓冲级别太低,我无法研究。

Python默认情况下会缓冲stdout。 试试这个程序:

import sys
print "hello"
sys.stdout.flush()
while True:
    pass

或使用无缓冲的stdout和stderr运行Python:

cmd := exec.Command("python", "-u", "foo.py")

注意-u标志。

使用cmd.Stout = os.Stdout时会看到不同的结果,因为当stdout为终端时,Python使用行缓冲。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM