【问题标题】:Exclusive and shared locks in bashbash 中的独占锁和共享锁
【发布时间】:2015-04-16 06:30:42
【问题描述】:

我正在尝试使用 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 的用法

谢谢

【问题讨论】:

    标签: bash unix flock


    【解决方案1】:

    让我们从200&gt;"$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 中(如果有的话,之前的内容已被删除)。这是因为我们使用&gt;&amp;200ls 的标准输出重定向到文件描述符200/dev/fd/200,然后将其重定向到文件lock.log

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

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

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

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

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

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

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

    【讨论】:

    • 非常感谢您的详尽回答!它确实向我解释了很多关于文件锁定的事情。另外,您能否告诉我进程如何在完成写入文件时发出通知?共享锁独占,如何知道文件内容的哪一部分被添加了? (假设我们在末尾追加)
    • @Mark 我不太明白你的问题。 flock 使用系统调用flock()(参见man 2 flock)对文件应用锁定。我不知道内核在执行这样的调用时真正做了什么——但在我们的层面上它是无关紧要的。当进程完成写入文件时,没有通知(在这个级别,据我所知)(当然,除非查询阻塞锁,但这不是你的情况,因为你使用的是@987654361 @ 转变)。所有这些都是在内核级别完成的,并不是我们真正关心的级别。
    • @Mark 我想最好准确地告诉您您要做什么(如果可以以非常简洁的方式完成,可以通过编辑问题),或者提出一个新问题(这将引用这个)如果您的任务涉及更多。
    猜你喜欢
    • 2012-08-03
    • 2014-10-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多