检查一个 php 进程是不是已经在运行

Posted

技术标签:

【中文标题】检查一个 php 进程是不是已经在运行【英文标题】:Checking if a php process is already running检查一个 php 进程是否已经在运行 【发布时间】:2011-02-12 11:36:06 【问题描述】:

我正在尝试使用临时文件 demo.lock 检查进程是否已在运行:

demo.php:

<?php
    $active=file_exists('demo.lock');
    if ($active)
    
        echo 'process already running';
    
    else
    
        file_put_contents ('demo.lock', 'demo');
        sleep(10);  //do some job
        unlink ('demo.lock');
        echo 'job done';
    
?>

但是它似乎不起作用:如果我打开 demo.php 两次它总是显示“工作完成”,也许是因为它认为它是同一个过程?有什么办法吗?我也尝试使用 getmypid() 得到类似的结果。

谢谢

【问题讨论】:

我建议你使用一个命名的互斥体来做这样的事情,但我不知道这些是否在 php 中可用.. 另外,你的操作系统是什么? 我在windows和linux机器上都试过了,结果一样 【参考方案1】:

为我工作。

确保脚本可以在目录中创建文件。取消注释“unlink”行并运行脚本并检查目录中是否存在锁定文件。如果你没有看到,那就是目录权限问题。

【讨论】:

对我来说似乎很奇怪,它也不起作用。但是,如果权限错误,PHP 应该发送警告。 您是否尝试过评论“取消链接”行? (抱歉,这是@Borgtex)@zneak 也许他没有看到警告/错误... 权限正确,一次运行,文件被创建然后删除,这似乎没有任何问题。问题是,当我在浏览器中运行此文件时,假设在另一个选项卡中再次调用它 5 秒后,第二个实例,而不是显示警告消息(因为第一个已经在运行并且文件已经创建) 再次执行整个过程。如果我创建一个名为 demo2.php 的精确副本并一个接一个地运行,它会按预期工作; demo 等待 10 秒,demo2 立即显示警告 从两个不同的浏览器运行时它也可以工作,也许我应该尝试重定向到另一个页面并让进程在服务器中运行 ignore_user_abort(true); 啊,可能是您的浏览器限制了对 url 的请求数。为什么不使用计时器对两个请求进行计时 - 如果它们都在 10 秒左右,那么我们仍然会遇到问题,但如果第二个请求大约需要 20 秒,那么您需要调查您的浏览器并增加与网络相关的浏览器设置之一连接(如果有的话)。【参考方案2】:

假设一个“正常、简单”的环境,不能确定你的具体情况有什么问题,因为它对我有用,但至少你的代码中有竞争条件。如果您同时启动两个进程,并且都发现 demo.lock 不存在怎么办?

您可以使用fopenx 模式来防止这种情况发生。 X模式尝试创建文件;如果它已经存在,它会失败并生成一个E_WARNING 错误(因此是闭嘴操作员)。由于文件系统操作在驱动器上是原子操作,因此可以保证一次只有一个进程可以保存文件。

<?php

$file = @fopen("demo.lock", "x");
if($file === false)

    echo "Unable to acquire lock; either this process is already running, or permissions are insufficient to create the required file\n";
    exit;


fclose($file); // the fopen call created the file already
sleep(10); // do some job
unlink("demo.lock");
echo "Job's done!\n";

?>

我在这里测试过,它似乎可以工作。

【讨论】:

感谢您的建议,我知道使用 fopen 如何为检查增加另一层安全性。但是,我仍然有同样的问题;这就像第二个实例等待第一个实例结束并删除文件以再次创建它 @Borgtex:那么你的问题胜过我。我不明白为什么它会失败。 :/ 好吧,至少我希望我有用。【参考方案3】:

好吧,发送一些标题和刷新似乎对我有用(不知道为什么),所以现在当我加载页面时显示“开始”并且如果我在完成该过程之前点击浏览器上的刷新按钮,警告消息:

<?php

$file = @fopen("demo.lock", "x");
if($file === false)

    echo "Unable to acquire lock; either this process is already running, or permissions are insufficient to create the required file\n";
    exit;


header("HTTP/1.0 200 OK");
ob_start();
echo "Starting";
header('Content-Length: '.ob_get_length(),true);
ob_end_flush();
flush();

fclose($file); // the fopen call created the file already
sleep(10); // do some job
unlink("demo.lock");    
?>

感谢到目前为止所有的答案和建议

【讨论】:

以上是关于检查一个 php 进程是不是已经在运行的主要内容,如果未能解决你的问题,请参考以下文章

有没有办法检查子进程是不是仍在运行?

检查和运行进程的php代码

如何使用 C++ 检查进程是不是正在运行

如何检查一个进程是不是在 docker 容器内运行?

如何检查正在运行的进程是不是是后台进程? [关闭]

php停止已经运行的脚本进程