Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does my Perl script return a zero return code when I explicitly call exit with a non-zero parameter?

I have a Perl script which calls another script. The Perl script should be propagating the script's return code but seems to be returning zero to its caller (a Java application) desipte the explicit call to exit $scriptReturnCode.

Code and output as follows (I realise that <=> could/should be != but that's what I have):

print "INFO: Calling ${scriptDirectory}/${script} ${args}"
$scriptReturnCode = system("${scriptDirectory}/${script} ${args}");

if ( $scriptReturnCode <=> 0 ) {
        print "ERROR: The script returned $scriptReturnCode\n";
        exit $scriptReturnCode;
} else {
        print "INFO: The script returned $scriptReturnCode.\n";
        exit 0;
}

The output I have from my Java is:

20/04/2010 14:40:01 - INFO: Calling /path/to/script/script.ksh arg1 arg2 
20/04/2010 14:40:01 - Could not find installer files <= this is from the script.ksh    
20/04/2010 14:40:01 - ERROR: The script returned 256
20/04/2010 14:40:01 - Command Finished. Exit Code: 0 <= this is the Java app.
like image 706
Tom Duckering Avatar asked Apr 21 '10 10:04

Tom Duckering


2 Answers

You need to shift the return code from system() call by 8 bits.

E.g. $exit_value = $? >> 8; # In your script the $? is $scriptReturnCode

From http://perldoc.perl.org/perlfaq8.html :

system() runs a command and returns exit status information (as a 16 bit value: the low 7 bits are the signal the process died from, if any, and the high 8 bits are the actual exit value

A more expanded code checking for coredumps as well could look like this:

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

UPDATE: As per ysth's excellent reminder, the exit codes are truncated at 8 (low) bits, so returning 256 instead of the intended 1 ends up as 0. Similarly, returning 257 ends up as 1.

like image 171
DVK Avatar answered Sep 23 '22 17:09

DVK


If capturing $? and shifting its value is too much trouble to remember, you can simplify that code by using IPC::System::Simple, which enhances system() and backticks with more error checking and diagnostics, e.g.:

use IPC::System::Simple qw(run EXIT_ANY);

my $command = "${scriptDirectory}/${script} ${args}";
print "INFO: Calling $command\n";

# runs command through a shell first; does not die on any exit value
run(EXIT_ANY, $command);
my $scriptReturnCode = $IPC::System::Simple::EXITVAL;
like image 23
Ether Avatar answered Sep 20 '22 17:09

Ether