如何在go中打印运行子进程的实时输出?

时间:2016-08-26 19:24:42

标签: go

我有以下bash脚本bash_loop.sh,它打印1到10并在其间睡3秒。

#!/bin/bash
# Basic while loop
counter=1
while [ $counter -le 10 ]
do
    echo $counter
    ((counter++))
   sleep 3 
done
echo All done

现在,我的代码如下:

burstingScript := "bash_loop.sh"
cmd := exec.Command("/bin/sh", burstingScript)

var out bytes.Buffer
cmd.Stdout = &out
if err := cmd.Run(); err != nil {
    fmt.Println("An error has occurred..")
    log.Fatal(err)
}
fmt.Println(out.String())

但是,这只会在30秒后打印 cmd完成后的所有内容,而不是在可用时打印内容。

所以我的问题是,如果我可以打印每个数字 bash脚本仍在运行,而不是在bash脚本完成执行后将所有内容打印在一起。

PS1:在实际使用案例中,我必须实时处理bash脚本的输出,而不是简单地将内容打印到os.Stdout,所以我想知道是否有任何命令poll() go中的界面或等价。

P.S.2:在实际使用案例中,我想在找到有趣的信息后立即脱离子进程。例如,在我读完3之后,我希望我的函数立即返回3并且不再等待输出的其余部分,尽管我仍然希望子进程(bash脚本)本身启动并运行。

P.S.3:在python中,我会做这样的事情

cmd = "./bash_loop.sh"
p = subprocess.Popen(cmd, shell=True, stderr=subprocess.PIPE, stdout=subprocess.PIPE)

result = {}
while True:
    out = p.stdout.readline()
    if out == '' and p.poll() != None:
        break
    if out != '':
        #process(out)
        sys.stdout.write(out)
        sys.stdout.flush()

P.S.4:现在我已经进化了我的go片段。如果我在命令完成运行之前返回,孩子会变成僵尸吗?

burstingScript := path.Join(rootDir, "bash_loop.sh")
cmd := exec.Command("/bin/sh", burstingScript)

stdout, _ := cmd.StdoutPipe()
cmd.Start()
scanner := bufio.NewScanner(stdout)
for scanner.Scan() {
    m := scanner.Text()
    fmt.Println(m)
    //if m=="3" {
    //  return process(m)
    //}
}
cmd.Wait()

1 个答案:

答案 0 :(得分:2)

将命令输出设置为stdout:

cmd.Stdout = os.Stdout