下面的Perl子例程使用File::FcntlLock
来检查文件是否被锁定。
为什么即使文件被锁定,它也会返回0
并打印/tmp/test.pid is unlocked.
?
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();
}
文件被锁定如下(lock.sh):
#!/bin/sh
(
flock -n 200
while true; do sleep 1; done
) 200>/tmp/test.pid
文件确实已锁定:
~$ ./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
答案 0 :(得分:6)
fcntl
和flock
锁彼此不可见。
这对您的用例来说是个大问题,因为您在shell脚本中使用的flock
实用程序取决于flock
语义:shell脚本运行flock
子进程,它锁定一个继承的文件描述符然后退出。 shell保持该文件描述符打开(因为重定向是在整个命令序列上),直到它想要释放锁。
该计划无法与fcntl
一起使用,因为fcntl
锁不会在进程间共享。如果有一个与flock
相同但使用fcntl
的实用程序,则锁定将过早释放(一旦子进程退出)。
为了协调perl进程和shell脚本之间的文件锁定,您可以考虑以下几个选项:
zsh
并使用zsystem flock
模块中的zsh/system
内置版(注意:在其声称使用fcntl
的文档中尽管名称如此是flock
)/proc/locks
来模拟Linux上的内容)fcntl
实用程序以便在shell脚本中使用(使用模式将不同 - shell脚本必须对其进行后台处理,然后在以后将其解除以解锁 - 并且需要某种方式告诉父进程何时获得或未能获得锁定,这将很难,因为它现在异步发生...可能使用某些shell具有的 coprocess 功能。 fcntl
实用程序需要相同的后台处理)有关不同类型锁的功能的更多信息,请参阅What is the difference between locking with fcntl
and flock
。