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("已经在运行。\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 存在时出现的通知
return true;
# 链接已存在
# 检查是否过期
if (is_link(LOCK_FILE) && !is_dir(LOCK_FILE))
{
unlink(LOCK_FILE);
# 再次尝试锁定
return tryLock();
}
return false;
}
?>