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
……って、あれうまく行かない例を作ったつもりが 動いちゃったよ。えーと、ま、いっか。サンプルとしてつこてくだされ。