`flock -u` 到底做了什么?
What does `flock -u` actually do?
我正在使用命令 flock
,它获取和释放对文件的锁定。例如,如果我 运行
flock /tmp/mylock true
然后它立即退出,大概是获取然后释放锁。如果我运行
flock /tmp/mylock sleep 100
然后延迟100秒,再次获取和释放锁。而且,如果我 运行 以下两个单独的 shells:
flock /tmp/mylock sleep 100
和
flock /tmp/mylock true
那么第二个命令就被阻塞了,因为它在第一个命令运行s的时候无法获取到锁。一旦 sleep 100
完成并释放锁,第二个命令 运行s 并退出。一切顺利。
问题来了。如果在这 100 秒的延迟期间,我 运行 在第三个 shell 中执行以下操作:
flock -u /tmp/mylock true
然后会发生什么? flock 的手册页说:
-u, --unlock
Drop a lock. This is usually not required, since a lock is
automatically dropped when the file is closed. However, it may
be required in special cases, for example if the enclosed com-
mand group may have forked a background process which should not
be holding the lock.
所以,这应该放下锁,这应该允许 flock /tmp/mylock true
到 运行,对吧? (我也猜测 flock /tmp/mylock sleep 100
会立即退出,但这是推测。)
会发生什么?没有什么。 flock -u /tmp/mylock true
立即退出,但flock /tmp/mylock true
继续阻塞,flock /tmp/mylock sleep 100
继续退出。
flock -u /tmp/mylock <command>
实际上是做什么的?
(所有示例均在 Ubuntu 18.04 上测试。)
这是一个示例,其中 -u
使用在文件 mylock
上打开的文件描述符 9,成功解锁 9,以便后台 flock mylock
可以继续。
请注意,flock 9
也不能有命令,因为在这种情况下,“9”被视为文件名,而不是 fd。
bash -s <<\! 9>mylock 2>&1 |
flock 9; echo gotlock1
flock 9; echo gotlock2
9>&- flock mylock bash -c 'echo start_sleep;sleep 8; echo end_sleep' &
sleep 2
flock -u 9; echo unlock; sleep .1
flock 9; echo gotlock3
!
awk '{t2=systime(); if(t1==0)t1=t2; printf "%2d %s\n",t2-t1,[=10=]; t1=t2}'
第一行使 bash 运行 在打开 fd 9 之后成为以下几行,而且还通过最后看到的 awk 脚本通过管道传输 stdout 和 stderr。这只是用行的时间来注释输出。结果是:
0 gotlock1
0 gotlock2
2 unlock
0 start_sleep
8 end_sleep
0 gotlock3
这会立即显示前 2 个 flock 9
命令 运行。然后一个 flock mylock
命令在后台是 运行,在关闭 fd 9 之后只是为了这一行。例如,此命令可能是来自第二个 window 的 运行。输出显示它挂起,因为我们没有看到 start_sleep
。这意味着前面的 flock 9
确实获得了独占锁。
然后输出显示在 sleep 2
和 flock -u 9
之后我们得到 unlock
回显,然后后台命令才获得锁并启动它的 sleep 8
.
主脚本立即执行flock 9
,但输出显示直到后台脚本以end_sleep
8 秒后结束,主脚本输出gotlock3
.
lslocks
命令有时会显示 2 个对锁感兴趣的进程。 *
表示等待:
COMMAND PID TYPE SIZE MODE M START END PATH
flock 23671 FLOCK 0B WRITE* 0 0 0 /tmp/mylock
flock 23655 FLOCK 0B WRITE 0 0 0 /tmp/mylock
但是它本身并没有显示第一个 flock 9
的结果,大概是因为没有进程拥有锁,即使文件确实被锁定了,正如我们看到的后台作业无法继续。
我正在使用命令 flock
,它获取和释放对文件的锁定。例如,如果我 运行
flock /tmp/mylock true
然后它立即退出,大概是获取然后释放锁。如果我运行
flock /tmp/mylock sleep 100
然后延迟100秒,再次获取和释放锁。而且,如果我 运行 以下两个单独的 shells:
flock /tmp/mylock sleep 100
和
flock /tmp/mylock true
那么第二个命令就被阻塞了,因为它在第一个命令运行s的时候无法获取到锁。一旦 sleep 100
完成并释放锁,第二个命令 运行s 并退出。一切顺利。
问题来了。如果在这 100 秒的延迟期间,我 运行 在第三个 shell 中执行以下操作:
flock -u /tmp/mylock true
然后会发生什么? flock 的手册页说:
-u, --unlock
Drop a lock. This is usually not required, since a lock is
automatically dropped when the file is closed. However, it may
be required in special cases, for example if the enclosed com-
mand group may have forked a background process which should not
be holding the lock.
所以,这应该放下锁,这应该允许 flock /tmp/mylock true
到 运行,对吧? (我也猜测 flock /tmp/mylock sleep 100
会立即退出,但这是推测。)
会发生什么?没有什么。 flock -u /tmp/mylock true
立即退出,但flock /tmp/mylock true
继续阻塞,flock /tmp/mylock sleep 100
继续退出。
flock -u /tmp/mylock <command>
实际上是做什么的?
(所有示例均在 Ubuntu 18.04 上测试。)
这是一个示例,其中 -u
使用在文件 mylock
上打开的文件描述符 9,成功解锁 9,以便后台 flock mylock
可以继续。
请注意,flock 9
也不能有命令,因为在这种情况下,“9”被视为文件名,而不是 fd。
bash -s <<\! 9>mylock 2>&1 |
flock 9; echo gotlock1
flock 9; echo gotlock2
9>&- flock mylock bash -c 'echo start_sleep;sleep 8; echo end_sleep' &
sleep 2
flock -u 9; echo unlock; sleep .1
flock 9; echo gotlock3
!
awk '{t2=systime(); if(t1==0)t1=t2; printf "%2d %s\n",t2-t1,[=10=]; t1=t2}'
第一行使 bash 运行 在打开 fd 9 之后成为以下几行,而且还通过最后看到的 awk 脚本通过管道传输 stdout 和 stderr。这只是用行的时间来注释输出。结果是:
0 gotlock1
0 gotlock2
2 unlock
0 start_sleep
8 end_sleep
0 gotlock3
这会立即显示前 2 个 flock 9
命令 运行。然后一个 flock mylock
命令在后台是 运行,在关闭 fd 9 之后只是为了这一行。例如,此命令可能是来自第二个 window 的 运行。输出显示它挂起,因为我们没有看到 start_sleep
。这意味着前面的 flock 9
确实获得了独占锁。
然后输出显示在 sleep 2
和 flock -u 9
之后我们得到 unlock
回显,然后后台命令才获得锁并启动它的 sleep 8
.
主脚本立即执行flock 9
,但输出显示直到后台脚本以end_sleep
8 秒后结束,主脚本输出gotlock3
.
lslocks
命令有时会显示 2 个对锁感兴趣的进程。 *
表示等待:
COMMAND PID TYPE SIZE MODE M START END PATH
flock 23671 FLOCK 0B WRITE* 0 0 0 /tmp/mylock
flock 23655 FLOCK 0B WRITE 0 0 0 /tmp/mylock
但是它本身并没有显示第一个 flock 9
的结果,大概是因为没有进程拥有锁,即使文件确实被锁定了,正如我们看到的后台作业无法继续。