d-_*_*_-b 10 shell shell-script lock
我想要一个用作计数器的文件。用户 A 将写入并增加此数字,而用户 B 请求读取文件。是否有可能用户 A 可以锁定此文件,以便在用户 A 的写入完成之前没有人可以读取或写入它?
我已经调查过,flock
但似乎无法按我的预期工作。
flock -x -w 5 /dev/shm/counter.txt echo "4" > /dev/shm/counter.txt && sleep 5
Run Code Online (Sandbox Code Playgroud)
如果有更合适的方法来获取这个类似原子的递增文件,那也很高兴听到!
我的目标是:
LOCK counter.txt; write to counter.txt;
Run Code Online (Sandbox Code Playgroud)
同时
Read counter.txt; realize it's locked so wait until that lock is finished.
Run Code Online (Sandbox Code Playgroud)
gol*_*cks 16
文件锁不是强制性的1 -- 即,您不能锁定文件,以便另一个进程无法访问它。锁定文件意味着如果一个(另一个)进程检查它是否已被锁定,它就会知道。
的目的flock
是做这样的东西,你想要什么,但你必须使用flock
为每一个尝试访问。请记住,那些是阻塞调用;来自man flock
:
如果无法立即获取锁,则 flock 等待锁可用
1. 如果您将其用于安全等目的,这会使该功能看起来毫无用处,但这不是文件锁定的目的——它们用于同步,而这正是您正在做的。用户 Leo 指出,基于其他 *nix 操作系统的历史相似之处,Linux 内核中可能存在强制文件锁定的非标准化实现(请参阅此讨论)。但是,这看起来只是一个 C 级接口。
Joh*_*024 10
Bash 对下面命令的处理可能会令人惊讶:
flock -x -w 5 /dev/shm/counter.txt echo "4" > /dev/shm/counter.txt && sleep 5
Run Code Online (Sandbox Code Playgroud)
Bash 首先运行flock -x -w 5 /dev/shm/counter.txt echo "4" > /dev/shm/counter.txt
,如果成功完成(释放锁),则运行sleep 5
. 因此,锁定不会在人们预期的 5 秒内保持。
&
对&&
如果有两个命令,A
并且B
,则:
A & B
开始A
在后台,然后开始B
而无需等待A
到结束。
A && B
开始A
,等待它完成,然后,如果它成功完成(退出代码 0),则开始B
。如果A
失败(非零退出代码),则B
永远不会运行。
总之,&
和&&
是两个完全不同的列表运算符。
您可以使用“sh -c command...”来运行整个 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))'
Run Code Online (Sandbox Code Playgroud)
将加号更改为减号应减少计数器:
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))'
Run Code Online (Sandbox Code Playgroud)
我希望您会在任何争用发生之前初始化计数器,因此无需担心提前锁定:
echo 0 > /dev/shm/counter.txt
Run Code Online (Sandbox Code Playgroud)
我认为您不需要在可能发生争用时破坏计数器值,但是,如果您曾经这样做过,您应该这样做:
flock --exclusive --wait 5 /dev/shm/counter.txt sh -c 'echo 0 > /dev/shm/counter.txt'
Run Code Online (Sandbox Code Playgroud)
我认为您了解如何进行阅读,但为了完整起见,我将其包括在内:
flock --shared /dev/shm/counter.txt cat /dev/shm/counter.txt
Run Code Online (Sandbox Code Playgroud)