我有一个perl脚本,它一直作为守护进程循环运行.我想在perl脚本中运行一个基于时间(或计时器)的子函数,所以每运行2小时它会运行该子函数并继续它的循环.我正在考虑获取纪元时间,只是通过循环检查它几次,一旦它超过2小时就会运行子功能.在perl中有更好的方法吗?
谢谢,
LF4
这取决于自上次子程序启动开始以来或自上次执行结束以来是否应该有2个小时.
1)如果后者(在运行最后一个子程序结束和新程序开始之间2小时),cespinoza的解决方案是完全可以接受的(无限循环,并sleep(7200);
在执行子程序后调用).
my $timeout = 7200;
while (1) {
dostuff();
sleep($timeout);
};
Run Code Online (Sandbox Code Playgroud)
唯一的问题是它无法处理dostuff()
永远需要的情况,例如陷入困境 - 讨论为什么这是一个需要考虑的重要情况和解决方法,见下文.
2)如果是前者(起点之间2小时),则有三个选项,与处理超过2小时[0]的子程序运行时有关.您在下面详细解释的3个选项是:
2a)启动一个新的子程序,而旧的子程序继续运行(并行);
2b)在旧子程序结束后启动新的子程序;
2c)启动一个新的子程序但首先停止执行前一个子程序.
2a 2c选项要求您设置alarm()
2小时,并且在触发警报时会发生什么不同.
[0]注意:由于任何子程序可能至少需要来自PC的一些资源,因此它总是 - 但是很小 - 它可能会超过2小时,所以你必须选择其中一个选项来处理这种情况.
2a)每2小时开始一次,如果没有完成则与旧执行并行运行.
该选项基本上是实现cron
功能.
无论何时你听到并行这个词,你都可能会分开这个过程.
my $timeout = 7200;
while (1) { # Not tested!
eval {
local $SIG{ALRM} = sub { die "alarm\n" };
if (!defined($child_pid = fork())) {
die "cannot fork: $!\n";
} elsif (!$child_pid) { # Child
dostuff();
exit;
} # Parent continues to sleep for 2 hours
alarm $timeout; # You need it in case forking off take >2hrs
sleep; # forever
};
die unless $@ eq "alarm\n"; # propagate unexpected errors
# We don't need to check if $@ is true due to forever sleep
}
Run Code Online (Sandbox Code Playgroud)
2b)每2小时开球,如果旧的没有完成,让它一直运行直至完成
这可以重新措辞为"启动任务,如果它完成超过2小时,睡眠剩余"
my $timeout = 7200;
while (1) {
my $start = time;
dostuff();
my $end = time;
my $lasted = $end - $start;
if ($lasted < $timeout) {
sleep($timeout - $lasted);
}
};
Run Code Online (Sandbox Code Playgroud)
2c)每两个小时开球,如果前一个没有完成,将它计时并杀死它
每当你看到这样的逻辑时,警报显然就是答案.
while (1) {
my $finished = 0;
eval {
local $SIG{ALRM} = sub { die "alarm\n" };
alarm 7200;
dostuff();
$finished = 1;
sleep; # forever
};
die unless $@ eq "alarm\n"; # propagate unexpected errors
warn "Timed out!!!\n" unless $finished
}
Run Code Online (Sandbox Code Playgroud)
PS正如cespinoza所指出的,你需要以某种方式守护脚本(确保它在你退出启动它的shell时不被杀死),通过Unix方式(例如将其作为nohup启动)或Perlish意味着(搜索daemonize + Perl)在Stackoverflow上的力学).
归档时间: |
|
查看次数: |
4663 次 |
最近记录: |