如何告诉Perl每20秒运行一些代码?
答案 0 :(得分:21)
for (;;) {
my $start = time;
# your code;
if ((my $remaining = 20 - (time - $start)) > 0) {
sleep $remaining;
}
}
答案 1 :(得分:9)
while (1) {
sleep 20;
<your code here>;
}
答案 2 :(得分:8)
虽然sleep
函数适用于某些用途,但如果您尝试“永远每20秒”执行一次,那么最好使用cron
之类的外部实用程序。< / p>
除了已经提到的漂移问题之外,如果您的sleep
脚本退出(预期或其他方式),那么它将不会在接下来的20秒标记处再次运行。
@Blrfl是对的,我感到羞怯。也就是说,它很容易克服。
* * * * * /path/to/script.pl
* * * * * sleep 20 && /path/to/script.pl
* * * * * sleep 40 && /path/to/script.pl
您还可以采用混合方法在脚本中放置一个有限计数的睡眠循环,并使用cron每隔X分钟运行一次,覆盖脚本死亡的情况。任何比20秒更频繁的事情,我肯定会接受这种方法。
答案 3 :(得分:7)
设置一个SIGALRM处理程序,并使用alarm
每20秒发送一个信号(参见perldoc -f alarm):
$SIG{ALRM} = sub {
# set up the next signal for 20 seconds from now
alarm 20;
# do whatever needs to be done
# ...
};
随着时间的推移会出现漂移,因为每个信号可能会延迟一秒钟;如果这很重要,请改为设置一个cron作业。此外,如果您的其他代码运行时间超过20秒,则会发生更多漂移,因为只有一个计时器可以立即计数。你可以通过产生线程来解决这个问题,但是在这一点上,我已经回到了一个简单的cron解决方案。
选择正确的解决方案取决于您需要定期执行的任务类型,而您没有指定。
答案 4 :(得分:3)
#!/usr/bin/perl
use strict; use warnings;
use Schedule::ByClock;
my $scheduler = Schedule::ByClock->new(0, 20, 40);
while ( defined( my $r = $scheduler->get_control_on_second ) ) {
printf "%02d\n", $r;
}
其他人指出的所有警告仍然适用,但我认为该模块很整洁。
答案 5 :(得分:2)
一起去..
while () {
sleep 20;
#Code here
}
答案 6 :(得分:2)
#!/usr/bin/perl -w
use strict;
# heartbeat
$SIG{ALRM} = sub {
# set up the next signal for 20 second from now
alarm(20);
printf "<heartbeat/>\n";
};
alarm(20); # start timer
my $i = 0;
while(1) {
$i++;
printf "loop" . $i . "\n";
sleep 2;
}
alarm(0);
printf "done!\n";
输出:
loop1
loop2
loop3
loop4
loop5
loop6
loop7
loop8
loop9
loop10
<heartbeat/>
loop11
loop12
loop13
loop14
loop15
loop16
loop17
loop18
loop19
loop20
<heartbeat/>
答案 7 :(得分:1)
最好使用一些事件库。有两种选择:
use IO::Async::Timer::Periodic;
use IO::Async::Loop;
my $loop = IO::Async::Loop->new;
my $timer = IO::Async::Timer::Periodic->new(
interval => 60,
on_tick => sub {
print "You've had a minute\n";
},
);
$timer->start;
$loop->add( $timer );
$loop->run;
AnyEvent::DateTime::Cron->new()
->add(
'* * * * *' => sub { warn "Every minute"},
'*/2 * * * *' => sub { warn "Every second minute"},
)
->start
->recv
等