Flock 似乎不起作用

Mr.*_*esh 8 file-descriptors subshell flock

我最近一直在尝试为一个小项目创建一个 shell 脚本,但由于某种原因,该flock命令对我不起作用。每当我在子 shell 中以原子方式调用它并将其置于后台时,其他程序似乎能够读取/写入锁定的文件。

Bash 会话:

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.
Run Code Online (Sandbox Code Playgroud)

我觉得我可能遗漏了一些与“flock”程序内部相关的非常简单的东西,但不知道它可能是什么。

Kus*_*nda 10

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)
Run Code Online (Sandbox Code Playgroud)

输出:

1: Locking for 5 secs
2: Will now attempt to get lock
1: Done
2: Got lock
Run Code Online (Sandbox Code Playgroud)

您可以看到该锁是由后台进程获取的,并且其他flock调用必须等待它被释放才能锁定它。

还要注意,锁定文件不是这里受保护的,而是echo子shell 中的操作保证是独占的。特别是,锁定文件不受写入或读取它的不合作进程的保护。

这意味着,每个flock子外壳,通过锁定/tmp/lock在这个例子中,保证了操作(上的文件或其他共享数据资源)将不会与冲突操作从混杂任何其他程序使用flock/tmp/lock作为锁定文件。

为了说明上面的最后一段,在两个不同的终端(可能稍微增加睡眠时间)中运行我上面的脚本,尽可能同时,并验证两个相互竞争的脚本是否适当地获取了锁(相互等待)。由于在后台进程中请求了一个锁,这意味着在同时运行脚本的两个实例时,可能会按照脚本中指定的顺序获取锁。

在您的示例中,交互式 shell不与锁定机制合作。这就是为什么即使锁定由后台子shell 持有,您也可以读取和写入文件的原因。

另请注意,并非所有文件系统都支持文件锁定flock(或其等效的 C 库,flock())。例如,网络文件系统 AFS 和 NFS 在这方面可能存在问题。请参阅https://en.wikipedia.org/wiki/File_locking#Problems