从 GNU 并行获取退出状态值

Posted

技术标签:

【中文标题】从 GNU 并行获取退出状态值【英文标题】:Obtaining exit status values from GNU parallel 【发布时间】:2011-06-10 17:48:00 【问题描述】:

下面的 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); 

如何从各个命令中获取退出状态值?

【问题讨论】:

用 Perl 和退出代码重新标记 @pavel,GNU 并行,根据主题 【参考方案1】:

要获取各个作业的存在状态,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 文件将表明异常死亡。 (不过,您必须首先确保它不存在。)


更新

@Ole Tange 提到我上面提到的--joblog file 的限制,即没有通过信号记录死亡,已在版本 20110722 中解决。

【讨论】:

谢谢。我实际上在命令之后尝试了“echo $status”,但没有意识到它是“echo $?”。事实证明,我的并行版本没有 --joblog,但是“echo \$? > $i.res”(转义以避免 Perl 解释 $?)就像一个魅力!【参考方案2】:

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

【讨论】:

【参考方案3】:

如果你想避免使用包装器,你可以考虑:

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"

【讨论】:

【参考方案4】:

除了包装 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);

【讨论】:

以上是关于从 GNU 并行获取退出状态值的主要内容,如果未能解决你的问题,请参考以下文章

为啥标准输入上的 Gnu grep 退出状态始终为 0?

“错误:命令'x86_64-linux-gnu-gcc'失败,退出状态为1”在virtualenv中

致命错误:Python.h:没有这样的文件或目录错误:命令“x86_64-linux-gnu-gcc”失败,退出状态为 1

Simulink Stateflow:等待并行状态

从最后一个管道(stdin)获取退出代码

如何在 getline 管道中获取命令的退出状态?