There's an echo in my head

日々のメモ。

外部コマンド実行時の標準出力、標準エラーを随時受け取る

Rubyで外部コマンドを実行する手段はいろいろあるけど、そのほとんどは実行し終わったときにまとめて標準出力等を得ることになる。時間がかかるコマンドを実行しつつその出力を随時受け取りたい場合にはOpen3.popen3を使う。

require "open3"

Open3.popen3("long-long-command") do |stdin, stdout, stderr, wait_thr|
  stdin.close_write # 標準入力を閉じる。

  begin
    # 標準出力、標準エラーの出力があるまで延々と待ち、随時1行ずつ書き出す
    loop do
      IO.select([stdout, stderr]).flatten.compact.each do |io|
        io.each do |line|
          next if line.nil? || line.empty?
          puts line
        end
      end
      # 標準出力、標準エラーでEOFが検知された、つまり外部コマンドの実行が終了したらループを抜ける
      break if stdout.eof? && stderr.eof?
    end
  rescue EOFError
  end
end
このブログに出てくるコードスニペッツは、引用あるいは断りがない限りMITライセンスです。