Just been trying to create a Perl script to run ping and return results
#!/usr/bin/perl
use strict;
# this is a heap of notes to try and come to grips with Perl
# a bit better.
#
# Looks at how the system() call works
#
# How to build the command arguments to get
# shell redirection working inside system()
#
# What the return value from system() means and how return it
#
# Using bitwise `&' and bitwise `>>' to pull
# the correct value from the system() return value
#
my $down = 1; # in perl 1 is true 0 is false -1 is also true
# undefined is false
# e.g. perl -e 'if($blah){ print "It is true\n" };'
# prints nothing
# defined is true
# e.g. perl -e 'my $blah="Anything"; if($blah) {print "It is true\n"};'
# returns It is true
#
my $sleep = 1; # time in seconds for loop to sleep
my $host = "220.233.0.3"; # my ISP's DNS Server
# successful ping returns 0
# failed ping reply returns 1
#$host = "192.168.1.1"; # bogus IP to test ping exit value
# system() returns 256
# equals ping's exit value of 1
#$host = "www.notahostblahlahlah.com";
# bogus hostname to test ping exit value
# returns "ping: unknown host www.notahostblahlahlah.com"
# system() returns 512 ( 100 000 000 )
# equals child (ping's) exit value of 2
while($down) {
# for some reason I couldn't give the recommended array of args
# @args = ( "ping", "-c 2", "-W 2", $host, '2>&1 > /dev/null');
# this returns "ping: unknown host 2>&1 > /dev/null"
# this works however if it's one argument only
my @args = ('ping -c 2 -W 4 ' . $host . ' 2>&1 > /dev/null');
# this test is to trigger the -1 if block
# @args = ("badjh");
# returns "failed: No such file or directory"
print "Start Ping\n";
system(@args) ;
print "End Ping\n";
# don't do the normal
# system(@args) == 0 or die "Blah blach $!\n";
# because we want to test $? as below
# can't do a succesful bit shift on -1
# e.g.
# perl -e 'print -1 >> 8'
# returns: "16777215"
#
print "Checking/Converting return value $?\n";
if ($? == -1) {
print "failed: $!\n";
$down = 0; # it's still down continue loop and ping test
} elsif ( $? & 127 ) {
# the docs (perldoc perlfaq8) say re system() calls return value:
#
# 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).
#
# this section of the if statement code checks
# for signal the process was killed by
# try running this script and pressing control C
# to trigger this block
#
# so my question from reading the docs was:
# if you have the low 7 doing the signal process bit
# and the high 8 doing the called programs exit value
# what is that bit doing in the middle?
#
# e.g.
# Bits number from lowest value (right) to highest value (Left)
# 16 15 14 13 12 10 09 08 07 06 05 04 03 02 01
# |-----high 8 ------| ?? |-------low 7------|
#
# the answer is that number eight bit is
# the "core dumped" bit as this code from the web
# shows
#
printf "child died with signal %d, %s coredump\n",
($? & 127), ($? & 128) ? 'with' : 'without';
# so if the binary value has the 8th bit set
# it indicates a core dump occurred
#
# we don't need to do any bitwise shifting to get at the low 7 bits
# because they return the right values unmoved so only `&' is needed
#
# the eight bit is the same because it's either on or off
#
# the high 8 need shifting because we want the number as if it was
# in the same position as low 7
# (huh? it's too late at night I'm going to bed)
} else {
# we have gotten to this block because the system() calls child
# hasn't coredumped or been killed by an external signal
# and it has completed and exited returning a exit value
#
# hopefully zero and success but it could be
# any number of other result
# we are only interested in the high 8 bits
# that system() has returned on behalf of the child process
#
# a system() return value of 256 equals in 16 bit binary:
# |high 8| |low 7|
# 0000000100000000
#
# we need to shift the high eight right to
# make it return the correct value
# i.e. the first high 8 bit becomes the lowest bit
#
my $exit_value = $? >> 8;
# in effect we are doing the following
# 0000000100000000
# original system() return value is 256
# so we are now shifting
# the bits right >> 8 times
# 0000000010000000 shifted 1 bit to right
# 0000000001000000 shifted 2 bits to right
# 0000000000100000 etc
# 0000000000010000
# 0000000000001000
# 0000000000000100
# 0000000000000010
# 0000000000000001
# shifted 8 bits to right return value becomes 1
# because the first bits possible values are 0 or 1
# and this is set as 1 so it's 1 ok?
# This is a table showing the possible
# range of numbers that can occur
# as each bit bit is set going from right to left
#
# (16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1)
#
# 1st bit set value 1 or not set 0 (0=0 1=1)
# 2nd bit values 2-3 (2=10 3=11)
# 3rd bit values 4-7 (4=100 5=101 6=110 7=111)
# 4rd bit values 8-15 (8=1000 ... 15=1111)
# 5th bit values 16-31 (etc etc)
# 6th bit values 32-63
# 7th bit values 64-127
# 8th bit values 128-255
# 9th bit values 256-511
# 10th bit values 512-1023
# 11th bit values 1024-2047
# 12th bit values 2048-4095
# 13th bit values 4096-8191
# 14th bit values 8192-16383
# 15th bit set possible values ranges are 16384-32767
# 16th bit value 32768-65535
printf "child exited with value %d\n", $exit_value ;
if ($exit_value == 0) {
print "Successful ping exiting\n";
$down = 0;
}
}
sleep $sleep;
}
Yes; but what do the numbers returned mean?
That depends on what the system() call is launching. Each program returns a different return result.
For the ping example above: Try the following in bash shell
ping localhost
echo $?
returns 0
ping ahostthatresolvestoanIPbutWontReply
echo $?
returns 1
ping adjflkajlkd
echo $?
returns 2