Обработка вывода зависшего процесса - PullRequest
2 голосов
/ 10 мая 2011

Я хочу запустить некоторые тестовые исполняемые файлы со скриптом Perl, проанализировать их STDOUT и вернуть значение выхода в зависимости от того, что содержится в STDOUT. Я не очень знаком с Perl, так что это было немного сложно.

Проблема, с которой я сталкиваюсь, заключается в том, чтобы мой скрипт на Perl получал все, что мог, даже если исполняемые файлы теста зависали или зависали.

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

Моя (вероятно, наивная) версия получения результатов теста такова.

#!/usr/bin/perl
use strict;
use warnings;

my @output;

eval {
   local $SIG{ALRM} = sub {die "alarm\n"};
   alarm 15;
   @output = `testExecutable`;
   alarm 0;
};

if ($@) {
  die unless $@ eq "alarm\n";
  print "timed out\n";
}
else {
  print "didn't time out\n";
}

print @output;

По сути, мне нужно выполнить testExecutable таким образом, чтобы я мог получить доступ к любым данным, которые он выводит до срабатывания тревоги, а затем уничтожить процесс testExecutable в моем обработчике тревоги.

При необходимости я могу изменить исполняемые файлы теста. Оглядываясь вокруг, кажется, что буферизация может вызывать некоторую озабоченность.

Ответы [ 2 ]

1 голос
/ 10 мая 2011

Записать вывод внешней команды в файл и прочитать файл после завершения процесса (обычно или по истечении времени ожидания).Как сказал Содвед, лучше, если вы сможете заставить внешнюю программу часто сбрасывать свои выходные данные.

my $output_file = '/tmp/foo';
eval {
   local $SIG{ALRM} = sub {die "alarm\n"};
   alarm 15;
   system("testExecutable > $output_file 2>&1");
   alarm 0;
};

# whether successful or not, there could be output in $output_file ...
open my $fh, '<', $output_file;
@output = <$fh>;
close $fh;
unlink $output_file;
1 голос
/ 10 мая 2011

Ваша проблема в том, что использование оператора backquote заполняет вашу переменную perl только после завершения.Так что вместо этого вы должны читать из Perl-канала.Так что-то вроде этого:

#!/usr/bin/env perl
use strict;
use warnings;

my @output;

eval {
    local $SIG{ALRM} = sub {die "alarm\n"};
    alarm 15;
    open my $pipe_handle, '-|', 'testExecutable' or die "open error: $!";
    while (my $line = <$pipe_handle>) {
        push @output, $line;
    }
    close $pipe_handle;
    alarm 0;
};

if ($?) {
    print "testProgram failed\n";
} elsif ($@) {
    die unless $@ eq "alarm\n";
    print "timed out\n";
} else {
    print "didn't time out\n";
}

print @output;

Имейте в виду, что может происходить некоторая буферизация, поэтому вы все равно можете пропустить некоторые выходные данные.$? для проверки состояния детской программы

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...