如何从IPC :: Run3测试退出状态

时间:2016-11-24 01:52:41

标签: perl exit-code perl-ipc-run

我试图测试Perl模块IPC :: Run3,但很难检查命令是否失败或成功。
我知道IPC :: Run3会在其参数出错的情况下发出退出代码,但是如果参数正常但命令不存在呢?我该如何测试以下示例?

有一个子程序来调用Run3

sub runRun3 {

    my $cmd = shift;
    my ($stdout, $stderr);

    run3($cmd, \undef, \$stdout, \$stderr);

#   if( $? == -1 ) {
    if (! $stdout and ! $stderr) {
        die "Something is wrong";
    } else {
        print "OK \n";
    }

}

当执行下面的命令$cmds[0]时(* nix系统的ls命令),它按预期打印OK,但是使用命令$cmds[1]它只是说{{1} }}。 通过对退出代码的测试,我希望它能够打印No such file or directory at ./testrun3.pl line 18

Something is wrong

或者在这种情况下,IPC :: Run3的最佳替代方案是什么?这只是对过程的过度简化,但最终我想在更复杂的情况下捕获STDERR和STDOUT。

感谢。

1 个答案:

答案 0 :(得分:2)

要经过几点。

首先,对于直接问题,IPC::Run3文档告诉我们

  如果已回复run3来回system-1处理文件句柄出错,则

run3会引发异常。否则返回true。它保留$?完整,以检查退出和等待状态。

您提出的错误属于那种类型,您需要eval调用以捕获该异常

use warnings 'all';
use strict;
use feature 'say';

my ($stdout, $stderr);

my @cmd = ("ls", "-l");

eval { run3 \@cmd, \undef, \$stdout, \$stderr };
if    ( $@        ) { print "Error: $@";                     }
elsif ( $? & 0x7F ) { say "Killed by signal ".( $? & 0x7F ); }
elsif ( $? >> 8   ) { say "Exited with error ".( $? >> 8 );  }
else                { say "Completed successfully";          }

现在,您可以在if ($@) { }块内打印自己的消息,此时发生基础system无法执行的错误。例如,当调用不存在的程序时。

此处$@eval相关,而$?system相关。因此,如果run3没有问题且$@为假,我们会检查system本身的状态,从而检查$?。来自docs

  

请注意,run3的真实返回值并不意味着该命令   有一个成功的退出代码。因此,您应该始终检查$?

对于变量$@$?,请参阅General Variables in perlvar以及systemeval页。

这样做的最小版本是删除eval(以及$@检查),如果die出现问题,该程序会run3,这应该是罕见的,并且检查(并打印)$?的值。

关于run3界面的说明。对于\@cmd,它期望@cmd包含一个分为单词的命令,第一个元素是程序,其余参数。在$cmd接口支持的字符串中写入命令与在数组中写入命令之间存在差异。有关说明,请参阅system

哪种替代方案最适合您,取决于您的确切需求。这里有一些选择。也许首先尝试IPC::System::Simple(但在拼盘上没有STDERR)。为了清晰地捕获各种输出Capture::Tiny是很棒的。另一方面,IPC::Run有更大的权力。