我最近一直在尝试为一个小项目创建一个 shell 脚本,由于某种原因,该flock
命令无法正常工作。每当我在子 shell 中以原子方式调用它并将其放入后台时,其他程序似乎都能够读取/写入锁定的文件。
重击会话:
guest@guest ~ $ touch ./temp
guest@guest ~ $ ( flock -x 3 && sleep 99999999999; ) 3>./temp &
[1] 22874
guest@guest ~ $ cat ./temp
guest@guest ~ $ echo this is a test >./temp
guest@guest ~ $ cat ./temp
this is a test
guest@guest ~ $ jobs
[1]+ Running ( flock -x 3 && sleep 99999999999 ) 3>./temp &
guest@guest ~ $ bash --version
GNU bash, version 4.3.48(1)-release (x86_64-pc-linux-gnu)
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
我觉得我可能错过了一些与“flock”程序内部相关的非常简单的东西,但不知道它可能是什么。
答案1
flock
执行咨询锁定,这是一种协作锁定方案。这意味着如果您不合作,您将能够覆盖锁定。您可以通过在执行操作之前请求锁定来进行配合,然后在完成操作后释放锁定。这是受锁保护的操作,而不是(必然)锁文件本身。
从手册flock(2)
在我的系统上:
咨询锁允许协作进程对文件执行一致的操作,但不保证一致性(即,进程仍然可以在不使用咨询锁的情况下访问文件,这可能会导致不一致)。
考虑这个脚本:
#!/bin/sh
( flock -x 9 || exit 1
echo '1: Locking for 5 secs'; sleep 5; echo '1: Done' ) 9>/tmp/lock &
sleep 1
echo '2: Will now attempt to get lock'
( flock -x 9 || exit 1
echo '2: Got lock' ) 9>/tmp/lock
# Since the second flock call only performs one operation, the whole last
# subshell may be replaced by just
# flock -x /tmp/lock -c echo '2: Got lock'
#
# (-x and -c are not needed, a lock is exclusive ("write lock")
# unless -s is used to create a shared lock ("read lock"),
# and the -c is optional)
输出:
1: Locking for 5 secs
2: Will now attempt to get lock
1: Done
2: Got lock
您可以看到锁是由后台进程获取的,并且其他flock
调用必须等待它被释放才能锁定它。
另请注意,此处保护的不是锁定文件,而是echo
保证独占的子 shell 中的操作。特别是,锁文件不受写入或读取的不合作进程的保护。
这意味着flock
通过在此示例中锁定/tmp/lock
,可以保证每个子 shell 的操作(对文件或其他共享数据资源的操作)不会与来自其他子 shell 的冲突操作混合在一起。任何flock
使用with/tmp/lock
作为锁定文件的其他程序。
为了说明上面的最后一段,请尽可能同时在两个不同的终端中运行上面的脚本(可能会稍微增加睡眠时间),并验证两个竞争脚本是否适当地获取锁(相互等待)。由于在后台进程中请求一个锁,这意味着该锁可能同时运行脚本的两个实例时,无法按脚本中指定的顺序获取。
在您的示例中,交互式 shell 是不配合锁定机制。这就是为什么即使后台子 shell 持有锁,您也能够读取和写入文件。
另请注意,并非所有文件系统都支持使用flock
(或其等效的 C 库flock()
)进行文件锁定。例如,网络文件系统 AFS 和 NFS 在这方面可能存在问题。看https://en.wikipedia.org/wiki/File_locking#Problems