我有一个使用IPC::Open3的小子程序(通常我使用Capture::Tiny),因为我只想使用核心Perl模块。此子例程是较大安装脚本的一部分。它捕获命令输出,错误和退出代码。它适用于带有Perl 5.10.1(IPC :: Open3 1.04)的Centos 6(和5),但它在使用Perl 5.18.1(IPC :: Open3 1.13)的Ubuntu 14 LTS上失败。有人可以向我解释为什么它在新的Perl上失败以及如何修复它。
sub _capture_output {
croak( '_capture_output() needs a $cmd and options' ) unless (@_ == 2);
my ($cmd, $param_href) = @_;
my $verbose = defined $param_href->{verbose} ? $param_href->{verbose} : 0; #default is silent
print "Report: COMMAND is: $cmd\n" if $verbose;
local $| = 1; #autoflush
my ( $in, $out, $err );
open my ($in_fh), '<', \$in;
open my ($out_fh), '>>', \$out;
open my ($err_fh), '>>', \$err;
my $pid = open3($in_fh, $out_fh, $err_fh, $cmd);
my $stdout = $out;
my $stderr = $err;
$stdout = '' if !defined $stdout;
$stderr = '' if !defined $stderr;
waitpid( $pid, 0 ) or die "$!\n";
my $exit = $? >> 8;
if ($verbose == 2) {
print 'STDOUT is: ', "$stdout", "\n", 'STDERR is: ', "$stderr", "\n", 'EXIT is: ', "$exit\n";
}
return $stdout, $stderr, $exit;
}
它在open3调用失败时出现错误:
Report: COMMAND is: plenv --version
Uncaught exception from user code:
open3: exec of plenv --version failed at ./Perlinstall.pm line 175.
IPC::Open3::_open3('open3', 'GLOB(0x27819a0)', 'GLOB(0x2781730)', 'GLOB(0x2781b68)', 'plenv --version') called at /usr/share/perl/5.18/IPC/Open3.pm line 250
当我在命令行上尝试此命令时,我得到相同的错误代码但错误不同。 Centos6:
$ plenv --version
-bash: plenv: command not found
$ echo $?
127
Ubuntu14:
$ plenv --version
No command 'plenv' found, did you mean:
Command 'p7env' from package 'libnss3-tools' (main)
plenv: command not found
$ echo $?
127
答案 0 :(得分:4)
您不清楚您认为问题是什么,但open3
的行为与记录一致。
它不会在失败时返回:它只是引发一个异常匹配/ ^ open3:/。
您尝试执行的程序不存在,因此open3
会抛出异常。我想你想知道为什么$?
没有设置以及为什么没有在$stderr
的句柄上打印任何内容,但这不应该是一个惊喜,因为程序从未运行。< / p>
请记住,exec
(由open3
使用)将绕过shell,如果命令是一个除了空格之外没有shell字符的字符串,那么你将得到与执行<不同的结果< / p>
plenv --version
# Same as: open3(..., ..., ..., 'plenv', '--version')
# Exception: Can't find plenv
和
plenv '--version'
# Same as: open3(..., ..., ..., '/bin/sh', '-c', q{plenv '--version'})
# Shell exits with an error in ($? >> 8)
您可以使用eval BLOCK
来捕获异常。