我试图测试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。
感谢。
答案 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以及system
和eval
页。
这样做的最小版本是删除eval
(以及$@
检查),如果die
出现问题,该程序会run3
,这应该是罕见的,并且检查(并打印)$?
的值。
关于run3
界面的说明。对于\@cmd
,它期望@cmd
包含一个分为单词的命令,第一个元素是程序,其余参数。在$cmd
接口支持的字符串中写入命令与在数组中写入命令之间存在差异。有关说明,请参阅system。
哪种替代方案最适合您,取决于您的确切需求。这里有一些选择。也许首先尝试IPC::System::Simple(但在拼盘上没有STDERR
)。为了清晰地捕获各种输出Capture::Tiny是很棒的。另一方面,IPC::Run有更大的权力。