В Perl есть ли способ перезапустить программу, запущенную в настоящее время изнутри?
Я запускаю программу в Perl, которая в какой-то момент оценивает данные в операторе if, вызываемом из подпрограммы, например
sub check_good {
if (!good) {
# exit this subroutine
# restart program
}
else {
# keep going
}
} # end sub
проблема у меня есть с выходом и перезапуском. Я знаю, что могу просто использовать exit 0;
чтобы выйти прямо, но, очевидно, это неправильно, если я хочу вернуться к началу. Я попытался вызвать подпрограмму, которая по существу запускает программу, но, конечно, после ее запуска она снова вернется к этой точке.
Я думал о поместить его в цикл while, но это означало бы поместить весь файл в цикл, и это было бы очень непрактично.
Я на самом деле не знаю, возможно ли это, поэтому любой вход будет отличным.
3 ответов
если вы не меняли @ARGV
, или вы держите его копию, вы могли бы сделать что-то вроде exec($^X, , @ARGV)
.
$^X
и (или
$EXECUTABLE_NAME
и $PROGRAM_NAME
, см. комментарий Брайана ниже) являются текущим интерпретатором perl и текущим скриптом perl соответственно.
альтернативой было бы всегда иметь два процесса: супервизор и работник.
рефакторинг всей вашей логики в подпрограмму под названием run
(или main
или любой другой). Whn ваша реальная логика обнаруживает, что ей нужно перезапустить, она должна выйти с предопределенным ненулевым кодом выхода (например, 1).
тогда ваш основной скрипт и супервизор будут выглядеть так:
if (my $worker = fork) {
# child process
run(@ARGV);
exit 0;
}
# supervisor process
waitpid $worker;
my $status = ($? >> 8);
if ($status == 1) { ... restart .. }
exit $status; # propagate exit code...
в простом сценарии, где вы просто хотите перезапустить один раз, это может быть немного перебор. Но если вам в любой момент нужно иметь возможность обрабатывать другие сценарии ошибок, этот метод может быть предпочтительным.
например, если код выхода равен 255, это означает, что основной скрипт называется die(). В этом случае может потребоваться реализовать некоторую процедуру принятия решения для перезапуска сценария, игнорирования ошибки или эскалации проблемы.
существует довольно много модулей по CPAN, реализующих таких супервизоров. Proc:: Launcher один из них и на странице руководства подробно обсуждаются соответствующие работы. (Я никогда не использовал Proc::Launcher, в основном из-за этого обсуждения я ссылаюсь на него)
ничто не мешает тебе называть system
на себя. Что-то вроде этого (явно нуждается в аккуратности), где я передаю аргумент командной строки, чтобы предотвратить вызов кода навсегда.
#!/usr/bin/perl
use strict;
use warnings;
print "Starting...\n";
sleep 5;
if (! @ARGV) {
print "Start myself again...\n";
system("./sleep.pl secondgo");
print "...and die now\n";
exit;
} elsif ((@ARGV) && $ARGV[0] eq "secondgo") {
print "Just going to die straightaway this time\n";
exit;
}