私は同時に実行される一連のサブプロセス「スレーブ」を管理するプログラム「マスター」を見ています。サブプロセスは必要に応じて開始および終了します。これらのサブプロセスの多くは起動スクリプトを使用します。
出力はpstree
次のとおりです(抜粋、マスターはJavaで実装され、2つのスレーブはスクリプトを介して開始されます)。
systemd───java─┬─sh───slave
├─slave
└─sh───slave
以前は、起動スクリプトがサイトの出力をログファイルにリダイレクトしていました。マスターデバイスがスレーブデバイスの出力も処理する必要があるかどうかを決定します。次のようにバッファリングされたリーダーを追加してマスター実装を拡張します。
process = Runtime.getRuntime().exec(cmd);
BufferedReader br = new BufferedReader(new InputStreamReader(process.getInputStream()));
while (null != (line = br.readLine())) {
// handle slave output here
}
その後、システムはSIGTERM
マスターによってシャットダウン(転送)されましたが、実際にはまだ実行中のスレーブに深刻な問題がありました。私はこのようなことが起こったことに気づきました。ただ2つの基準を満たすスレーブの場合:
- 彼らは起動スクリプトを使用しました
- 標準出力に書き込む場合はほとんどありません。
マスターがスレーブを殺さず、スレーブの直系親(シェルソルバー)だけを殺したので、今スレーブはinitの所有になります。私の場合、systemdがデフォルトのようです死神。pstree
次のようになります。
systemd─┬─java───sh───slave
└─slave
機能的には明示的に問題を解決しました。奴隷の家族全体を殺す。しかし、私はまだ知りたいです:
systemdがstdout(またはエラー)に書き込み、以前に他のプロセスからstdoutを読み込んだときに孤立プロセスのみを終了するのはなぜですか?
この質問は実際にはかなり長いです。要求に応じて説明された動作を再現するための最小限のコード例を提供できます。
答え1
systemdではこれを行うことはできません。
対照的に、プロセスが読み取り側で閉じたパイプに書き込もうとすると、SIGPIPEによってプロセスが終了します。これは、「標準出力が以前に別のプロセスによって読み取られた」という説明と一致しています。