无法使用带有文件描述符的群来锁定文件

Unable to lock file using flock with file descriptor

首先让我展示一下什么是有效的。如果我将 flock 与文件路径一起使用,它就可以工作。

1 号航站楼:

[root@centos ~]# flock -x -n /tmp/foo.txt -c "sleep 100"

2 号航站楼:

[root@centos ~]# flock -x -n /tmp/foo.txt -c "sleep 100"
[root@centos ~]# echo $?
1

上面的输出显示我首先在第一个终端中获取了 /tmp/foo.txt 上的独占锁。然后在第二个终端中,当我尝试获取同一个文件的锁时,它失败了。

现在让我知道什么不起作用。如果我将 flock 与文件描述符一起使用,它就不起作用。

1 号航站楼:

[root@centos ~]# { flock -x -n 100; sleep 100; } 100> /tmp/foo.txt

2 号航站楼:

[root@centos ~]# { flock -x -n 100; sleep 100; } 100> /tmp/foo.txt

以上输出显示我首先尝试在第一个终端中获取 /tmp/foo.txt 上的锁。然后在第二个终端中,当我尝试获取同一文件的锁时,它成功了。我预计它会像前面的示例一样失败。为什么会成功?

您正在使用 -n,如果无法立即获取锁,它将终止,并且 flock 将失败,退出代码为 1。因此,在您在第一个终端中执行代码后,它会休眠持续 100 秒。接下来当你在另一个终端执行相同的操作时,flock 失败并且 returns 1,但是因为有一个 ; 而你没有对 return 代码做任何事情, shell 只是继续执行下一条语句并休眠 100 秒。

因此您需要对 flock 的 return 代码做出如下决定。

( flock -x -n 100 || exit 55; sleep 100; ) 100> /tmp/foo.txt

现在,如果您在一个终端中执行上述行,它将休眠 100 秒。接下来,如果您 运行 另一个终端上的代码,它将立即 return 提示。做一个 echo $? 你会看到它 returned 55 正如我们想要的那样 return 使用 || .

||的作用是短路。如果 flock returns 0 正常退出是 true 值 shell,它不会执行正确的表达式的手边,因此转到下一个语句。如果 return 值为 1,对于 shell,它是 false,它将继续计算右侧表达式 exit 55 并因此退出。您也可以通过 if-then-fi 执行此操作。

另请注意,我使用了方括号 () 而不是大括号 {}。这是因为,如果您使用大括号,那么命令将在当前 shell 中执行,如果您使用 exit,那么它将从当前 shell 中退出。括号将创建一个 subshell,因此从那里执行 exit 会终止 subshell 并返回到原始 shell.

它适用于您使用 -c 的第一个示例,因为您在 flock 参数中包含了单个命令。因此,如果 flock 无法获取锁,它将不会执行语句并终止。