2

我正在尝试测试 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]下面的ls命令(*nix 系统的命令)时,它会OK按预期打印,但使用命令$cmds[1]它只是说No such file or directory at ./testrun3.pl line 18. 通过对退出代码的测试,我希望它打印出来Something is wrong

#!/usr/bin/perl

use warnings;
use strict;

use IPC::Run3;

my @cmds = qw(ls silly);

runRun3($cmds[0]);
runRun3($cmds[1]);

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

谢谢。

4

1 回答 1

2

有几点要经过。

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

run3system如果包装的调用返回-1run3文件句柄的处理出现任何问题,则抛出异常。否则返回真。它$?完好无损地检查退出和等待状态。

您询问的错误属于那种类型,您需要评估调用以捕获该异常

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 ($@) { }的错误发生时,您现在可以在块内打印自己的消息。例如调用不存在的程序时。

这里$@涉及到evalwhile $?to system。所以如果run3没有问题并且$@是假的,接下来我们检查system自身的状态,因此$?. 来自文档

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

有关变量$@$?请参阅perlvarsystemeval页面中的通用变量。

一个最小的版本是删除eval(和$@检查)并期望程序die如果run3有问题,什么应该是罕见的,并检查(和打印)$?.

关于run3界面的说明。它\@cmd期望@cmd包含一个分解成单词的命令,第一个元素是程序,其余的参数。$cmd在接口支持的字符串和数组中编写命令是有区别的。参见系统解释。

哪种选择最适合您取决于您​​的确切需求。这里有一些选项。也许首先尝试IPC::System::Simple(但STDERR盘片上没有)。对于干净地捕获各种输出Capture::Tiny非常棒。在另一端有IPC::Run以获得更大的功率。

于 2016-11-24T02:18:18.383 回答