Perl, как правильно обрабатывать системные команды (включая тайм-аут с Kill и захват RC / STDERR / STDOUT)

Из сценария Perl я хочу выполнять различные системные команды и обрабатывать вывод в моем сценарии.

Скрипт запустится автоматически, поэтому я хочу убедиться, что никакие команды не зависают и т. Д.

Я открыт для любых отзывов.

Мои требования к выполнению команды:

  • Тайм-аут -> Если команда выполняется дольше XX секунд, она должна убить свой процесс (ы)
  • Если команда возвращает информацию, ей не нужно ждать окончания тайм-аута.
  • Я хочу зафиксировать статус выхода, STDERR, STDOUT в скрипте.

Вот пример, который я разработал из другого вопроса о переполнении стека: Убить зависший дочерний процесс

Что у меня не работает на данный момент:

  • не может зафиксировать статус выхода выполненной команды
  • не может захватить STDERR выполненной команды

Код:

my $cmd = "sleep 15"; # other tests i use -> "echo bla" and "alkjdsf"
my $TIMEOUT = 10;

my $pid = open my $proc, '-|', "$cmd";

if (fork() == 0) {
    my $poor_mans_alarm = "sleep 1,kill 0,$pid ||exit for 1..$TIMEOUT;kill 9,$pid";
    # run poor man's alarm in a background process
    exec($^X, '-e', "$poor_mans_alarm");
}

my $process_output = "";
while (<$proc>) {
   $process_output .= $_;
}

Если у вас есть трюк с этим кодом или вы порекомендуете совершенно другое решение, дайте мне знать.

Спасибо и ура



Дополнение:

Есть рабочий пример с IPC :: Open3, но для будущих читателей, пожалуйста, ознакомьтесь с IPC :: Run, в котором включена функция тайм-аута, как упоминал Джеймс Грин.

Рабочий пример с IPC :: Open3:

my $pid = open3(\*WRITE, \*READ,\*ERROR,"$command");

if (fork() == 0) {
    my $poor_mans_alarm = "sleep 1,kill 0,$pid ||exit for 1..10;kill 9,$pid";
    # run poor man's alarm in a background process
    exec($^X, '-e', "$poor_mans_alarm");
}


# get all the STDOUT and STDERR from the Child.
while (<READ>) {
   $output .= $_;
}

while (<ERROR>) {
   $output .= $_;
}

waitpid($pid, 0);
if ($?) {
    $rc = $? >> 8;
    if ($rc != 1){
        print "Some error $?\n";
    }
}

person Martin B    schedule 26.06.2014    source источник


Ответы (1)


Похоже, что IPC::Run предоставляет почти все, что вам нужно, включая таймауты и захват как STDOUT, так и STDERR. Документы находятся по адресу https://metacpan.org/pod/IPC%3a%3aRun, включая некоторые примеры использования.

person James Green    schedule 26.06.2014