2012-04-19 25 views
12

ファイルを受け取り、そのファイルをいくつかのバイナリの1つに渡して処理し、エラーの変換プロセスを監視するコードを書いています。私はOSX上で次のルーチンを書いてテストしましたが、Linuxは私が明確ではない理由で失敗します。Ruby on Linux PTYはEOFなしで消えますErrno :: EIO

#run the command, capture the output so it doesn't display 
PTY.spawn(command) {|r,w,pid| 
    until r.eof? do 
     ##mark 
     puts r.readline 
    end 
} 

実行されるコマンドはかなり異なります。##マークのコードは、問題をデバッグするためにローカルエコーに簡素化されています。コマンドが実行され、スクリプトは端末で予想される出力を出力し、その後例外をスローします。 Errno::EIO (Input/output error - /dev/pts/0):

コマンド文字列のすべての私はそのエラーを生成を考え出すことができる、と私はローカルエコーブロックせずにコードを実行すると、それだけで正常に動作します:

それはDebianシステムで生成エラーです

PTY.spawn(command) {|r,w,pid|} 

どちらの場合でも、コマンド自体は正常に実行されますが、debian linuxがptyをeofに送信していないようです。 ruby-doc上のPTYとIOのドキュメントページは、ここでは援助していないようです。

提案がありますか?ありがとう。

-vox-

+0

これはまあまあですが、Debianのrubyバージョンに正しく読み込まれたreadlinesですか?それが問題で、rvmを使用している場合は、問題のノートを参考にしてください:[http://beginrescueend.com/packages/readline/](http://beginrescueend.com/packages/readline/) – forforf

+0

Thats良い考え。私はこれらのサーバーでrvmを使用していませんが、ソース(および別のサーバー1.9.2)からruby1.9.3をコンパイルしました。私はreadlineのlibを変更することでそれを並べ替えるかもしれないと考えていませんでした。提案していただきありがとうございます。 – voxobscuro

+0

libreadlineは、コマンドラインの編集、履歴など(irbなど)に関連しています。 IO#readlineメソッドには影響しません。 libreadlineをサポートせずにRubyをコンパイルすると、IOは期待どおりに動作します(irbは使用するのが面倒です)。 –

答えて

15

私はここで何が起こっているのか本当に満足するためにPTYライブラリのCソースを読んでいなければなりませんでした。

Ruby PTYの担当者は、コメントin the source codeが何を言っているかは実際には言いません。

私の解決方法は、ラッパーメソッドをまとめて、必要に応じてスクリプトから呼び出すことでした。これはPTY.spawnと基本的に同じに使用されている

# file: lib/safe_pty.rb 

require 'pty' 
module SafePty 
    def self.spawn command, &block 

    PTY.spawn(command) do |r,w,p| 
     begin 
     yield r,w,p 
     rescue Errno::EIO 
     ensure 
     Process.wait p 
     end 
    end 

    $?.exitstatus 
    end 
end 

require 'safe_pty' 
exit_status = SafePty.spawn(command) do |r,w,pid| 
    until r.eof? do 
    logger.debug r.readline 
    end 
end 

#test exit_status for zeroness 
私も $?から必ず出ると終了ステータスのアクセスのためにプロセスを待っている方法に箱詰めしました

ruby​​-docで完全に文書化されていないので、これが有効な応答であることを知るために少し不満を感じました。

+0

興味深い。 srcを参照すると、pty_openのコメントで「ptyスレーブが閉じているときの読み取り操作の結果はプラットフォームに依存します」というコメントが表示されました。それは実際にはrdocにもありますが、私はそれを逃しました。 –

+0

@RichDrummondはい、私が話していたコメントです。私もrdocでそれを逃したが、それは.spawnのためのノートを見ていて、本当に他のものではなかったからだ。 : - / – voxobscuro

5

この関数はerrno :: EIOが、ここで提起されるために、あなたがそれを期待し、それをキャッチする必要がありますので、(それは単に子プロセスが終了し、ストリームを閉じたことを意味します)有効なようです。例えば

Continuously read from STDOUT of external process in Rubyで選択された解答を見るとhttp://www.shanison.com/2010/09/11/ptychildexited-exception-and-ptys-exit-status/

ところで、私はいくつかのテストをしました。 Ubuntu 10.04のRuby 1.8.7では、エラーは発生しません。 Ruby 1.9.3では、私はそうです。 Ubuntu上でJRuby 1.6.4を1.8と1.9の両方のモードで使用しても、エラーは発生しません。 OS Xでは、1.8.7,1.9.2、1.9.3でエラーは発生しません。この動作は明らかにあなたのRubyのバージョンとプラットフォームに依存しています。

+0

私が話していたことを考えていた唯一の人であることで、バウンティが授与されました!あなたがこれを投稿する前に約15分前にCソースの解決策を発見しなかったなら、それは私にとってそれがとにかく導かれたと確信しています。乾杯! – voxobscuro

関連する問題