问题
I'm using Perl 5.10.1 on Ubuntu 11.04. I want Perl to execute a shell script and exit with the same code the shell script exits. But this isn't working for me ...
system($runCmd) or die("Failed to run \"$runCmd\": $!");
I have confirmed that running the "$runCmd" by itself returns an exit code of 255, but the "die" clause isn't getting invoked. How do I exit with the correct code or at least fail for non-success codes?
Another minor requirement is that I want the output from $runCmd to be printed to the screen.
回答1:
As perldoc -f die says, die
doesn't give a specific exit code (only a nonzero exit code). To get what you want, you'll need something like:
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";
}
回答2:
If system
returns 255
, you need an and
conditional.
system
returns zero on successful execution. Also, die
will modify your script's exit code. Instead warn
and return the last exit code like this:
system($cmd) and do {
warn "Failed to run $cmd. Exit code is $?";
exit $? >> 8;
};
In order to catch the program's output, use the backtick (`) operator:
my $output = `$cmd`;
if ($?) {
warn ...;
exit $? >> 8;
}
The backtick operator only captures STDOUT
, so for all error messages (which usually go to STDERR
) to be captured, modify $cmd
and append 2>&1
to it.
Notice the right shift by eight bits on the $?
global.
Credits go to @musiKk: The perl documentation on system() states how to properly retrieve the actual exit status.
回答3:
system($runCmd) or die("Failed to run \"$runCmd\": $!");
Unlike most Perl functions, system
returns false when it succeeds and true when it fails. This is completely backwards I know but it is just how it is.
You need "system() and" not "system() or". And you probably want $?
not $!
, although this can sometimes be tricky.
I have a minor aversion to
system(...) && die
because it screws up all the rest of || die
’s that normally make a continuous vertical double margin over on the right, I sometimes write
system(...) == 0 || die
so that they all line up correctly again.
回答4:
If system()'s seeming backwardness bothers you, you can always make it more palatable by doing something like:
my $err = system '/something/that/may/not/work';
if ($err) {
warn "@{[$! || 'undefined error']}\n";
exit $err >> 8;
}
Your $runCmd, BTW, if it prints to the screen (and this is run from the command line and you haven't redirected the output, etc.) will print to the screen. It's just that IT will print it to the screen. Perl won't be responsible for that or know (or care) what it's printing. If that's all you want, and you don't want to systematically analyse or manipulate the output of $runCmd, you're golden. Try it:
perl -e "system 'ls -Fahl'"
It also won't interfere with your $runCmd's STDOUT either. That'll go to your terminal too. For instance:
$ 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.
来源:https://stackoverflow.com/questions/7080434/getting-perl-to-return-the-correct-exit-code