2009-08-01 54 views
16

RubyでIO.popenを使用して、一連のコマンドラインコマンドをループで実行しています。私はループの外で別のコマンドを実行する必要があります。ループ内のすべてのコマンドが終了するまで、ループ外のコマンドは実行できません。IO.popenを使用してプロセスが終了するのを待つ方法は?

これを実行するためにプログラムを待機させるにはどうすればよいですか?現時点では、最終的なコマンドはすぐに実行されていません。

例:

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

だから、すべてcmd_foosanother_cmdが実行される前に返却する必要があります。

答えて

4

IO.popen呼び出しの結果を変数に割り当てる必要があり、がすべてtrueになるまで、read()を呼び出す必要があると思います。

すべてのプログラムが実行を終了したことを知っていれば、another_cmdを開始できます。

+2

ただ、追加の注記として:IOメソッドのブロック形式を使用すると、通常は安全です。また、1.9では、ブロック変数の有効範囲が異なるため、ブロック外の同じ名前付き変数の変更を防ぐことができます(警告が表示されます)。 –

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

+0

それは欠落しています。 –

3

私はあなたが最後popenコール同期するためにThread.joinを使用することをお勧め:あなたはpopenの出力が必要です

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

t.join 

IO.popen(another_cmd) 
1

を?そうでない場合は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を破棄しますか? Docsは '$?'をセットしていると言いますが、私はブロックしないでstdoutもすべて破棄します。 –

+0

"stdoutを破棄する"という言葉はどういう意味ですか?表示するコードは何も破棄しません。あなたが何かを実行したいだけで出力システム()が特別なものではない場合は、 –

+0

は "discard stdout"で "出力を読む"を意味していました。 –

16

どうやらこれを行うにはcanonical wayは次のとおりです。

Process.wait(popened_io.pid) 
+0

この回答が最も正しいです。副作用がなく(io.readのような)、それが何をしているのかは非常に明白です。 – siannopollo

関連する問題