Perl как правилно да обработва системни команди (включително изчакване с унищожаване и улавяне на RC/STDERR/STDOUT)

От Perl скрипт искам да изпълня различни системни команди и да обработя изхода в моя скрипт.

Скриптът ще се стартира автоматично, така че искам да се уверя, че няма команди, които висят и т.н.

Отворен съм за всякакъв вид обратна връзка.

Моите изисквания за изпълнение на командата:

  • Изчакване -> Ако командата се изпълнява по-дълго от XX секунди, тя трябва да убие процеса(ите) си
  • Ако командата върне информация, не трябва да чака края на времето за изчакване
  • Искам да уловя състоянието на изход, STDERR, STDOUT в скрипта.

Ето един пример, който разработих от друг въпрос на stackoverflow: Убийте увиснал дъщерен процес

Какво не ми работи в момента:

  • не може да улови изходния статус на изпълнената команда
  • не може да улови 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