Rubyスクリプト中から別のRubyスクリプトを呼び出した時の標準出力

Rubyスクリプトから別のRubyスクリプトを呼び出したい時がある.
そういう場合,

msg=`hoge.rb`

とすると,hoge.rbが標準出力へ出力した文字列すべてを変数msgで受け取ることが出来る.
1行ずつ受け取って処理したい場合は,

IO.popen("hoge.rb") do |pipe|
    pipe.each do | line |
         print line
    end
end

という感じにすれば,1行ずつとって表示することが出来る.
しかし,デフォルトだと,Rubyスクリプトの標準出力はバッファリングされるため,hoge.rbの処理に時間がかかる場合,長い時間立った後に,まとめてhoge.rbの出力をどかっと渡されるようになる.
(受け取ったプログラムは,それを1行ずつ処理することはできるけれど)
これは標準出力がバッファリングされているのが原因なので,バッファリングしないようにすればOK.
つまり,呼び出される側のスクリプトhoge.rbの最初に,

STDOUT.sync = true

と書けば良い.
[Ruby] Rubyの標準出力をバッファしないを参考にしました.)
これで,ばっちり動く.
例(STDOUT.sync=trueの有無での挙動の違いを確認)
呼び出される側:hoge.rb

#!/usr/bin/ruby
STDOUT.sync = true
puts "hoge"
sleep 3 # 長時間かかる処理
puts "hoge"

呼び出す側:main.rb

#!/usr/bin/ruby
puts "start"
IO.popen("test.rb") do |f|
        f.each do |line|
                print line
        end
end
puts "finish"

コメントする