go - 如何在go中打印正在运行的子进程的实时输出?
Posted
技术标签:
【中文标题】go - 如何在go中打印正在运行的子进程的实时输出?【英文标题】:How to print the realtime output of running child process in go? 【发布时间】:2016-08-26 19:24:41 【问题描述】:我有以下 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
现在,我的 go 代码如下:
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())
但是,这只会在 cmd 运行 30 秒后 打印出所有内容,而不是在可用时打印。
所以我的问题是,如果我可以打印每个数字 而 bash 脚本仍在运行,而不是在 bash 脚本完成执行后将所有内容一起打印。
P.S.1:在实际用例中,我必须实时处理 bash 脚本的输出,而不是简单地将内容打印到 os.Stdout
,所以我想知道是否有任何命令 poll()
接口或等效项去吧。
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 sn-p 来跟随。如果我在命令运行完成之前返回,孩子会变成僵尸吗?
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()
【问题讨论】:
Streaming commands output progress 的相关/可能重复。 @icza 很棒的指针。我添加了 P.S.2,而不是等待整个 Cmd 完成,我希望我的函数在读取后立即返回有趣的输出,而不会终止正在运行的进程。 re P.S.4,是的,你需要调用wait,所以在调用cmd.Wait()之前不要返回。 【参考方案1】:将命令输出设置为标准输出:
cmd.Stdout = os.Stdout
【讨论】:
我实际上想嗅探 bash 脚本的输出并在将其打印到os.Stdout
之前进行一些处理。
下次一定要在你的问题中提到你想做的每一件事,以避免问这些:xyproblem.info
@cookieisaac:那为什么不使用StdOutPipe?以上是关于go - 如何在go中打印正在运行的子进程的实时输出?的主要内容,如果未能解决你的问题,请参考以下文章
实时打印使用 Python 中的子进程启动的 bash 命令的结果