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 "你好,世界!\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;
}
?>