Управление параллельными процессами - PullRequest
0 голосов
/ 11 мая 2018

Я запускаю несколько сценариев bash из сценария Perl и хочу отслеживать их и регистрировать их поведение.

Я знаю, что могу сказать, работает ли процесс с kill 0, $pid, и могу ли я получить код выхода из $?, но, запустив несколько сценариев в фоновом режиме, я не могу связать значения $? с процессы, которые дали его в качестве кода выхода.

Как я могу запустить эти сценарии параллельно, но получить код завершения для каждого из них? Мне нужно что-то вроде proc_get_status из PHP.

Извините, что не указали код с самого начала. Я сократил код, поэтому важно увидеть.

use warnings;
use strict;

use IPC::Open3;
use IO::Handle;

my $timeLimit = 60*60; # some time limit not to be crossed
my $startTime = time();

my @commands  = (); # fill up with commands to be executed
my @processes = ();

foreach my $cmd (@commands) {
  my $stdout = IO::Handle->new;
  my $stderr = IO::Handle->new;
  my $pid = open3(undef, $stdout, $stderr, $cmd);
  push @processes, {"pid" => $pid, "out" => $stdout, "err" => $stderr, "cmd" => $fullcmd};
}

do {
  if (time() - $startTime > $timeLimit) {
    kill 2, $_->{pid} foreach (@processes);
    @processes = ();
    last;
  } else {
    for (my $i = 0; $i < @processes; $i++) {
      unless (kill 0, $processes[$i]) {
        # if it's not running, I would like to check the exit code and log it from here on.
        # also remove it from the array, thats why I used for and not foreach, so I can use splice later.
      }
    }
  }
} while (@processes > 0);

Ответы [ 3 ]

0 голосов
/ 11 мая 2018

Вы можете использовать wait и waitpid, чтобы получить статус отдельных детей. Документация perlipc дает несколько примеров в разделе «Сигналы».

Поскольку вы используете IPC :: Open3, в Синопсисе также есть пример использования waitpid ():

    my($wtr, $rdr, $err);
    use Symbol 'gensym'; $err = gensym;
    $pid = open3($wtr, $rdr, $err,
            'some cmd and args', 'optarg', ...);

    waitpid( $pid, 0 );
    my $child_exit_status = $? >> 8;
0 голосов
/ 11 мая 2018

Вы уже нашли способ хранения данных фоновых заданий в мини-объектах.Сделайте следующий шаг и попробуйте полнофункциональный пакет распараллеливания, например Forks::Super.Вы можете создавать объекты фонового процесса, которые затем можно запросить для их status и код выхода .Forks::Super поддерживает тайм-ауты процесса и open3 -подобный интерфейс .

use Forks::Super;
$Forks::Super::MAX_PROC = 10;   # optional, block while 10 jobs already running

...

foreach my $cmd (@commands) {
    my $job = fork {
         cmd => $cmd,              # run $cmd in background process
         child_fh => 'out,err',    # child STDOUT,STDERR available to parent
         timeout => $timeLimit     # kill the job after $timeLimit seconds
    };
    push @processes, $job;
}

while (@processes) {
    sleep 5;
    foreach my $job (@processes) {
        if ($job->is_complete) {
            $job->wait;
            my $exit_code = $job->status;
            my $output = $job->read_stdout;
            my $error = $job->read_stderr;
            # ... log status, output, error, $job->{cmd}, etc. ...
            $job->dispose;     # close filehandles and other clean up
        }
    }
    @processes = grep { !$_->is_reaped } @processes;
}
0 голосов
/ 11 мая 2018

Во-первых, взгляните на функцию Perl fork().Это был бы типичный способ, которым я делаю такие вещи.Здесь есть хорошее объяснение с примерами здесь .

Простой в использовании модуль разветвления предоставляется Parallel :: ForkManger .

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

Другой возможный способ - с GNU Parallel .parallel - очень мощный инструмент для параллельного запуска команд.С его помощью вы можете легко запускать и управлять несколькими командами и сценариями.У него есть опция ---joblog, которая может быть вам полезна.

Все эти подходы предоставляют способы получения кода выхода подпроцессов.В конце концов, лучший выбор зависит от вашей текущей реализации, которую вы не предоставили.

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