2010-09-20 82 views
10

如何让Perl每20秒运行一次代码?如何让Perl每20秒运行一次代码?

+7

以人向下投票这个问题,停下来想想了几分钟。像“睡眠20”这样的简单答案只是部分解决方案。 – 2010-09-20 15:05:54

+1

@Chas。问题是这个问题没有明确指出(参见Ether/Blrfl关于答案的评论)。因此,即使所要求的不是,问题也不好。 – DVK 2010-09-20 17:32:43

+2

@DVK是的​​,会出现各种各样的复杂情况(代码应该每隔20秒重复一次,没有重叠,在二十秒边界上,在一分钟的第0,第20和第40秒等等)执行。这些都是对所需问题的改进,但是反对票不会得到改进,特别是没有人评论为什么它不是一个很好的问题。 – 2010-09-20 19:35:16

回答

9
while (1) { 
     sleep 20; 
     <your code here>; 
} 
+2

如果“您的代码在这里”需要19秒才能运行? – Ether 2010-09-20 16:43:15

+3

这取决于。代码是否必须从20秒的边界开始,或者最后一次迭代结束和下一次迭代开始之间是否需要20秒? – Blrfl 2010-09-20 17:01:34

18
for (;;) { 
    my $start = time; 
    # your code; 
    if ((my $remaining = 20 - (time - $start)) > 0) { 
     sleep $remaining; 
    } 
} 
+1

Upvote:不会受到漂移的影响。 – daxim 2010-09-20 08:48:15

+3

@daxim如果'#你的代码'部分花费了超过20秒的时间,它会发生漂移。为了防止漂移,它需要'sleep(($ interval - (time - $ start))%$ interval)',其中'$ interval'是二十。 – 2010-09-20 13:24:12

+0

@daxim当然,每20分钟可能有一秒钟的漂移。 – 2010-09-20 15:08:12

7

虽然sleep功能将用于某些应用工作,如果你正在试图做“每20秒,永远”,那么你最好使用外部工具像cron

除了已经提到的可能的漂移问题之外,如果您的sleep脚本退出(预期或以其他方式),那么它在下一个20秒时间内不会再运行。

@Blrfl是正确的,我觉得好笑。也就是说,这很容易克服。

* * * * * /path/to/script.pl 
* * * * * sleep 20 && /path/to/script.pl 
* * * * * sleep 40 && /path/to/script.pl 

你也可以采取将在脚本中的有限数量的睡眠循环,并利用cron来运行它每隔X分钟,覆盖脚本死亡的情况下的混合方法。任何比20秒更频繁的事情,我肯定会采取这种方法。

+3

POSIX'cron'不会执行分钟分辨率。 – Blrfl 2010-09-20 17:00:19

5

建立一个SIGALRM处理程序,并给自己发送信号,每隔20秒alarm(见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解决方案。

选择合适的解决方案取决于您需要定期执行哪种任务,而您没有指定。

2

Schedule::ByClock

#!/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; 
} 

所有的告诫也有人指出仍然适用,但我认为该模块整齐。

+0

@BugShotGG您还需要一台运行Perl的计算机。 – 2017-07-19 17:11:30

1

围棋与..

while() { 
    sleep 20; 
    #Code here 
} 
0
#!/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/> 
+0

可能有些注释会受到欢迎。最好的祝福 – YakovL 2017-09-05 13:32:50