私はプロセス管理のためにシェルスクリプトを使用する方法を調べてきました。
たとえば、プログラムのPIDをファイルに書き込み、一番wait
上に置き、プログラムが終了した後にPIDファイルをクリーンアップできます。
kill
たとえば、initスクリプトでこのデーモンを使用したい場合は、次のことを検討してください。
do_stop() {
kill $(</var/run/program.pid)
}
これは明らかに動作しません。 PIDを取得して終了信号を送信する間に、他のプロセスが終了し、その場に代わった可能性がある。
正しいアプローチは、プログラムの親プログラムでIPCを使用してサブプログラムに終了信号を送信するようです。これにより、そのプロセスのPIDが他のプロセスで再利用されなくなります。
私はできるだけ正確な私自身の初期化スクリプトを書こうとしました。この文脈で、私はNRPEに関する記事を書いてきました。残念ながら、NRPEはデーモン化されており、initとの接続が失われており、wait
使用できません。代わりに、私は次の解決策を思いついた。
do_stop() {
echo "Stopping (sending SIGTERM to) nrpe"
pkill -u nrpe || { echo >&2 "nrpe isn't running"; exit 1; }
}
ユーザーが実行する唯一のプロセスnrpe
はNRPE自体です。これは、システムが私の制御下にあることを考慮すると、比較的合理的な解決策だと思います。
私が気になったのは原子性pkill
(これが正しい言葉なら)です。pkill
次の手順に従うとします。
- プロセス標準パラメータを解析したら、プロセステーブルでPIDを見つけます。
SIGTERM
取得したPIDに転送(デフォルト)
pkill -u nrpe
手順1で与えられたPIDが42であるとします。nrpe
ステップ2が発生する前にプロセスが終了し、その場で別のプロセスを作成できますか?
答え1
(小さい!) 原子性問題があると疑うのが正しい。
どの方法を使用しても、システム標準ユーティリティ(ユーザーIDstart-stop-daemon
で照会および終了するために直接生成されたPIDファイルpkill
、実行可能バイナリ、またはその他の手段)に関係なく、必要な照会プロセスの間には常にスペースがあります。プロセスを終了し、プロセスIDをシステムコールkill
に提供してシグナルを送信します。
基本的には心配しなくても構いません。問題があり、両方以下が発生する必要があります。
- 対象プロセスは、プロセスIDを識別する時刻と実際に終了する時刻との間で終了する。
- 新しく作成されたプロセスのプロセスIDは、空のプロセスIDを再利用するために同じ間隔内で循環する必要があります。
これは本当に可能性が低いです。
あなたが見ている特定の状況では、実際にこの状況から自分を守る方法があることに注意してください。ユーザーが実行する唯一のプロセスはNRPE自体であるため、nrpe
コマンドを実行する前にユーザーに切り替えることはほとんどありませんnrpe
。root
kill
努力する他のものに属するが権限のない貧しい無邪気なプロセスを殺すことは何の効果もありません。