如何正确捕获unix命令的返回值?

时间:2013-08-14 05:13:00

标签: perl shell return-value

我无法将unix命令的返回值转换为perl变量。

Unix命令:

#nc -z 8.8.8.8 441; echo $?
1

Perl命令:

#perl -e 'my $pstate=`nc -z 8.8.8.8 441; echo $?`; print $pstate;'
0

所以perl命令似乎得到“无错误”的返回值?如何正确捕获* nix命令的返回值?

另一个例子:

#perl -e 'my $pstate=`ping -v 8.8.8.8 -c 1`; print $pstate;'
PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.

返回正确的值。那么我在第一次做错了什么呢?

2 个答案:

答案 0 :(得分:9)

变量在反引号内插,因此

中的$?
my $pstate=`nc -z 8.8.8.8 441; echo $?`

指的是Perl的$?,而不是shell的$?。 shell看到的是

nc -z 8.8.8.8 441 ; echo 0

要解决此问题,您可以转义shell命令

my $pstate=`nc -z 8.8.8.8 441; echo \$?`;

或使用单引号作为分隔符的qx运算符(这是“qx运算符规则中的插值”的一个例外)

my $pstate=qx'nc -z 8.8.8.8 441; echo $?';

或使用readpipe非插值引用构造

my $pstate= readpipe( 'nc -z 8.8.8.8 441; echo $?' );
my $pstate= readpipe( q{nc -z 8.8.8.8 441; echo $?} );

答案 1 :(得分:1)

另一种方法是使用IPC::Run3“允许您运行子进程并将stdin,stdout和/或stderr重定向到文件和perl数据结构”。

与系统类似,你可以检查$?之后以各种方式,包括换8,得到如下的实际退出代码:

if ($? == -1) {
print "failed to execute: $!\n";
}
elsif ($? & 127) {
printf "child died with signal %d, %s coredump\n",
($? & 127), ($? & 128) ? 'with' : 'without';
}
else {
printf "child exited with value %d\n", $? >> 8;
}

此块取自http://perldoc.perl.org/functions/system.html的系统文档,其中还提到了devnull所说的内容。任何时候我关心的不仅仅是关于qx或系统的问题,而是切换到IPC :: Run3,因为它可以轻松获取所有内容。