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