偵測程式是否有其他副本正在執行(*NIX 特定)
一個巧妙的技巧,用於查看是否有其他進程正在執行,是向其發送信號 0。信號 0 實際上並未發送,但 kill 會檢查是否可以發送信號。請注意,這僅在您有權向該進程發送信號時才有效。
此技術的實際用途是避免執行同一程式的多個副本。您可以用通常的方式將 PID 保存到檔案中...然後在啟動期間,您檢查 PID 檔案的值,看看該進程目前是否存在。
這並非完全萬無一失。在極少數情況下,不相關的程式可能會使用相同的回收 PID。但該程式很可能不會接受來自您程式的信號(除非您的程式是 root 使用者)。
為了使其盡可能可靠,您需要讓您的程式在關閉期間移除其 PID 檔案(請參閱 register_shutdown_function)。這樣,只有在您的程式崩潰*並且*另一個程式碰巧使用相同的 PID*並且*另一個程式願意接受來自您程式的信號時,您才會得到錯誤的結果。這將是一個極其罕見的情況。這也假設 PID 檔案沒有被篡改(就像所有依賴 PID 檔案的程式一樣...)。
也可以使用 'ps x' 來偵測,但使用 kill 效率更高。
以下是核心程式碼
$PrevPid = file_get_contents($PathToPidFile);
if(($PrevPid !== FALSE) && posix_kill(rtrim($PrevPid),0)) {
echo "錯誤:伺服器已在執行,PID 為:$PrevPid\n";
exit(-99);
} else {
echo "正在啟動伺服器...";
}
嗯...如果您想要完全 100% 的可靠性,加上效率。您可以做的就是使用 kill 進行初始檢查。如果它顯示未執行,那麼您就可以開始了。但如果 kill 顯示已在執行,那麼您可以使用
//您可以從 $argv[0] 取得 $ProgramName
$Result = shell_exec('ps x | grep "' . $PrevPid . '" | grep "' . $ProgramName . '" | grep -v "grep"');
假設您的程式有權限執行此操作。如果您執行該命令並返回空字串,則另一個程式是使用回收 PID 的冒名頂替者,您可以繼續操作。
-- Erik