私は初期化スクリプトとメインサービスがデーモンとして実行される非常に複雑なアプリケーションを持っています。すばやくエレガントに停止したいので、stop()関数に次のように使用しました。
group_id=$(ps -o pgid= $(cat $pidfile))
if [ ! -z $group_id ]; then
kill -- -$group_id
success
fi
すべての子プロセス/スレッドに終了信号を送信します。しかし、そのうちのいくつかが新しい子プロセスを作成した場合はどうなりますか?これらの新しいサブプロセスが正しく機能していないようですが、これが必要です。親デーモンに終了シグナルを送信すると、すべての子プロセスが操作を正常に完了しますが、シェルではサービスが停止したとマークされます(前の項目を確認してください)。すべての子プロセスが停止した場合にのみ、initスクリプトに「OK」を印刷させるにはどうすればよいですか?)おそらく非常に明確なものを見逃しているようですが、最小限の努力でこの問題を解決する方法はまだわかりません。少なくともいくつかのアイデアを提供してください。
答え1
プロセスグループIDによる終了は原子性である。単に間違った時間に分岐しても、プロセスが逃げることはできません。この目的のためにkill
、fork
およびsetpgid
を順次実行されるアトミックタスクと考えることができます。プロセスが実行中の場合、子プロセスは後で実行されるとif (!fork()) setpgid()
終了します。kill
fork
setpgid
これらの新しいサブプロセスが正しく機能していないようです。
すべてのサブプロセスが信号を受信します。これがプロセスグループのすべてです。
親デーモンに終了シグナルを送信すると、すべての子プロセスは操作を正常に完了しますが、シェルではサービスが停止したとマークされます。
これは予想されます。プロセスが終了する前に実際にkill
スクリプトに戻ります。ターゲットプロセスが現在信号をブロックしている可能性があります。マルチプロセッサシステムでは、シャットダウンされたプロセスがkill -9
返された後にいくつかのタスクが実行されることがわかります。
シェルスクリプトは、基本プロセスが終了したかどうかを確認すると、基本プロセスが終了したことを示します。プロセスまたはプロセスグループリーダーの親プロセスに加えて、プロセスまたはプロセスグループが終了するのを待つ方法はありません。基本プロセスの開始時に何も設定しないと、プロセスグループ内のすべてのプロセスが終了したことを確認する便利な方法はありません。
そのような状況を処理する一般的な方法は次のとおりです。コントロールパネル終了完了を報告し、終了する前に完全に終了するコマンドです(子プロセスによって実行されたすべてのジョブ処理を含む)。 Apache HTTPDを例に挙げましょう。
または、事前に準備してプロセスツリーを計測することもできます。バラより最後のバックグラウンドアプリケーションのPIDを取得する方法