Rubyのpty,expectで同一wordをwaitすると出力が止まる

    Rubyからexpect & ptyを組み合わせてtelnetをする方法を記事にした。多段telnetをすると、出力に処理結果が表示されないことに気づいた。pyt.getptyでも、pty.spawnでも同じ。多段sshも同じ。

    Ruby から サーバ上にパスワードなしでtelnetログイン(expect,pty) | Futurismo

    正確にいうと、初めはちょろっと出力されるが、途中から表示されなくなる。echoコマンドだと6コまで表示されて、pwdコマンドを実行すると、2つまでされた。この違いはなんだろう(・・?

    表示されてないだけで、処理自体は動いているようだ。バックグラウンド処理(&)として起動すると、ちゃんと出力される。

    また、多段telnetでない場合は問題なくexpectが動作する。多段にすると、失敗する。

    いろいろと実験して、解決方法を探ってみたが、結論はわからなかった。

    原因

    expectで同一wordをwaitしていると、初めのwordをexpectした時点で、後ろのexpectも動作する。一気に動作するために、表示に間に合わに終了するため、動作していないように見えた。(echo と pwdで差がでたのも実行時間のせい)

    これだとダメ。同一の”tsunera-virtual-machine”

    r.expect(“tsunera-virtual-machine”){ w.puts “echo  ‘hello’” }
    r.expect(“tsunera-virtual-machine”){ w.puts “echo  ‘hello’” }
    r.expect(“tsunera-virtual-machine”){ w.puts “echo  ‘hello’” }
    r.expect(“tsunera-virtual-machine”){ w.puts “echo  ‘hello’” }
    r.expect(“tsunera-virtual-machine”){ w.puts “echo  ‘hello’” }
    r.expect(“tsunera-virtual-machine”){ w.puts “echo  ‘hello’” }

    これだとOK.期待文字列がかぶってないので。

    r.expect(“hello”){ w.puts “echo  ‘hello1’” }
       r.expect(“hello1”){ w.puts “echo  ‘hello2’” }
       r.expect(“hello2”){ w.puts “echo  ‘hello3’” }
       r.expect(“hello3”){ w.puts “echo  ‘hello4’” }
       r.expect(“hello4”){ w.puts “echo  ‘hello5’” }
       r.expect(“hello5”){ w.puts “echo  ‘hello6’” }
       r.expect(“hello6”){ w.puts “echo  ‘hello7’” }

    不思議なのは、前回記事にした Smart-Compileを経由したスクリプト実行だとうまくいく。

    EmacsでRubyの開発環境をめちゃガチャパワーアップしたまとめ | Futurismo

    このへんに解決の糸口がありそうだが、お腹がすいたので今日はここまで。

    追記 解決 13/08/11

    いろいろ試行錯誤して、うまくいく方法を見つけました。

    waitで止まったように見えていたが、実はウラで動いていたよう。標準出力に出力されていないだけだっだ。

    {|c| print c}

    telnetした結果を表示するためには、waitforを以下の形式で書けば良い。

    telnet.waitfor(/*****/){ |c| print c }

    {|c| print c}で標準出力を出力する。

    telnet.cmdてはなくて、telnet.puts

    多段telnetをするとき、telnet.cmd(“hogehoge”)で実行すると、“hogehoge”コマンドの出力を待ち続けるために、エラーする。telnet.cmdではなくtelnet.putsを利用することで、出力を待つことがなくなる。

    STDOUT.sync = true

    STDOUT.flushを実行すると、バッファにたまっている出力が吐出されるので、よりリアルタイムに画面出力させることができる。

    コマンドを実行するたびに、これを打つのは面倒なので、常時リアルタイムで出力するよう、おまじないを書く。

    STDOUT.sync = true