2010-09-20 5 views
10

Wie kann ich Perl mitteilen, dass alle 20 Sekunden ein Code ausgeführt wird?Wie kann ich Perl sagen, dass er alle 20 Sekunden einen Code ausführen soll?

+7

Um die Menschen nach unten stimmrechts diese Frage, stoppen und um es für ein paar Minuten denken. Eine einfache Antwort wie "Schlaf 20;" ist nur eine Teillösung. –

+1

@Chas. - Das Problem ist, dass die Frage das nicht explizit spezifiziert (siehe Ether/Blrfl Kommentare zur Antwort). Daher ist die Frage schlecht, auch wenn das, was gefragt wird, nicht ist. – DVK

+2

@DVK Ja, es gibt alle Arten von Komplikationen, die auftreten (sollte der Code alle 20 Sekunden mit Überlappungen, ohne Überlappungen, an Zwanzig-Sekunden-Grenzen, an der 0., 20. und 40. Sekunde einer Minute usw. ausgeführt werden). Dies sind alles Verbesserungen an der Frage, die benötigt werden, aber Downstimmen werden nicht die Verfeinerungen erhalten, besonders ohne dass jemand kommentiert, warum es keine sehr gute Frage ist. –

Antwort

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

Was passiert, wenn "Ihr Code hier" 19 Sekunden dauert? – Ether

+3

Das hängt davon ab. Muss der Code an 20-Sekunden-Grenzen beginnen, oder sollten zwischen dem letzten Iterationsabschluss und dem Start des nächsten Iterationsschritts 20 Sekunden liegen? – Blrfl

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

Upvote: leidet nicht unter Drift. – daxim

+3

@daxim Es leidet unter Drift, wenn der '#your code' Teil länger als 20 Sekunden dauert. Um Drift zu vermeiden, müsste es "sleep (($ interval - (time - $ start))% $ interval) sein, wobei $ interval 20 ist. –

+0

@daxim Natürlich leidet das an einer möglichen Abweichung von nur einer Sekunde pro Zwanzig. –

7

Während die sleep Funktion für einige Anwendungen funktionieren wird, wenn Sie versuchen, „alle 20 Sekunden, für immer“ zu tun, dann sind Sie besser dran wie cron ein externes Programm.

Zusätzlich zu dem bereits erwähnten Problem der Drift, wenn Ihr sleep Skript (erwartet oder nicht) ausläuft, wird es bei der nächsten 20-Sekunden-Marke nicht erneut ausgeführt.

@blrfl ist richtig, und ich fühle mich schüchtern. Das heißt, es ist leicht genug zu überwinden.

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

könnten Sie auch einen Hybrid-Ansatz von einer begrenzten Zählung Schlafschleife im Skript setzen und mit dem Cron es alle X Minuten laufen, den Fall von Skript Tod abdeckt. Etwas häufiger als 20 Sekunden, würde ich definitiv diesen Ansatz nehmen.

+3

POSIX 'cron' macht keine Sub-Minuten-Auflösung. – Blrfl

5

eine SIGALRM Handler, Einstellungen und selbst ein Signal alle 20 Sekunden mit alarm (siehe perldoc -f alarm) senden:

$SIG{ALRM} = sub { 
    # set up the next signal for 20 seconds from now 
    alarm 20; 

    # do whatever needs to be done 
    # ... 
}; 

Diese Drift im Laufe der Zeit erfahren werden, da jedes Signal um bis zu einem zweiten verzögert werden kann, ; Wenn dies wichtig ist, richten Sie stattdessen einen Cron-Job ein. Darüber hinaus wird noch mehr Drift auftreten, wenn Ihr anderer Code mehr als 20 Sekunden zum Ausführen benötigt, da nur ein Timer gleichzeitig zählen kann. Sie könnten das umgehen, indem Sie Threads erzeugen, aber zu diesem Zeitpunkt wäre ich bereits zu einer einfachen Cron-Lösung zurückgekehrt.

Die Auswahl der richtigen Lösung hängt davon ab, welche Art von Aufgabe Sie regelmäßig ausführen müssen, die Sie nicht angegeben haben.

2

Siehe 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; 
} 

Alle Einsprüche andere gelten weiterhin darauf hingewiesen, aber ich denke, das Modul ordentlich ist.

+0

@BugShotGG Sie benötigen auch einen Computer, auf dem Perl ausgeführt wird. –

1

Gehen Sie mit ..

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"; 

Ausgang:

loop1 
loop2 
loop3 
loop4 
loop5 
loop6 
loop7 
loop8 
loop9 
loop10 
<heartbeat/> 
loop11 
loop12 
loop13 
loop14 
loop15 
loop16 
loop17 
loop18 
loop19 
loop20 
<heartbeat/> 
+0

Wahrscheinlich werden einige Anmerkungen begrüßt. Freundliche Grüße – YakovL

Verwandte Themen