Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Mike Lewis on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Exit codes for system call, work great execpt for rm 1

Status
Not open for further replies.

travs69

MIS
Dec 21, 2006
1,431
0
0
US
I running system command on a remote box (not my favorite thing to do but I deal with it) and all the commands come back correct except for the rm command. I wrote a simple test script
Code:
#!/usr/bin/perl

if (`rm -f /tmp/travis.txt`) { print "success\n"; } else
{ print "Failure\n"; }

This code prints "Failure" even when it is succesful and it prints "Failure" when it fails :), Any help is appreciated as I don't like to just assume that the rm is working.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[noevil]
Travis - Those who say it cannot be done are usually interrupted by someone else doing it; Give the wrong symptoms, get the wrong solutions;
 
So I found a way to get the exit like this $exit_value = $? >> 8;
but should I be using that on every command?

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[noevil]
Travis - Those who say it cannot be done are usually interrupted by someone else doing it; Give the wrong symptoms, get the wrong solutions;
 
You should generally only use `backticks` when your program actually cares about the text output of the command (its STDOUT). If your program only cares about the exit code, use system() instead, which returns the exit code (and presumably also puts it into $?).

Code:
if (system("rm -f /tmp/travis.txt") == 0) { print "success\n"; } else
{ print "Failure\n"; }

The reason your code was working/not working before was probably that, when programs exit with an error code, they usually send error text to STDERR which isn't returned in the backtick format (only STDOUT is). Programs that succeed generally write something to STDOUT. rm usually doesn't write anything to STDOUT on success, and only to STDERR on error. So your old if was checking if the backticks returned any true value.

Kirsle.net | My personal homepage
Code:
perl -e '$|=$i=1;print" oo\n<|>\n_|_";x:sleep$|;print"\b",$i++%2?"/":"_";goto x;'
 
so what is your suggestion for code where I need to use backticks (well.. I actually normal use qx and they are equal correct?) I'm just worried I'm not correctly capturing the output, and is there a qx version of system?

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[noevil]
Travis - Those who say it cannot be done are usually interrupted by someone else doing it; Give the wrong symptoms, get the wrong solutions;
 
system() executes a command and it returns the exit code (usually 0). The command's normal outputs (STDOUT/STDERR) will display in your terminal but this output isn't returned to the Perl script.

Backticks and qx{} execute a command and return its STDOUT output (but not STDERR; STDERR goes to your terminal and isn't returned to the Perl script). If you want the exit code when using backticks or qx{} you should use $?

Examples:

Code:
# get the output of a command
my $output = `rpm -q firefox`;
print "We got: $output (command exited with code: $?)\n\n";

my $output = `rpm -q openarena`;
print "We got: $output (command exited with code: $?)\n\n";

# only get the exit code if you don't care about the output
my $exit = system("rpm -q firefox");
print "Exit code: $exit\n";

my $exit = system("rpm -q openarena");
print "Exit code: $exit\n";

Running this code shows this on my system:

Code:
We got: firefox-3.5.5-1.fc12.i686
 (command exited with code: 0)

We got: package openarena is not installed
 (command exited with code: 256)

[red]firefox-3.5.5-1.fc12.i686[/red]
Exit code: 0
[red]package openarena is not installed[/red]
Exit code: 256

The red lines were printed to the terminal by rpm and were not sent to my Perl script in any way. Everything else was printed by Perl.

Kirsle.net | My personal homepage
Code:
perl -e '$|=$i=1;print" oo\n<|>\n_|_";x:sleep$|;print"\b",$i++%2?"/":"_";goto x;'
 
One more thing to note:

You can reroute STDERR into STDOUT in your commands, if you want the backticks or qx to collect ALL output (including STDERR) given by the command.

Code:
my $all_output = `traceroute google.com [red]2>>&1[/red]`;

This is unixish and might not work on Win32 (haven't tested it).

Kirsle.net | My personal homepage
Code:
perl -e '$|=$i=1;print" oo\n<|>\n_|_";x:sleep$|;print"\b",$i++%2?"/":"_";goto x;'
 
So what's with this explanation I keep seeing every where,
$? >> 8

They're bit shifting that right correct (easy for me to say when I don't necessarily understand the concept).

Thanks for your explanations though. I try and do everything naively through perl so I don't do many system calls (and when I used to I didn't bother to check the exit codes anyway :D )

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[noevil]
Travis - Those who say it cannot be done are usually interrupted by someone else doing it; Give the wrong symptoms, get the wrong solutions;
 
naively :) I'm pretty sure that even though I meant natively.. naively is correct also [afro2]

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[noevil]
Travis - Those who say it cannot be done are usually interrupted by someone else doing it; Give the wrong symptoms, get the wrong solutions;
 
Code:
$ perl -e 'print 256 >> 8, "\n"';
1

I guess it's something to do with how operating systems represent exit codes.

256 in binary is 100000000 (9 bits), so a bitshift to the right 8 bits moves each bit over 8 places, so you get 000000001 (or in decimal, 1).


If you really need to get picky about the exact number returned in an error code you'd do this; if all you care about is whether it ran okay or exited in error, all you need to do is see if it exited with 0 (success) or not.

A successful exit code is always 0.

Kirsle.net | My personal homepage
Code:
perl -e '$|=$i=1;print" oo\n<|>\n_|_";x:sleep$|;print"\b",$i++%2?"/":"_";goto x;'
 
Thanks again Kirsle

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[noevil]
Travis - Those who say it cannot be done are usually interrupted by someone else doing it; Give the wrong symptoms, get the wrong solutions;
 
Hopefully this explains it:

Code:
      $CHILD_ERROR
      $?      The status returned by the last pipe close, backtick (``)
              command, successful call to wait() or waitpid(), or from the
              system() operator.  This is just the 16-bit status word
              returned by the wait() system call (or else is made up to look
              like it).  Thus, the exit value of the subprocess is really
              ("$? >> 8"), and "$? & 127" gives which signal, if any, the
              process died from, and "$? & 128" reports whether there was a
              core dump.  (Mnemonic: similar to sh and ksh.)

So by using $? >> 8 you are just grabbing the first 8 bits of the 16-bit word stored in $?.

Annihilannic.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top