- expectで素朴にプロンプトを待つだけだとコマンドの実行が完了するまで途中の出力が表示できなくていまいちだったのであれこれ試して下記のようにしてみた。
- プロンプトのパターンに改行が含まれる場合はもうちょい工夫(途中の出力をバッファリングしておく)が必要。
# coding: utf-8 require 'pty' require 'expect' require 'timeout' puts "-->> spawn" PTY.spawn("bash -i") do |i, o| # 最初の出力を出し切る begin Timeout.timeout(1) do loop { print i.getc } end rescue Timeout::Error end # 実行するコマンドを送信 o.puts "ruby command.rb" finished = false while ! finished # プロンプトに加えて途中の出力にもマッチさせる i.expect(/(.*)\$ |(.*)\n/) do |m| print m[0] if m[1] # プロンプトが来た場合 finished = true else # 途中の出力 end end end end puts "<<-- spawn"
テスト用の command.rb
(1..3).each do |i| $stdout.puts "out #{i}" $stderr.puts "err #{i}" sleep 1 end
$ ruby -v ruby 2.5.0p0 (2017-12-25 revision 61468) [x86_64-linux]
追記 2018-02-25
単に標準出力に出したいだけなら $expect_verbose = true
する方法もあります。
IO#expect
のソースはコメントを除くと40行くらいなのでさらっと見ておくとよいです。場合によっては expect
自体をモンキーパッチするのもいいかも。
ruby/expect.rb at v2_5_0 · ruby/ruby