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
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 求差集那个函数有问题,有无佬可以解决
  • ¥15 【提问】基于Invest的水源涵养
  • ¥20 微信网友居然可以通过vx号找到我绑的手机号
  • ¥15 寻一个支付宝扫码远程授权登录的软件助手app
  • ¥15 解riccati方程组
  • ¥15 display:none;样式在嵌套结构中的已设置了display样式的元素上不起作用?
  • ¥15 使用rabbitMQ 消息队列作为url源进行多线程爬取时,总有几个url没有处理的问题。
  • ¥15 Ubuntu在安装序列比对软件STAR时出现报错如何解决
  • ¥50 树莓派安卓APK系统签名
  • ¥65 汇编语言除法溢出问题