5

我有一个要执行的 php 脚本,前提是该脚本的其他实例尚未运行。我有这个代码:

$lockfile = __DIR__.'/lock.file';

if(file_exists($lockfile) == false)
{
    echo 'no lockfile. Job will execute.';
    $handle = fopen($lockfile, 'x') or die('Cannot open file:  '.$lockfile);
    $data = 'This is the lockfile';
    fwrite($handle, $data);
    fclose($lockfile);

    createLinks();

    unlink($lockfile);
}
else
{
    echo 'Lockfile present, job will not execute. Please try again later';
}

但它不能正确检查文件是否存在。如果我用浏览器调用脚本,lock.file 会正确创建(我可以用 ftp 看到它),然后删除。但是,我仍然可以同时多次运行该脚本。如果我自己用 ftp 创建一个 lock.file,它不会执行脚本。我已经搜索了几个小时了,会是什么?也许我很愚蠢,但我认为这应该可行,对吧?

编辑:杰普,羊群做到了。非常感谢!最终代码:

$lockfile = __DIR__.'/lock.file';
$handle = fopen($lockfile, "x");

if(flock($handle, LOCK_EX))
{
    echo 'no lockfile. Job will execute.';

    $data = 'This is the lockfile';
    fwrite($handle, $data);

    createLinks();

    fclose($lockfile);  
    unlink($lockfile);
}
else
{
    echo 'Lockfile present, job will not execute. Please try again later';
}
4

3 回答 3

4

从以下文档file_exists

注意:此函数的结果被缓存。有关详细信息,请参阅 clearstatcache()。

和:

您还应该注意,PHP 不会缓存有关不存在文件的信息。因此,如果您对不存在的文件调用 file_exists(),它将返回 FALSE,直到您创建该文件。如果您创建该文件,即使您随后删除该文件,它也会返回 TRUE。但是 unlink() 会自动清除缓存

尝试将您的功能更改为:

if(file_exists($lockfile) == false)
{
    clearstatcache();
    ...

看看clearstatcache()

于 2013-03-03T18:27:55.130 回答
1

我今天已经花了半天时间来处理与您的问题几乎相同的问题。我的 PHP 代码也使用了文件锁,并在其中调用了 file_exists()。我在“奇怪的” file_exists() 结果中遇到了同样的问题。当我将文件的使用(以获得锁)更改为数据库的使用时,我完全感到困惑——锁对应于表中的一行。结果完全一样——我尝试在浏览器的不同选项卡中同时启动代码,但我仍然未能获得锁定。

然后我意识到这种奇怪行为的真正原因是什么。在我的情况下(看起来你的情况是一样的),主要问题在于脚本是在一个浏览器中“同时多次”启动的。但是请求不是同时处理的,而是顺序处理的。这里给出了对这种效果的一个很好的解释: https ://stackoverflow.com/a/3623584/1758680

因此,随着所有请求按顺序排列 - 每个请求都在等待前一个请求结束。每个锁在下一个脚本开始并尝试获取锁之前被释放。

于 2013-08-05T17:14:43.463 回答
-1

尝试

$lockfile = 'lock.file';

或其他..

于 2013-03-03T18:28:43.030 回答