无法使用文件描述符

时间:2015-06-05 04:01:24

标签: linux shell concurrency locking

首先让我展示一下有效的方法。如果我使用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的锁定。然后在第二个终端中,当我尝试获取同一文件的锁时,它会成功。我预计它会像上一个例子中那样失败。为什么会成功?

1 个答案:

答案 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无法获取锁,则它将不执行该语句并终止。