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