【发布时间】: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()之前不要返回。
标签: go