pcめも、新年一発目。今年もよろしゅ。
子プロセスの標準出力と標準エラー出力を両方読み取る話。 Ruby1.9 なら spawn を使うところだが、Ruby1.8 on unix だとどうすぺ。
はい、open3。単純化したのはこう。
#!/usr/bin/env ruby
require 'open3'
Open3.popen3("sh subproc.sh") do |i, o, e|
i.close_write
t1 = Thread.new {
while line=o.gets do print line end
}
Thread.new {
while line=e.gets do print line end
}
t1.join
puts "Finished!"
end
Thread使えば実にシンプル。ところが、Ruby/tk と組み合わせると 意外に難儀する。Ruby/tk と RubyのThread が相性悪いのは よく言われていることだが、open3で上記のようなことを手軽に済ませたい場合は 困る。たとえば、子プロセスの出力をTkウィンドウに出したりしたいとき、 こんな風にするとうまく行かない。
#!/usr/bin/env ruby
require 'tk'
require 'open3'
text = TkText.new(:width=>80, :height=>10) {
self.value = "[[ Output from Subprocess ]]\n"
}.pack
TkButton.new(:text => "DONE", :command => proc{exit}).pack
def update(textwig, string)
textwig.value += string
textwig.see('end')
textwig.update
end
Open3.popen3("sh subproc.sh") do |i, o, e|
i.close_write
t1 = Thread.new {
while line=o.gets do update(text, line) end
}
Thread.new {
while line=e.gets do update(text, line) end
}
t1.join
puts "Finished!"
end
Tk.mainloop
……って、あれうまく行かない例を作ったつもりが 動いちゃったよ。えーと、ま、いっか。サンプルとしてつこてくだされ。