2009-08-01 128 views
16

我在Ruby中使用IO.popen在循环中运行一系列命令行命令。然后我需要在循环之外运行另一个命令。直到循环中的所有命令都终止,循环外的命令才能运行。如何等待进程完成使用IO.popen?

如何让程序等待这种情况发生?目前最后的命令运行得太快。

一个例子:

for foo in bar 
    IO.popen(cmd_foo) 
end 
IO.popen(another_cmd) 

因此,所有cmd_foos需要运行another_cmd之前返回。

回答

4

我想你需要将周期内的IO.popen调用的结果赋值给变量,并且一直调用read()直到eof()成为真。

然后你知道所有的程序都已经完成了执行,你可以开始another_cmd

+2

只是作为一个附加的注释:使用的IO方法块形式通常是安全的。此外,在1.9中,您可以增加健壮性,因为块变量具有不同的范围,从而防止在块之外修改相同的命名变量(并且您将获得警告)。 – 2009-08-07 09:50:23

6
for foo in bar 
    out = IO.popen(cmd_foo) 
    out.readlines 
end 
IO.popen(another_cmd) 

将输出读取到一个变量,然后调用out.readlines做到了。我认为out.readlines必须等待该过程结束后才返回。

感谢Andrew Y为我指出了正确的方向。

+0

我尝试了完全相同的事情,并以僵尸(已停用)结束,所以不理想 – nhed 2014-04-07 15:01:52

+0

它缺少out.close – 2015-01-28 01:47:14

3

我建议你使用Thread.join最后popen调用同步:

t = Thread.new do 
    for foo in bar 
     IO.popen(cmd_foo) 
    end 
end 

t.join 

IO.popen(another_cmd) 
1

你需要的popen输出?如果不是,你想使用Kernel#system还是其他一些命令?

18

使用块形式和阅读所有内容:

IO.popen "cmd" do |io| 
    # 1 array 
    io.readlines 

    # alternative, 1 big String 
    io.read 

    # or, if you have to do something with the output 
    io.each do |line| 
    puts line 
    end 

    # if you just want to ignore the output, I'd do 
    io.each {||} 
end 

如果没有读取输出,它可能是工艺块,因为连接其它工艺管道和你的过程充满了,没有人从中读取。

+0

丢弃标准输出时`IO.popen('cmd')。close`会工作吗?文档说它设置了'$?`(因此等待),但是我不清楚它是否会在没有阻塞的情况下丢弃所有stdout。 – 2014-11-06 13:55:37