程序管理和 pkill
我一直在研究使用 shell 腳本的流程管理,我開始意識到確保它正確完成是多麼困難。
例如,您可以將一個程序的PID記錄到一個文件中,並在該文件
wait
上,並在程序退出後清理該PID文件。例如,如果你想從一個初始化腳本中嘗試
kill
這個守護程序,你可能會考慮做這樣的事情: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。在第 2 步發生之前,是否有可能nrpe
’ 的程序可能會死亡,而另一個程序可能會在其位置產生?
您懷疑存在(小!)原子性問題是正確的。
無論您使用什麼方法,無論是系統標準實用程序,例如
start-stop-daemon
,滾動您自己的 PID 文件,pkill
用於通過使用者 ID、可執行二進製文件或其他方式查詢和殺死,在查找哪個程序之間總是有一個間隔您想殺死並將該程序ID提供給kill
系統呼叫以向其發送信號。基本上,你不應該擔心它。為了遇到麻煩,以下兩種情況都必鬚髮生:
- 目標程序在您確定其程序 ID 和您實際殺死它的時間之間死亡。
- 新創建的程序的程序 ID 必須在同一時間間隔內碰巧循環以重用剛剛騰出的程序 ID。
這真的不太可能。
請注意,在您正在研究的特定情況下,您實際上確實有一種方法可以保護自己免受這種情況的影響。使用者執行的唯一程序是 NRPE 本身,因此如果您在發出命令之前
nrpe
切換到nrpe
使用者(可能來自,可能) ,在極不可能的情況下,您可能會嘗試殺死屬於其他東西的可憐的無辜程序,但您不會沒有權限這樣做,它不會有任何影響。root``kill