Как я могу завершить системную команду с предупреждением в Perl?

Я работаю ниже фрагмента кода в Windows. Сервер начинает слушать непрерывно после чтения от клиента. Я хочу завершить эту команду после периода времени.

Если я использую предупреждение () вызов функции в main.pl, затем это завершает целую программу Perl (здесь main.pl), таким образом, я назвал эту системную команду путем размещения его в отдельный файл Perl и вызова этого файла Perl (alarm.pl) в исходном Файле Perl с помощью системной команды.

Но таким образом я не мог взять вывод этого system() не звоните ни в исходный Файл Perl, ни в названный один Файл Perl.

Мог кто-либо сообщать мне способ завершить a system() назовите или возьмите вывод таким образом, я использовал выше?

main.pl

my @output = system("alarm.pl");
print"one iperf completed\n";

open FILE, ">display.txt" or die $!; 
print FILE @output_1; 
close FILE;

alarm.pl

alarm 30;
my @output_1 = readpipe("adb shell cd /data/app; ./iperf -u -s -p 5001");

open FILE, ">display.txt" or die $!; 
print FILE @output_1; 
close FILE;

Обоими способами display.txt всегда пусто.

8
задан Sinan Ünür 1 April 2010 в 19:28
поделиться

3 ответа

Можно использовать "timeout -n" для упаковки ваших команд, если это уже распространено в вашей системе.

-2
ответ дан 5 December 2019 в 07:11
поделиться

Здесь есть несколько отдельных вопросов.

Во-первых, чтобы alarm не убил ваш скрипт, вам нужно обработать сигнал ALRM. См. документацию по alarm. Для этого вам не должно понадобиться два скрипта.

Во-вторых, system не перехватывает вывод. Вам нужен один из вариантов backtick или pipe, если вы хотите это сделать. Ответы на этот вопрос уже есть на Stackoverflow.

В-третьих, если alarm.pl помещает что-либо в display.txt, вы отбрасываете это в main.pl, когда снова открываете файл в режиме записи. Вам нужно создать файл только в одном месте. Когда вы избавитесь от лишнего скрипта, у вас не будет этой проблемы.

Недавно у меня были проблемы с alarm и system, но переход на IPC::System::Simple это исправил.

Удачи, :)

15
ответ дан 5 December 2019 в 07:11
поделиться

О чем я, черт возьми, думал? Для этой задачи вам не нужен фоновый процесс. Вам просто нужно следовать примеру функции perldoc -f alarm и заключить свой чувствительный ко времени код в блок eval .

my $command = "adb shell cd /data/app; ./iperf -u -s -p 5001";
my @output;
eval {
    local $SIG{ALRM} = sub { die "Timeout\n" };
    alarm 30;
    @output = `$command`;
    alarm 0;
};
if ($@) {
    warn "$command timed out.\n";
} else {
    print "$command successful. Output was:\n", @output;
}

Внутри блока eval вы можете фиксировать свой вывод обычным способом (с помощью обратных кавычек или qx () или readpipe ). Хотя, если время вызова истечет, выхода не будет.

Если вам не нужен вывод (или вы не против взломать какое-то межпроцессное взаимодействие вместе), почти защищенная от идиота альтернатива - установить будильник и запустить системный вызов в дочернем процессе. .

$command = "adb shell cd /data/app; ./iperf -u -s -p 5001";
if (($pid = fork()) == 0) {
    # child process
    $SIG{ALRM} = sub { die "Timeout\n" }; # handling SIGALRM in child is optional
    alarm 30;
    my $c = system($command);
    alarm 0;
    exit $c >> 8;  # if you want to capture the exit status
}
# parent
waitpid $pid, 0;

waitpid вернется, когда команда system ребенка будет завершена, или , когда сработает будильник ребенка и убьет ребенка. $? будет содержать код выхода системного вызова или что-то еще (142 в моей системе) для необработанного SIGALRM или 255, если ваш обработчик SIGALRM вызывает die .

8
ответ дан 5 December 2019 в 07:11
поделиться
Другие вопросы по тегам:

Похожие вопросы: