我有一个
的Perl脚本启动时,此脚本会创建一个文件(比如说script.lock),退出后会删除该文件。我有一个crontab条目,每分钟运行一次这个脚本。如果存在lockfile,则脚本退出,假设其自身的另一个实例正在运行。
上述过程运行正常,但我对这种方法的稳健性不太满意。具体来说,如果由于某种原因脚本过早退出并且未删除锁定文件,则新实例将无法正常执行。
我希望对以下内容提出一些建议:
答案 0 :(得分:4)
我们假设您采用连续循环路线。你将你的程序重新调整为一个无限循环。你睡了一段时间,然后醒来并处理你的数据库文件,然后再回去睡觉。
您现在需要一种机制来确保您的程序仍然正常运行。这可以通过像inetd这样的东西来完成。
但是,您的程序基本上只执行一项任务,并且在一天中重复执行该任务。这就是crontab的用途。 inetd 机制适用于等待客户端的服务器,如https或sshd。在这些情况下,您需要一种机制来在服务器进程终止后立即重新创建它。
您可以改进 lockfile 机制的一种方法是将PID包含在其中。例如,在Perl脚本中执行此操作:
open my $lock_file_fh, ">", LOCK_FILE_NAME;
say {$lock_file_fh} "$$";
close $lock_file_fh;
现在,如果您的crontab看到锁定文件,它可以测试该进程ID是否仍在运行:
if [ -f $lock_file ]
then
pid=$(cat $lock_file)
if ! ps -p $pid
then
rm $lock_file
fi
restart_program
else
restart_program
fi
答案 1 :(得分:3)
如果使用cron,使用锁文件是一个很好的方法,但如果你可以轻松安装和使用一个数据库,我会推荐一个数据库(MySQL / Postgres / whatever。不是SQLite)。除了其他原因之外,这比本地文件系统上的文件更便携,并且可以重复使用。
你确实是对的。因为你描述的原因,cron不是这个场景的最佳选择 - 如果过程过早死亡,很难恢复(你可以通过检查时间戳,但不是很容易)。
你应该使用cron for是一个“start_if_daemon_died”工作。
StackOverflow已经很好地涵盖了这一点,例如:这里:
“How can I run a Perl script as a system daemon in linux?”或more posts。
答案 2 :(得分:1)
这并不是一个新的答案,而只是一个在David W的Perl中得到解决的例子。
my $LOCKFILE = '/tmp/precache_advs.lock';
create_lockfile();
do_something_interesting();
remove_lockfile();
sub create_lockfile {
check_lockfile();
open my $fh, ">", $LOCKFILE or die "Unable to open $LOCKFILE: $!";
print $fh "$$";
close $fh;
return;
}
sub check_lockfile {
if ( -e $LOCKFILE ) {
my $pid = `cat $LOCKFILE`;
if ( system("ps -p $pid") == 0 ) {
# script is still running, so don't start a new instance
exit 0;
}
else {
remove_lockfile();
}
}
return;
}
sub remove_lockfile {
unlink $LOCKFILE or "Unable to remove $LOCKFILE: $!";
return;
}