dongxing2302 2016-08-26 19:24
浏览 147
已采纳

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

I have the following bash script bash_loop.shthat prints 1 to 10 and sleep 3 s in between.

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

Right now, I have my go code as follow:

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())

However, this only print out everything after the cmd finish running after 30s, instead of print things as they become available.

So my question is that if I can print each number while the bash script is still running instead of printing everything all together after the bash script finishes execution.

P.S.1: In the real use case, I have to process the output of bash script in realtime, instead of simply printing things out to os.Stdout, so I am wondering if there's any command poll() interface or equivalence in go.

P.S.2:In the real use case, I want to detach from the child process as soon as I find interesting message. For example, after I read 3, I want my function return 3 immediately and not wait for the rest of output anymore, though I still want the child process (the bash script) itself to be up and running.

P.S.3: In python, I would do something like this

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: Now I have evolved my go snippet to follow. Will the child become a zombie if I return before the command finishes running?

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条回答 默认 最新

  • dongyou6847 2016-08-26 19:30
    关注

    Set the command output to stdout:

    cmd.Stdout = os.Stdout
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥20 keepalive配置业务服务双机单活的方法。业务服务一定是要双机单活的方式
  • ¥50 关于多次提交POST数据后,无法获取到POST数据参数的问题
  • ¥15 win10,这种情况怎么办
  • ¥15 如何在配置使用Prettier的VSCode中通过Better Align插件来对齐等式?(相关搜索:格式化)
  • ¥100 在连接内网VPN时,如何同时保持互联网连接
  • ¥15 MATLAB中使用parfor,矩阵Removal的有效索引在parfor循环中受限制
  • ¥20 Win 10 LTSC 1809版本如何无损提升到20H1版本
  • ¥50 win10 LTSC 虚拟键盘不弹出
  • ¥30 微信小程序请求失败,网页能正常带锁访问
  • ¥15 Matlab求解微分方程,如何用fish2d进行预优?