Kevin Trass 在注释中提到的锁文件机制是错误的,因为它容易受到竞争条件的影响。
对于锁,您需要一种原子方法来验证锁文件是否存在,如果不存在则创建它。在 `file_exists` 和 `file_put_contents` 之间,另一个进程可能比我们更快地写入锁。
我所知道的唯一匹配上述要求的文件系统操作是 `symlink()`。
因此,如果您需要锁文件机制,请使用以下代码。这在没有 `/proc` 的系统上不起作用(因此,Windows、BSD、OS X 以及可能的其他系统无法使用),但可以调整以解决此缺陷(例如,通过像我的脚本中一样链接到您的 pid 文件,然后通过符号链接像 Kevin 的解决方案中那样操作)。
#!/usr/bin/php
<?php
define('LOCK_FILE', "/var/run/" . basename($argv[0], ".php") . ".lock");
if (!tryLock())
die("Already running.\n");
# 退出时删除锁(Control+C 不算作“退出”?)
register_shutdown_function('unlink', LOCK_FILE);
# 您的脚本的其余部分位于此处....
echo "Hello world!\n";
sleep(30);
exit(0);
function tryLock()
{
# 如果锁文件存在,检查是否已过期。如果存在且没有过期,则返回 TRUE
# 否则,创建锁文件并返回 FALSE。
if (@symlink("/proc/" . getmypid(), LOCK_FILE) !== FALSE) # 'symlink' 前面的 @ 用于抑制如果 LOCK_FILE 存在时收到的 NOTICE
return true;
# 链接已存在
# 检查它是否已过期
if (is_link(LOCK_FILE) && !is_dir(LOCK_FILE))
{
unlink(LOCK_FILE);
# 尝试再次锁定
return tryLock();
}
return false;
}
?>