在我的Linux服务器上,我需要同步多个脚本,用BASH和PHP编写,这样只有其中一个能够启动一个系统关键的工作,这是一系列BASH / PHP命令,会弄乱如果由两个或多个脚本同时执行的话。根据我在C ++中使用多线程的经验,我熟悉互斥的概念,但是如何为在一系列不同进程中运行的脚本实现互斥,当然,不是用C ++编写的?
嗯,首先想到的解决方案是确保每个脚本最初创建一个“锁定标志”文件,让其他脚本知道该作业被“锁定”,然后在文件完成后删除该文件。工作。但是,正如我所看到的那样,编写和读取操作的文件必须是完全原子才能让这种方法以100%的概率运行,同样的要求也是如此适用于任何其他同步方法。而且我很确定文件写入/读取操作不是原子的,它们至少在所有现有的Linux / Unix系统中都不是原子的。
那么同步并发BASH 和 PHP脚本的最灵活,最可靠的方法是什么?
答案 0 :(得分:2)
我不是PHP程序员,但文档说它提供了可以使用的flock
的可移植版本。第一个示例代码段看起来非常接近您想要的内容。试试这个:
<?php
$fp = fopen("/tmp/lock.txt", "r+");
if (flock($fp, LOCK_EX)) { // acquire an exclusive lock
// Do your critical section here, while you hold the lock
flock($fp, LOCK_UN); // release the lock
} else {
echo "Couldn't get the lock!";
}
fclose($fp);
?>
请注意,默认情况下flock
会等到可以获取锁定。如果您希望在程序的另一个副本已经运行的情况下立即退出,则可以使用LOCK_EX | LOCK_NB
。
使用名称“/tmp/lock.txt”可能是一个安全漏洞(我不想过于认真地决定它是否真的如此)所以你应该选择一个只能写入的目录你的计划。
答案 1 :(得分:1)
您可以使用flock以原子方式锁定您的标记文件。 -e
选项是获取独占锁。
从手册页:
默认情况下,如果无法立即获取锁定,则flock会等待 直到锁定可用。
因此,如果你所有的bash / php脚本都试图独占锁定文件,那么只有一个可以成功获取它,其余部分会等待锁定。
如果您不想等待,请使用-w
暂停。
答案 2 :(得分:0)
fuser - 基于Bash的锁(它保证没有两个进程同时访问受保护的资源,但可能导致负锁定尝试,即使没有进程访问资源,但几乎不可能):
#!/bin/bash
set -eu
function mutex {
local file=$1 pid pids
exec 8>>"$file"
{ pids=$(/sbin/fuser -f "$file"); } 2>&- 9>&-
for pid in $pids; do
[[ $pid = $$ ]] && continue
exec 8>&-
return 1 # locked by other pid
done
}