bash 中的独占锁和共享锁

Exclusive and shared locks in bash

我正在尝试使用 bash 锁定一个文件,我已经设法做到了,但我不确定我的做法是否正确。

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

#!/bin/bash

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

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

exit 0

我不明白为什么它会打印在标准输出上,并且标记为关键的 2 行对我来说不是很清楚,所以我恳请您提供一些解释,也许还有一个更好的例子。

可能会有一些类似的问题,但是 none 我要问的基本问题 - flock

的用法

谢谢

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

myfunc 被调用时 Bash 看到这个:

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

因此它打开文件描述符编号 200 并将其重定向到通过扩展 </code> 获得的文件。在你的情况下,它完全像:</p> <pre><code>( ... 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 中(之前的内容已删除,如果有的话)。这是因为使用 >&200 我们将 ls 的标准输出重定向到文件描述符 200,即 /dev/fd/200,然后再重定向到文件 lock.log

我想这解释了 critical 行之一。

现在 subshel​​l 内部发生了什么?我不是 flock 专家,请耐心等待。

使用参数 200,您告诉 flock 使用文件描述符 200(即“文件”/dev/fd/200)作为锁定文件.当您调用 flock 200 时,flock 会尝试保留该文件。如果可以,一切都很好,它会一直掌握它,否则它要么失败(如果给定 -n 选项,这是你的情况),要么等到其他人放开文件。

万一失败,你输出 can't reach 消息 到标准输出 并退出 subshel​​l,然后您正在执行函数的剩余部分(即消息 end)。现在,如果成功,您将 echo 传递给函数的第一个参数(这里是一个数字)并将其重定向到文件 lock.log。这是否解释了第二个 critical 行?

在此脚本结束时,您会看到文件 lock.log 是空的。那是因为对 myfunc 的第一次调用成功了,但所有后续调用都会截断文件 lock.log(跟你一起响铃?)。如果您想查看 lock.log 中的某些内容,请只调用您的函数一次(以便后续调用不会截断文件),或者以追加模式打开文件:

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

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