首先让我展示一下有效的方法。如果我使用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
的锁定。然后在第二个终端中,当我尝试获取同一文件的锁时,它会成功。我预计它会像上一个例子中那样失败。为什么会成功?
答案 0 :(得分:11)
您使用的-n
如果无法立即获取锁定将终止,flock
将因退出代码1而失败。因此,在第一个终端中执行代码后,它会休眠100秒。接下来当你在另一个终端中执行相同的操作时,flock
失败并返回1,但因为有一个;
并且你没有对返回代码做任何事情,shell只是继续执行下一个语句然后睡100秒。
因此,您需要对flock的返回码做出如下决定。
( flock -x -n 100 || exit 55; sleep 100; ) 100> /tmp/foo.txt
现在,如果您在一个终端中执行上述行,它将会休眠100秒。接下来,如果您在另一个终端上运行代码,它将立即返回提示。执行echo $?
,您会看到它已返回55
,因为我们想要使用||
返回。
||
做的是短路。如果flock
返回0
,就像正常退出那样是shell的 true 值,它将不会执行表达式的右侧,因此会转到下一个语句。如果返回值为1
,这是shell的 false ,它将继续评估右侧表达式exit 55
,从而退出。您也可以if-then-fi
执行此操作。
另请注意,我使用括号()
而不是花括号{}
。这是因为,如果您使用curley-braces,那么命令将在当前shell中执行,如果您使用exit,则它将从当前shell退出。括号将创建一个子shell,因此从那里执行exit
会终止子shell并返回到原始shell。
它适用于您使用-c
的第一个示例,因为您在flock
参数中包含了单个命令。因此,如果flock
无法获取锁,则它将不执行该语句并终止。