我在Ubuntu 11.04上使用Perl 5.10.1。我希望Perl执行shell脚本并使用shell脚本退出的相同代码退出。但这对我不起作用......
system($runCmd) or die("Failed to run \"$runCmd\": $!");
我已经确认运行“$ runCmd”本身会返回退出代码255,但不会调用“die”子句。如何使用正确的代码退出,或者至少针对非成功代码失败?
另一个小要求是我希望$ runCmd的输出打印到屏幕上。
答案 0 :(得分:11)
正如perldoc -f die
所说,die
没有给出特定的退出代码(只有非零退出代码)。为了得到你想要的东西,你需要这样的东西:
my $exit_code=system($runCmd);
if($exit_code!=0)
{
print "Command $runCmd failed with an exit code of $exit_code.\n";
exit($exit_code >> 8);
}
else
{
print "Command $runCmd successful!\n";
}
答案 1 :(得分:9)
如果system
返回255
,则需要and
条件。
system
在成功执行时返回零。此外,die
将修改脚本的退出代码。而是warn
并返回最后一个退出代码,如下所示:
system($cmd) and do {
warn "Failed to run $cmd. Exit code is $?";
exit $? >> 8;
};
为了捕获程序的输出,请使用反引号(`)运算符:
my $output = `$cmd`;
if ($?) {
warn ...;
exit $? >> 8;
}
反引号操作符仅捕获STDOUT
,因此对于要捕获的所有错误消息(通常转到STDERR
),请修改$cmd
并将2>&1
附加到其中。
注意$?
全局右移8位。
致信@musiKk:perl documentation on system()
说明了如何正确检索实际退出状态。
答案 2 :(得分:5)
system($runCmd) or die("Failed to run \"$runCmd\": $!");
与大多数Perl函数不同,system
在成功时返回false,在失败时返回true。这完全是我所知道的倒退,但事实就是如此。
你需要“system()和”not“system()或”。你可能希望$?
不是$!
,尽管这有时候会很棘手。
我对
有一点厌恶system(...) && die
因为它搞砸了通常在右边连续垂直双边距的所有其余|| die
,我有时会写
system(...) == 0 || die
以便它们都能正确排列。
答案 3 :(得分:0)
如果系统()看似落后困扰你,你可以通过做类似的事情来使它变得更加可口:
my $err = system '/something/that/may/not/work';
if ($err) {
warn "@{[$! || 'undefined error']}\n";
exit $err >> 8;
}
你的$ runCmd,BTW,如果它打印到屏幕上(这是从命令行运行而你没有重定向输出等)将打印到屏幕上。只是IT会将其打印到屏幕上。 Perl不对此负责或知道(或关心)它的打印内容。如果这就是你想要的,并且你不想系统地分析或操纵$ runCmd的输出,你就是金色的。试试吧:
perl -e "system 'ls -Fahl'"
它也不会干扰你的$ runCmd的STDOUT。那也会到你的终端。例如:
$ perl -e "system 'ls -Fahl /dev/null/something' and die qq(fail: $! >> 8 == @{[$! >> 8]})"
ls: /dev/null/something: Not a directory
fail: 26205 >> 8 == 102 at -e line 1.
答案 4 :(得分:0)
我建议检查 $?
变量(也就是 $CHILD_ERROR
你是 use English;
双关语)。这样可以更彻底地检查您的 system()
调用结果。
要理解的是,$?
是一个 16 位字(艺术归功于 @ikegami):
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
| 15| 14| 13| 12| 11| 10| 9| 8| 7| 6| 5| 4| 3| 2| 1| 0|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
\-----------------------------/ \-/ \-------------------------/
Exit code core Signal that killed
(0..255) dumped (0..127)
(0..1)
system($runCmd);
if ($? == -1) { # Failed to start program / error of the wait(2) system call
die "Failed to execute '$runCmd': $!";
} elsif ($? & 127) { # Check for non-zero signal
die "'$runCmd' died with signal", ($? & 127), ($? & 128) ? 'with' : 'without', " coredump";
} else { # No kill signal, check exit code.
my $exit_code = $? >> 8; # This is the number you said to be 255.
# print "'$runCmd' exited with value ", $exit_code, "\n";
if ($exit_code == 255) {
die("Failed to run \"$runCmd\": $!");
} else {
# can do additional checks for other exit codes if desired
}
exit $exit_code;
}
如果您真的不想弄乱 $?
,还有一个值得注意的“替代方案”。基本上,只需使用 IPC::System::Simple。请注意,它不是核心模块,因此您需要安装它。
使用起来很简单:
use IPC::System::Simple qw(system); # system() will now die properly
my $exit_value = system($runCmd);
my $exit_value2 = system($runCmd,@args); # Alternative form that avoids shell if @args
如果您不想覆盖 system
,您可以改用 run
:
use IPC::System::Simple qw(run);
my $exit_value = run($runCmd);
my $exit_value2 = run($runCmd,@args);