如何确保一次只运行一份 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;
}
}
但它不起作用。可能是什么问题?
I need to ensure that only one copy of my Perl script is running at a time. According to the suggestions here I wrote a sub to do the check:
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;
}
}
But it doesn't work. What can be the issue?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
您正在使用子范围内的词法文件句柄。当
check_instances
返回时,文件句柄会自动关闭,从而释放锁。因此,除非两个副本完全相同地同时检查,否则您永远不会看到冲突。确保只要脚本正在运行(或者只要您想要保持锁定),文件句柄就保持打开状态。例如:
这也是使用
state
变量< /a>,如果您需要 Perl 5.10。You're using a lexical filehandle scoped inside the sub. When
check_instances
returns, the filehandle is automatically closed, which releases the lock. So you'll never see a conflict unless two copies check at exactly the same time.Ensure that the filehandle remains open as long as the script is running (or as long as you want to maintain the lock). For example:
This would also be a good place to use a
state
variable, if you can require Perl 5.10.您可以检查其他实例的进程列表(Proc::ProcessTable 可以提供帮助) ,但许多语言中的 UNIX 程序采用的常见途径是创建 pid 文件 - 请参阅 文件::Pid。
You can check the process list for other instances (Proc::ProcessTable can help), but a common route taken by unix programs in many languages is to create a pid file -- see File::Pid.
flock
的正常语义可能要求您以写入模式打开文件句柄,例如(来自
perldoc -f集群
)The normal semantics of
flock
may require you to open the filehandle in write mode, say,(From
perldoc -f flock
)文件锁定可能会因各种原因而失败(例如,如果文件位于 NFS 等网络文件系统上)。
我的解决方案是在脚本运行时创建一个目录。创建目录始终是一个原子操作。
File locking can fail for various reasons (for example if the file is on a network file system like NFS).
My solution is to create a directory while the script runs. Creating directories is always an atomic operation.