如何确保一次只运行Perl脚本的副本?
题
我需要确保一次只运行我的perl脚本的一个副本。根据建议 这里 我写了一个子来进行检查:
sub check_instances {
open my $fh, '<', $0 or die $!;
unless (flock($fh, LOCK_EX|LOCK_NB)) {
print "$0 is already running. Exiting.\n";
exit 1;
}
}
但这行不通。有什么问题?
解决方案
您正在使用子内部范围内的词汇filehandle。什么时候 check_instances
返回,FileHandle自动关闭,从而释放锁。因此,除非有两份副本同时进行检查,否则您将永远不会看到冲突。
只要脚本正在运行(或只要要维护锁),请确保文件打开。例如:
{
my $fh;
sub check_instances {
return if $fh; # We already checked
open $fh, '<', $0 or die $!;
unless (flock($fh, LOCK_EX|LOCK_NB)) {
print "$0 is already running. Exiting.\n";
exit 1;
}
}
} # end scope of $fh
这也将是一个使用的好地方 state
多变的, ,如果您需要Perl 5.10。
其他提示
您可以检查其他实例的过程列表(proc :: processTable 可以提供帮助),但是Unix程序以多种语言采取的一条通用路线是创建一个PID文件 - 请参阅 文件:: pid.
正常语义的语义 flock
可能需要您以写入模式打开文件handle,例如
open $fh, '>>', $0;
open $fh, '+<', $0;
(从 perldoc -f flock
)
请注意,FCNTL(2)FLOCK(3)的仿真要求使用读取意图打开fileHandle,以使用lock_sh,并要求它以写入意图打开以使用lock_ex。
由于各种原因,文件锁定可能会失败(例如,如果文件在NFS等网络文件系统上)。
我的解决方案是在脚本运行时创建一个目录。创建目录始终是原子操作。
不隶属于 StackOverflow