下面的Perl子程序使用File::FcntlLock
来检查文件是否被locking。
为什么它返回0
,打印/tmp/test.pid is unlocked.
即使文件被locking?
sub getPidOwningLock { my $filename = shift; my $fs = new File::FcntlLock; $fs->l_type( F_WRLCK ); $fs->l_whence( SEEK_SET ); $fs->l_start( 0 ); $fs->l_len( 0 ); my $fd; if (!open($fd, '+<', $filename)) { print "Could not open $filename\n"; return -1; } if (!$fs->lock($fd, F_GETLK)) { print "Could not get lock information on $filename, error: $fs->error\n"; close($fd); return -1; } close($fd); if ($fs->l_type() == F_UNLCK) { print "$filename is unlocked.\n"; return 0; } return $fs->l_pid(); }
该文件被locking如下(lock.sh):
#!/bin/sh ( flock -n 200 while true; do sleep 1; done ) 200>/tmp/test.pid
该文件确实被locking:
~$ ./lock.sh & [2] 16803 ~$ lsof /tmp/test.pid COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME bash 26002 admin 200w REG 8,5 0 584649 test.pid sleep 26432 admin 200w REG 8,5 0 584649 test.pid
fcntl
和flock
锁是彼此不可见的。
这对于你的用例来说是个大问题,因为你在shell脚本中使用的flock
工具依赖于flock
语义:shell脚本运行一个flock
子进程,它锁定一个继承的文件描述符,然后退出。 shell将该文件描述符保持打开状态(因为重定向是在一个完整的命令序列上),直到它想释放锁。
该计划无法与fcntl
因为fcntl
锁不在进程之间共享。 如果有一个与flock
相同的实用程序,但是使用fcntl
,锁定会被释放得太早(一旦子进程退出)。
为了协调perl进程和shell脚本之间的文件锁定,可以考虑一些选项:
zsh
并使用zsh/system
模块中的zsystem flock
内建(注意:尽管它的名字是flock
,但在文档中声明使用fcntl
) /proc/locks
来模拟Linux) fcntl
实用程序以便在shell脚本中使用(使用模式将有所不同 – shell脚本必须将其后台化,然后在解锁时终止),并且需要一些方法告诉父进程已经获得或未能获得锁,这将是很难的,因为它现在异步发生…也许使用一些shell有的协处理功能)。 fcntl
实用程序需要的相同的背景处理) 有关不同种类的锁的更多信息,请参阅fcntl
与flock
锁定有何区别 。