http://www.perlmonks.org?node_id=768752

irah has asked for the wisdom of the Perl Monks concerning the following question:

Dear Monks,

The following code is used to check the status of the network. The logic is, I am executing ping command with two different IP address. If first one failure only, it will goto second one.

#!/usr/bin/perl use strict; use warnings; # register signal. $SIG{'INT'} = 'Handler'; # declaring variable. my ($ip1, $ip2, $to, $exit_value1, $exit_value2, $flag); # this flag is used to avoid the repeat # execution when execute the second ping # with second IP address. $flag=0; # initializing IP address. $ip1 = "192.168.0.0"; # first IP address $ip2 = "google.com"; # second IP address. # execute the ping with first IP address. do { eval { $exit_value1 = `ping $ip1`; } }; exit; # if it is working fine, exit the program. # execute the ping with second IP address. Exec: print "$ip2\n"; $flag=1; # reset the flag to avoid repeat # execute second ping with different IP address. do { eval { $exit_value2 = `ping $ip2`; } }; # it is a signal handle for SIGINT signal. sub Handler { # alert message to user. print "Caught SIGINT: $?\n"; # if the first ping command is failure, goto second, if (($? != 0) and ($flag == 0)) { goto Exec; } exit(0); }

The if condition in handler is true when the first ping failure. But the goto statement inside if condition does not working. Please tell me where I did the mistake?

Note: I used eval instead of setjmp. I don't get any error or warning message for that.

Replies are listed 'Best First'.
Re: Please help me in goto statement
by Corion (Patriarch) on Jun 05, 2009 at 11:19 UTC

    What do you mean by "But the goto statement inside if condition does not working."?

    What is the output of your script? Do you send a SIGINT to the child process? Are you aware of Net::Ping?

      Thanks for your input. Now I changed to working in Net::Ping module. I got what I want. Thanks.

Re: Please help me in goto statement
by JavaFan (Canon) on Jun 05, 2009 at 12:24 UTC
    I presume you got an error message of the form Exiting subroutine via goto. Which is what you are trying to do, and isn't allowed.

    I don't think you need the goto - I would check the return value of the eval, and exit if the eval succeeded. Or rather, only execute the second ping if the first failed. Something like this (untested):

    # # Generalize to multiple ips # my @ips = ("192.168.0.0", "google.com"); $SIG{INT} = sub { print "Caught SIGINT: $?\n"; die if $?; }; foreach my $ip (@ips) { print $ip, "\n"; last if eval {`ping $ip`; 1}; }
    Note that I do not wrap the eval in a pointless do construct, I'm not needing a flag variable, and I'm not storing the output of ping in a variable that I'm not going to use.
      Change
      last if eval {`ping $ip`; 1};
      to
      last if eval { `ping $ip`; !$? };
      and you now check the value returned by ping as well.
Re: Please help me in goto statement
by tcf03 (Deacon) on Jun 05, 2009 at 17:25 UTC
    You could do something like
    #!/usr/bin/perl use strict; use warnings; use Net::Ping; my $down; my $host = $ARGV[0]; my $host2 = $ARGV[1]; my $rc = ( PING($host) == 0 ) ? "$host is up" : ( PING($host2) == 0 ) ? "$host2 is up" : "Neither $host or $host2 are reachable"; print "$rc\n"; sub PING { my $host = shift; my $p = Net::Ping->new("icmp"); return ( $p->ping($host) ) ? 0 : 1; }
    Just want to note though that you could hit ports on each machine and it may be a bit more reliable than icmp.... To do that I use something like the following and you don't need to be root to run it ( assuming you are using a UNIX-ish OS...
    From perldoc Net::Ping If the "icmp" protocol is specified, the ping() method sends an icmp echo message to the remote host, which is what the UNIX ping program does. If the echoed message is received from the remote host and the echoed information is correct, the remote host is considered reachable. Specifying the "icmp" protocol requires that the program be run as root or that the program be setuid to root.
    #!/usr/bin/perl use strict; use IO::Socket::INET; use Getopt::Long; my @hosts = ""; my $timeout = "2"; #my $port = ""; my @ports = ""; my $opts = GetOptions( "host=s" => \@hosts, "port=s" => \@ports, "timeout=s" => \$timeout ); @hosts = split /,/, join( ',', @hosts ); die "usage: sp -h <host|IP> [ -h <host|IP> ] -p <port> [ -p <port> ]\n +" unless $hosts[1]; shift @ports; for my $host (@hosts) { next if $host eq ''; for my $port (@ports) { my $status = ( connection( $host, $port ) == 0 ) ? "Up" : +"Down"; my $line = sprintf(" %-20s %-5s %-1s", $host, $port, $stat +us); print $line . "\n"; } } ############## sub connection ############## { my $host = shift; my $tcp_port = shift; return ( IO::Socket::INET->new( Timeout => $timeout, PeerAddr => $host, PeerPort => $tcp_port, Proto => 'tcp' ) ) ? 0 : 1; } perl sp.pl -h google.com -h yahoo.com -p 80 google.com 80 Up yahoo.com 80 Up
    Ted
    --
    "That which we persist in doing becomes easier, not that the task itself has become easier, but that our ability to perform it has improved."
      --Ralph Waldo Emerson