Как я могу сказать Perl запускать код каждые 20 секунд?
Как я могу сказать Perl запускать код каждые 20 секунд?
Ответ 1
while (1) {
sleep 20;
<your code here>;
}
Ответ 2
for (;;) {
my $start = time;
# your code;
if ((my $remaining = 20 - (time - $start)) > 0) {
sleep $remaining;
}
}
Ответ 3
Хотя функция sleep
будет работать для некоторых целей, если вы пытаетесь выполнить "каждые 20 секунд, навсегда", тогда вам лучше использовать внешнюю утилиту, например cron
.
В дополнение к возможной проблеме дрифта, о которой уже упоминалось, если ваш sleep
script завершается (ожидается или иначе), то он не будет запускаться снова на следующей отметке в 20 секунд.
@Blrfl верен, и я чувствую себя застенчивым. Тем не менее, его достаточно легко преодолеть.
* * * * * /path/to/script.pl
* * * * * sleep 20 && /path/to/script.pl
* * * * * sleep 40 && /path/to/script.pl
Вы также можете использовать гибридный подход, заключающийся в том, чтобы положить ограниченный цикл ожидания счета в script и использовать cron для запуска его каждые X минут, охватывая случай смерти script. Что-нибудь более частые, чем 20 секунд, я бы определенно принял такой подход.
Ответ 4
Настройте обработчик 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.
Выбор правильного решения зависит от того, какую задачу вы должны выполнять периодически, что вы не указали.
Ответ 5
См. 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;
}
Все предостережения, о которых говорили другие, все еще применяются, но я думаю, что модуль опрятен.
Ответ 6
#!/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
Пойдите с..
while () {
sleep 20;
#Code here
}
Ответ 8
Лучше использовать некоторую библиотеку событий. Есть несколько вариантов:
IO :: Асинхронный :: Таймер :: Периодическая
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
и т.п.