检测另一个程序副本是否正在运行(*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