使用互斥锁进行Linux并发脚本编写

时间:2012-11-07 11:03:23

标签: php linux shell concurrency

在我的Linux服务器上,我需要同步多个脚本,用BASH和PHP编写,这样只有其中一个能够启动一个系统关键的工作,这是一系列BASH / PHP命令,会弄乱如果由两个或多个脚本同时执行的话。根据我在C ++中使用多线程的经验,我熟悉互斥的概念,但是如何为在一系列不同进程中运行的脚本实现互斥,当然,不是用C ++编写的?

嗯,首先想到的解决方案是确保每个脚本最初创建一个“锁定标志”文件,让其他脚本知道该作业被“锁定”,然后在文件完成后删除该文件。工作。但是,正如我所看到的那样,编写读取操作的文件必须是完全原子才能让这种方法以100%的概率运行,同样的要求也是如此适用于任何其他同步方法。而且我很确定文件写入/读取操作不是原子的,它们至少在所有现有的Linux / Unix系统中都不是原子的。

那么同步并发BASH PHP脚本的最灵活,最可靠的方法是什么?

3 个答案:

答案 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
}