Получение значений статуса выхода из GNU parallel

Оболочка Perl ниже выполняет команды параллельно, сохраняя STDOUT и STDERR в файлы /tmp:

open(A,"|parallel"); 
for $i ("date", "ls", "pwd", "factor 17") { 
  print A "$i 1> '/tmp/$i.out' 2> '/tmp/$i.err'\n"; 
} 
close(A); 

Как получить значения статуса выхода из отдельных команд?


person Community    schedule 10.06.2011    source источник
comment
Ретег с Perl и код выхода   -  person Rob Raisch    schedule 10.06.2011
comment
@pavel, параллель с GNU, по теме   -  person ikegami    schedule 10.06.2011


Ответы (4)


Чтобы получить существующий статус отдельных заданий, parallel нужно будет куда-то записать информацию. Я не знаю, так это или нет. Если это не так, вы можете сделать это самостоятельно.

my %jobs = (
   "date"   => "date",
   "ls"     => "ls",
   "pwd"    => "pwd",
   "factor" => "factor 17",
);

open(my $parallel, "|parallel"); 
for my $id (keys(%jobs)) {
   print $parallel
      $jobs{$id}
      ." 1> '/tmp/$id.out'"
      ." 2> '/tmp/$id.err' ; "
      ."echo \$?"
      ." > '/tmp/$id.exit'\n"; 
} 

close($parallel); 

my $exit_status = $? >> 8;
if ($exit_status >= 255) {
    print("Failed\n");
} else {
    printf("%d failed jobs\n", $exit_status);
}

for my $id (keys(%jobs)) {
    ...grab output and exit code from files...
}

Обновление: я пошел и установил parallel.

У него есть опция --joblog {file}, которая создает отчет с кодами выхода. Он принимает - для имени файла, если вы хотите, чтобы он выводился в STDOUT.

Обратите внимание, что parallel не распознает ненормальную смерть по сигналу, поэтому это не включено в отчет --joblog. Используя решение, которое я опубликовал выше, отсутствующий файл .exit будет указывать на ненормальную смерть. (Однако вы должны убедиться, что его не существует в первую очередь.)

person ikegami    schedule 10.06.2011
comment
Спасибо. На самом деле я попробовал echo $status после команды, но не понял, что это было echo $?. Оказывается, в моей версии parallel нет --joblog, но echo \$? › $i.res (экранирование, чтобы избежать интерпретации Perl $?) работает как шарм! - person ; 11.06.2011

GNU Parallel 20110722 имеет выходное значение и сигнал в --joblog:

parallel --joblog /tmp/log false ::: a
cat /tmp/log
Seq     Host    Starttime       Runtime Send    Receive Exitval Signal  Command
1       :       1311332758      0       0       0       1       0       false a
person Ole Tange    schedule 22.07.2011

Если вы хотите избежать обертки, вы можете рассмотреть:

cat foo | parallel "{} >\$PARALLEL_SEQ.out 2>\$PARALLEL_SEQ.err; echo \$? >\$PARALLEL_SEQ.status"

Версия 20110422 или более поздняя делает его еще короче:

cat foo | parallel "{} >{#}.out 2>{#}.err; echo \$? >{#}.status"

Если ваши строки не содержат ', то это тоже должно работать:

cat foo | parallel "{} >'{}'.out 2>'{}'.err; echo \$? >'{}'.status"
person Ole Tange    schedule 11.06.2011

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

Например:

use Proc::Queue size => 10, qw(run_back);

my @pids;

for $i ("date", "ls", "pwd", "factor 17") {
  push @pids, run_back {
    open STDOUT, '>', '/tmp/$i.out';
    open STDERR, '>', '/tmp/$i.err';
    exec $i;
  }
}

for (@pids) {
  1 while waitfor($_, 0) <= 0;
  say "process $_ exit code: ", ($? >> 8);
}
person salva    schedule 22.07.2011