2011-11-14 6 views
1

私は、何らかの形のredhat OSを持つLinuxボックスで16時間または20時間実行できるプログラムを書いています。 nohupで起動するか出力をファイルにリダイレクトするとうまくいきますが、ユーザが起動してバックグラウンドに送信してログアウトすると、単純なステータスメッセージを送信しようとすると失敗します。ファイルが作成されたファイルの数)。ストリームがもはや有効ではないため、例外がスローされます。セッションがなくなったときにstd :: errorまたはstd :: outに書き込むときを除いて、ルビはなぜですか?

は、それが私のために働いた、なぜ私たちは実現ではなく、彼のために、私はいくつかのテストを実行し、そしてルビーは、Python、バッシュとPerlと比較すると、この動作で一意であることを発見したら。

良い理由は、ルビーは、このような状況で他のスクリプト言語とは異なる挙動することがありますか?それは残りのように動作するように変更する方法はありますか?

私は、エンドユーザーが自分の出力見ることができればC++(およびC)は気にしないメッセージを-が、私はそれらの言語のためのテストを書いていないことをかなり確信しています。あなたがログアウトすると、バックグラウンドに送られたジョブがなくなっていないことが分かりました。だから、私は確かに過去にこの行動をテストしたことはありません。

+0

例外はありますか? – shingara

+0

ええ、私はそれを書きませんでしたが、私が知っていたのは、例外がスローされたということでした。これはRubyでのみ発生します。その他のテストは例外ではありません。 – user632657

答えて

0

バックグラウンドに行くと、stdoutに書き込むすべてのプログラムのすべてのプログラムがエラーコードを取得するはずです。 Cの場合、あなたは無視するかもしれない戻り値を得るでしょう。他の言語では、本当に唯一ルビーが例外をスローした場合、私は本当に驚くでしょう。結局のところ、これはOSの作り方、問題はカーネルにあります。私はperlで1つのデーモンを書きました。私はstdout、stderrとstdinのクローズとnohupなしで殺されないように二重フォークを実装しなければならないと確信しています。あなたは文書化されていない機能に頼るべきではなく、あなたのためにそれを行うためにnohupに依存するか、入力と出力の記述子を適切に閉じるべきです。または、低レベルのオープンコールを使用してログファイルに再度開きます。

他の言語のスクリプトとの間でリダイレクトを試したことはありますか?壊れたパイプは通常、program1 | program2匿名パイプは、その一方の端が閉じており、他方のパイプはその端から読み書きを要求します。

+0

いくつかの言語では、言語でエラーが発生しないことが確認されています: – user632657

+0

#!/ bin/bash; sleep 60; エコー "OK"; touch jflkdfakl#これをバックグラウンドに送信してログアウトすると、ファイルが作成されます。この同じ振る舞いは、pythonとperlでも見ることができます。しかしRubyは例外を発生させます。 - それは最初の4つのスペースを無視しています... – user632657

0

ログアウトすると、あなたの$の標準エラー出力と$ STDOUTの受信機であるプロセスが殺されます。あなたの$ stderrと$ stdoutファイル記述子は、壊れたパイプに接続されます。それらに書き込むときは、オペレーティングシステムからSIGPIPEを取得する必要があります。

C++とCが気にしないのは間違っています。これは、実装言語とは関係なく、「ユーザー」が出力を「見る」ことができるかどうかで決まります。それはファイル記述子がまだ有効かどうかについてです。もう一方の端は閉じているので、それ以上はありません。

CまたはC++で書かれたデーモンを見てください。 fork後とexecの前に、子プロセスでstderrとstdoutをどのように閉じるかに注目してください。これは、破損したパイプへの書き込みや、オペレーティングシステムによってSIGPIPEが送信されるのを防ぐ方法です。

+0

私は少しC + +のテストを書いた。それは私のpythonスクリプトと同じように動作します。私はそれをstdに書いています:: 10秒ごとにN回、またファイルにエコーします。バックグラウンドに送信してログアウトすると、プログラムはエラーなしで完了します。Rubyは、ユーザがセッションを終了した後にstd :: outへの最初の書き込みを停止します(ただし、プロセスがstd :: out/errへの書き込みを試みたことがなければ、完了まで実行を継続します)。 – user632657

+0

私の推測では、あなたのサンプルプログラムで使用しているIO実装が、あなたが壊れたパイプ上のwrite(2)からあなたを守っているということです。 – sheldonh

+0

デーモンは特別なケースです。実際にはデーモンではありません。これは数時間実行する必要のある通常のプログラムですが、クラスターはさまざまな理由で時々セッションを終了しますので、セッションがなくなると、ルビ以外の言語プログラムはエラーなく完了しますが、ルビでは、セッションが失われて例外がスローされます。 – user632657

関連する問題