2010-09-20 79 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