获取文件的独占读/写锁定以进行原子更新


10

我想要一个用作计数器的文件。用户A将写入并递增该数字,而用户B请求读取文件。用户A是否可以锁定此文件,以便在用户A的写操作完成之前没有人可以对其进行读写?

我已经调查过,flock但似乎无法按我期望的那样工作。

flock -x -w 5 /dev/shm/counter.txt echo "4" >  /dev/shm/counter.txt && sleep 5

如果有一种更合适的方法来获得类似于原子的增量文件,那也将很高兴听到!

我的目标是:

LOCK counter.txt; write to counter.txt;

同时

Read counter.txt; realize it's locked so wait until that lock is finished.

1
“似乎无法使它正常工作。” 具体是什么意思?
John1024

我确定我没有正确使用它,但是在使用上面的代码时,我可以使用两个shell,并让它们都在我认为一个锁住它的同时编辑计数器文件。因此,如果我在两个单独的外壳上运行该行两次(每个外壳都有其自己的编号以回显),我仍然看到第二个编号被写入
d -_- b

1
当第一个完成并释放其锁定时,第二个运行。这不是应该的工作方式吗?(在上面的代码中,在羊群释放锁之后&& sleep 5执行。)
John1024 2013年

嗯,很有趣……在那种情况下,我的肉眼无法捕捉到。大!我的下一个挑战是如何在中放置多个命令flock,但我将其作为一个单独的问题。谢谢约翰!
d -_- b

3
@d -_- b我爱您的用户名。那是我见过的最聪明的用户名。
Devyn Collier Johnson

Answers:


10

Bash对以下命令的处理可能令人惊讶:

flock -x -w 5 /dev/shm/counter.txt echo "4" >  /dev/shm/counter.txt && sleep 5

Bash首先运行,flock -x -w 5 /dev/shm/counter.txt echo "4" > /dev/shm/counter.txt并且如果成功完成(释放锁定),那么它将运行sleep 5。因此,锁定可能不会持续5秒钟。

除了&&&

如果一个有两个命令AB,则:

  1. A & B开始A在后台,然后开始B而无需等待A到结束。

  2. A && B启动A,等待它完成,然后,如果成功完成(退出代码0),则启动B。如果A失败(非零退出代码),则B永远不会运行。

总之,&&&是两个完全不同的列表运算符。


3
如果在中A && BA它将等待B完成,这会让我感到惊讶。
Andras Gyomrey

1
在A && B中,首先执行A。仅当A执行成功并退出时,B才执行。用一个; B到总执行乙不管A的执行状态
kapad

15

文件锁定不是强制性的1-即,您不能锁定文件,以便另一个进程无法访问它。锁定文件意味着,如果(另一个)进程检查该文件是否已被锁定,它将知道。

的目的flock是做这样的东西,你想要什么,但你必须使用flock为每一个尝试访问。请记住,这些正在阻止通话;来自man flock

如果无法立即获取锁,则flock会等待直到锁可用为止


1.如果您将其用于例如安全性方面,这会使该功能显得无用,但这不是文件锁定的目的-它们是用于同步的,这就是您正在执行的操作。Leo用户指出,基于来自其他* nix操作系统的历史数据,Linux内核中可能存在非标准的强制性文件锁定实现(请参阅本讨论)。但是,这似乎只是一个C级接口。


谢谢!这有助于理解“咨询”方面以及flock每次使用方式。非常有帮助!
d -_- b 2013年

2

您可以使用“ sh -c命令...”来运行整个shell命令,包括保持锁定状态的文件重定向。另外,由于您使用文件作为计数器,因此在进行读取和回写操作时需要连续保持锁定。因此,您需要执行以下操作来增加计数器并返回其新值:

flock --exclusive --wait 5 /dev/shm/counter.txt sh -c 'read count < /dev/shm/counter.txt ; echo $((count + 1)) > /dev/shm/counter.txt ; echo $((count + 1))'

将加号更改为减号应减少计数器:

flock --exclusive --wait 5 /dev/shm/counter.txt sh -c 'read count < /dev/shm/counter.txt ; echo $((count - 1)) > /dev/shm/counter.txt ; echo $((count - 1))'

我希望您可以在发生任何争用之前初始化计数器,因此不必担心过早锁定:

echo 0 > /dev/shm/counter.txt

我认为在争用可能发生时,您不需要浪费计数器的值,但是,如果您这样做,则应该这样做:

flock --exclusive --wait 5 /dev/shm/counter.txt sh -c 'echo 0 > /dev/shm/counter.txt'

我认为您了解如何进行阅读,但出于完整性考虑,我将其包括在内:

flock --shared /dev/shm/counter.txt cat /dev/shm/counter.txt

这似乎是唯一正确注意到问题的答案,在该问题中,文件甚至在flock甚至运行之前
就已
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.