我已经看到很多示例,其中使用“锁定”文件来跟踪当前是否正在运行PHP脚本。
示例:
这样,如果长时间运行的脚本启动了两次,则仅第一个实例将运行。哪个很棒。
但是,这似乎是错误的解决方法。为什么我们不只是检查该进程是否已经在运行?
if(exec("ps -C " . basename(__FILE__) . " --no-headers | wc -l") > 1){
echo "Already running.";
exit;
}
此方法是否有潜在的陷阱?为什么我经常看到“锁定”文件的解决方法?用我们正在寻找的名称来计数进程绝对似乎更准确。
答案 0 :(得分:2)
根据这里的评论和我自己的观察,我组成了两种方法的优缺点列表:
flock
方法:优点:
exec()
,也可以正常工作缺点:
/tmp
目录中,则这是一种有效的方法,因为该目录中的所有内容都应该是“临时的” exec("ps -C...")
方法优点:
缺点:
编辑:我最终使用了这个
if (exec("pgrep -x " . $scriptName . " -u ". $currentUser . " | wc -l") > 1)
{
echo $scriptName . " is already running.\n";
exit;
}
...因为ps
不允许您除了进程名称之外还对进程的所有者进行筛选,并且我希望允许该脚本在其他用户运行时多次运行
编辑2:
...因此,在运行了几天之后,它也不是完美的。不知何故,该过程在同一计算机上在同一用户下多次启动。我唯一的猜测是,某个问题(内存不足等)导致pgrep
在应该返回某些内容时什么也不返回。
因此,这意味着flock
方法和计数过程方法都不是100%可靠的。您必须确定哪种方法更适合您的项目。
最终,我正在使用另一种解决方案,将当前任务的PID存储在“锁定”文件中,该文件实际上并未被flock锁定。然后,当脚本启动时,检查锁定文件是否存在,如果存在,则获取内容(脚本最后一次启动的PID),然后,通过比较{{1},检查其是否仍在运行。 }内容以及正在运行的脚本的名称。
答案 1 :(得分:0)
首先,命令不正确。当我运行php test.php
和命令
ps -C test.php
一无所获。您可以使用ps -aux|grep 'test.php' -c
来获取进程号。但是exec("ps -aux|grep 'php test.php' -c");
的返回号必须减去2为真实进程号
使用锁定文件的原因主要是exec或其他命令功能需要一些特殊权限,并且是php.ini默认配置中的disable_functions。
测试脚本如下:
$count = exec("ps -aux|grep 'php test.php' -c");
if($count > 3){
echo "Already running.".$count;
exit;
}
while(1){
sleep(20);
}
答案 2 :(得分:0)
使用“锁定文件”的主要原因仅仅是因为可以预期它们在任何主机环境中都可以工作。如果您可以“创建文件”,并且可以“锁定文件”,则此类代码将在任何地方都可以使用。
还–“没有什么可以通过'聪明'获得的。”众所周知,这种众所周知的策略很好用,因此,“顺其自然。”
答案 3 :(得分:0)
使用锁文件的最重要原因,遗憾的是没有在其他答案中给出,是锁文件使用原子锁机制,允许您运行多个实例脚本,处于比脚本本身更高级别的上下文中,并且更安全。
遍历进程列表本质上容易出现竞争条件;在检索和迭代列表所需的时间内,可能刚刚产生了第二个进程,而您无意中得到了多个进程。
文件锁定机制是严格原子的。只有一个进程可以获得文件的排他锁,所以当它有锁时,同一个命令不可能运行两次。
假设您想要运行多个单独的脚本实例,但每个实例都有自己的范围/选项。如果您只是计算脚本在 ps 输出中出现的次数,您将只能运行一个实例。通过使用单独的锁定文件,您可以在单个范围内正确锁定其运行状态。
锁定文件只是一种更加优雅和安全的设计。与其滥用进程列表(它需要更多的权限,并且必须在每个操作系统上以不同的方式访问和解析)来推断脚本是否已经在运行,您可以使用一个专用系统来明确锁定状态。
所以重申锁定文件优于其他方法的所有原因:
至于其他答案中提到的缺点;锁定文件可以被删除,有时锁定被转移到另一个进程:
通过设置适当的权限并将文件存储在非易失性存储中,可以防止删除锁定文件。与进程列表不同,如果根据规范使用锁定文件是“确定的”。
分叉子进程的进程确实会“遗赠”它对任何仍在运行的子进程的锁定,但是一旦脚本完成,通过专门解锁文件很容易补救。例如。使用 flock --unlock
。
长话短说:您应该始终使用锁定文件而不是解析正在运行的进程。
还有其他解决方案,但除非您有其他要求,否则它们通常不会比简单的文件锁提供任何好处: