bash中的独占和共享锁

时间:2015-02-15 18:40:54

标签: bash unix flock

我正在尝试使用bash锁定文件,而我已设法这样做,但我不确定我是否正确地执行此操作。

下面的代码应该尝试写入lock.log文件,如果失败则应退出退出状态-1。如果它可以锁定文件,那么它应该打印订单号,解锁文件,然后退出。

#!/bin/bash

function myfunc {
    (
        flock -e -n 200 || { echo "$1 - can't reach"; exit -1; }
        echo $1 >> $2 #critical
        sleep 2
        flock -u 200
    ) 200>$2 #critical
    echo "$1 -> end."
    exit 0
}

lock="lock.log"
for ((i=0; i < 10; i++)); do
    myfunc $i $lock &
done

exit 0

我无法理解为什么它会在标准输出上打印而且标记为关键的2行对我来说不太清楚,所以我请求一些解释,也许是为了更好的例子。

可能存在一些类似的问题,但没有一个问题与我提出的基本问题有关 - flock的使用

谢谢

1 个答案:

答案 0 :(得分:2)

让我们从200>"$2"部分开始:

当调用myfunc时,Bash会看到:

(
    ... stuff irrelevant for now ...
) 200>"$2"

因此它打开文件描述符号200并将其重定向到通过扩展$2获得的文件。在你的情况下,它就像:

(
    ... stuff irrelevant for now ...
) 200>lock.log

顺便说一下,文件lock.log此时已打开并被截断(即,其内容(如果有的话)被清除)。

要查看此内容,请尝试以下操作:

( ls /dev/fd ) 200>lock.log

你会看到那里有一个名为200的“文件”(此时,请使用包含某些内容的lock.log文件进行尝试,之后您会看到它内容消失了)但与

比较
ls /dev/fd

您很可能只看到0123。为了好玩,试试:

( ls /dev/fd >&200 ) 200>lock.log

这次终端屏幕上没有显示任何内容,但您会看到ls的内容位于文件lock.log中(包含之前的内容,如果有的话,已删除)。这是因为我们使用>&200ls的标准输出重定向到200的文件描述符/dev/fd/200,然后将其重定向到文件lock.log

我想这解释了其中一条关键行。

现在子shell内发生了什么?我不是flock专家,所以请耐心等待。

使用参数200,您告诉flock使用文件描述符200(即“文件”/dev/fd/200)作为锁定文件。当您致电flock 200时,flock会尝试暂停该文件。如果它可以,一切都很好,它会抓住它,否则它会失败(如果给出-n选项,这是你的情况)或等到其他人让文件进入。

如果失败,您将输出无法到达消息到标准输出并退出子shell,然后您正在执行其余部分功能(即消息 end )。现在,如果成功,你echo传递给函数的第一个参数(这里是一个数字),你将它重定向到文件lock.log。这是否解释了第二个关键行?

在此脚本的末尾,您会看到文件lock.log为空。那是因为第一次调用myfunc成功,但所有后续调用都会截断文件lock.log(和你一起响铃?)。如果你想在lock.log中看到一些内容,要么只调用你的函数一次(以便后续调用没有截断文件),要么以追加模式打开文件:

(
    ... the flock stuff ...
) 200>>"$2" # notice the >> instead of >

就像这样你会看到成功的第一个锁(不一定是数字0,因为有竞争条件)。