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

I have created a Script that will ping IP's and report which are up and what are not. The problem that I am having is the output presented to me on the screen very messed up and I am not sure why. What is being displayed is exactly as follows 10.1.1.1 is alive 10.1.1.2 is alive 10.1.1.3 is alive 10.1.1.4 Here is the code
#!/usr/bin/perl use warnings; use Net::Ping; use Socket; $ipnumber ="128.135.75"; chomp $ipnumber; @iparray = map $ipnumber. ".$_\n",1..254 ; chomp $ipnumber; print @iparray; #open (ERRORLOG, ">errorlog"); #open (OFFLINE,">offline"); #open (ONLINE,">online"); my $proto = 'icmp'; my $def_timeout = '5'; my $bytes = '64'; my $p = Net::Ping->new($proto, $def_timeout , $bytes); foreach my $host (@iparray) { if ( $p->ping( $host )){ print " $host is alive "; } #foreach my $host (@iparray) { # $testing = $p $host; # print "$testing"; # print "$host offline " unless $p->ping($host,1); # print "$host online " unless $p->ping($host,0); # print ERRORLOG "$host offline " unless $p->ping($host,1); # print OFFLINE "$host"unless $p->ping($host,1); # print ONLINE "$host online" unless $p->ping($host,0); } $p->close();
Any ideas

Replies are listed 'Best First'.
Re: Pingger
by Trinary (Pilgrim) on Apr 26, 2001 at 01:42 UTC
    When you construct the @iparray, you put a newline after each IP. Then when you use the @iparray to print out $host is alive, the newline is in the middle of whatever line it is you're printing.

    Additionally, you have no newline at the end of the print " $host is alive "; line, thus garbling your output a bit.

    Take the \n out of your map, and put one in your print to get one correctly formatted result on each line.

Re: Pingger
by MeowChow (Vicar) on Apr 26, 2001 at 01:45 UTC
    I'm not sure I'm understanding your problem entirely, but try it this way:
    $ipnumber ="128.135.75."; @iparray = map $ipnumber.$_,1..254 ; # no chomps needed ... foreach my $host (@iparray) { if ( $p->ping($host)){ print "$host is alive\n"; } } ...
       MeowChow                                   
                   s aamecha.s a..a\u$&owag.print
Forking Pinger
by Clownburner (Monk) on Apr 26, 2001 at 07:25 UTC
    Interesting problem. I had a similar one myself, except I don't really care which ones are up, just which ones are down, and I needed the results as a percentage so I could graph them.

    I also discovered that trying to ping a huge number of hosts one at a time was painfully slow, so I wrote the following.

    Bear in mind that this program is designed to pull the list of targets from a MySQL database, you could easily modify it to read in a config file though. It also doesn't handle forking the most efficient way possible, in that it doesn't ALWAYS keep $maxforks children running, it just runs them in bursts of $maxforks, but I find it's plenty fast enough even when pinging several hundred targets. I also used the system call to ping instead since I couldn't install CPAN modules on the machine it was running on. Again, that's probably a three-minute change.

    Hope you find it interesting...
    #!/usr/bin/perl -- # # ForkingPinger # Pings a list of remote hosts and calculates an uptime # percentage based on the number of responses. If run in # interactive mode, lists the sites that failed. # # (C) 2001 James Mancini <wfe@networkavatar.com> # Please send copies of modifications or improvements to # the author! # # Released under the same terms as perl itself. # # THIS PROGRAM IS PROVIDED WITH NO WARRANTY - USE AT YOUR # OWN RISK. # # 21 Mar 2001 my $Version = "0.2.2 - beta"; use DBI; use Getopt::Long; use POSIX ":sys_wait_h"; $|++; #autoflush output for speed ######################### # MAIN ######################### my (%opt, @targets); my $maxprocs = $opt{max} || 50; # set the maximum number of childre +n to spawn $main::avail = 0; &options(\%opt); &get_targets(); &check_remotes(); ######################### sub get_targets ######################### { ## Set up vars for main db call my ($dsn) = "DBI:mysql:routers:localhost"; my ($user_name) = "user"; my ($password) = "abcd1234"; my ($dbh, $sth); ## Connect to DB $dbh = DBI->connect ( $dsn, $user_name, $password, {RaiseError =>1} ); ## Fetch variables from database and write out config file ## The Database Query is option dependant if ($opt{cat}) { $sth = $dbh->prepare ("SELECT ip FROM routers WHERE category rlike + '$opt{cat}'"); } elsif ($opt{all}) { $sth = $dbh->prepare ("SELECT ip FROM routers"); } else { die "ERROR - Couldn't identify a target. $!"; } ## Go get it $sth->execute(); ## Process the data while( ($ip_add) = $sth->fetchrow_array() ) { push @targets, $ip_add; $noerror = "1"; } ## Disconnect the DB $sth->finish (); $dbh->disconnect(); unless ($noerror) {die "FATAL: Database did not return valid data! Che +ck Device name.\nError Response: $!\n";} } ######################### sub check_remotes ######################### { my $prox = int(scalar(@targets)/$maxprocs); my $prox_r = int(scalar(@targets)%$maxprocs); my $i = 0; if ($prox) { for ( 1 .. $prox ) # call the forking routine as many times as requ +ired to get most of the targets { &breed($maxprocs); } } if ($prox_r) { &breed($prox_r); # Then call the forking routine but this time on +ly enough to catch the modulo } # Calculate results and print to STDOUT my $uptime = ( $main::avail / scalar(@targets) ) * 100; # return res +ults as a percentage $uptime = sprintf('%.2f',$uptime); print "\nTOTAL:\t${uptime}% of devices are responding.\n"; } ######################### sub breed ($) ######################### { my $loop = shift; for ( 1 .. $loop ) { if ($pid=fork) { push @pids, $pid; $i ++; } elsif (defined $pid) { my $next = @targets[${i}]; &ping_remote($next); exit; } } foreach my $childpid (@pids) { waitpid($childpid, 0); $main::avail += ! $?; # 0 means success, non-zero means failure } } ######################### sub ping_remote($) ######################### { my $ip = shift; my $response = `ping -n -w 5 -i .3 $ip -c 3 | grep round-trip`; chomp $response; if ($response) { $response = 0; } else { $response = 1; } # 0 means su +ccess, non-zero means failure if (-t and $response) { print "Failed connect to $ip\n"; } exit($response); } ######################## sub options () ######################## { my $opt = shift; GetOptions( $opt, 'cat=s', 'max=s', 'all', ); $opt{cat} =~ s/[\"\;]//; # remove quotes and semicolons from querie +s unless (defined $opt{cat} || $opt{all}) #print usage if options not + given { print <<ECHO; ForkingPinger, Version $Version --------- Pulls a category from the database and checks it for availability, ret +urning a percentage. Designed to be run in batch mode but can be used at the command line f +or debugging or testing purposes. Highly parallel. Automatically prints the IP addresses of failed sites if used from the + command line. Usage: $0 [options] Options: --cat=name Pull all devices of category matching regexp 'name' from DB and test a +vailability. --all Pull all devices from DB and test availability. --max=num Spawn no more than num processes in parallel (default = 50) ECHO exit(1); } }
    Update: Fixed a little typo I spotted. Oops.
    Update2: Fixed a bigger omission: the -all switch was broken. I wasn't considering the option when validating command line switches. Oops again.
    Signature void where prohibited by law.
      I can't resist mentioning that at first glance, I read your title as Porking Finger, a spoonerism which would certainly qualify as a Cool Use For PerlTM.
         MeowChow                                                                   
          "you can prick your finger, but don't finger your prick" - George Carlin
Re: Pingger
by busunsl (Vicar) on Apr 26, 2001 at 01:42 UTC
    Don't know exactly what your problem is, but if you change the print-line to:
    print " $host is alive \n"; it will print:
    10.1.1.1 is alive 10.1.1.2 is alive 10.1.1.3 is alive
Re: Pingger
by ColonelPanic (Friar) on Apr 26, 2001 at 01:47 UTC
    After the map() statement you do a useless chomp of $ipnumber. did you mean to do that to @iparray instead? That could mess up the ping module, I suppose.

    When's the last time you used duct tape on a duct? --Larry Wall
Re: Pingger
by SgtClueLs (Novice) on Apr 26, 2001 at 01:44 UTC
    I assume that it's supposed to be
    128.135.75.1
    is alive
    ???
    Try removing the newline in this part
     @iparray = map $ipnumber. ".$_\n",1..254 ;
    And adding a newline to
    foreach my $host (@iparray) { if ( $p->ping( $host )){ print " $host is alive\n ";
    at the end of that.
    Otherwise when it goes to print the host it copies the newline from the original array. And hence the return at the end of the IP Address. So the final product should look like this (Note: I change the ips to match my network)

    #!/usr/bin/perl use warnings; use Net::Ping; use Socket; $ipnumber ="192.168.30"; chomp $ipnumber; @iparray = map $ipnumber. ".$_",1..254 ; chomp $ipnumber; #open (ERRORLOG, ">errorlog"); #open (OFFLINE,">offline"); #open (ONLINE,">online"); my $proto = 'icmp'; my $def_timeout = '5'; my $bytes = '64'; my $p = Net::Ping->new($proto, $def_timeout , $bytes); foreach my $host (@iparray) { if ( $p->ping( $host )){ print " $host is alive\n "; } #foreach my $host (@iparray) { # $testing = $p $host; # print "$testing"; # print "$host offline " unless $p->ping($host,1); # print "$host online " unless $p->ping($host,0); # print ERRORLOG "$host offline " unless $p->ping($host,1); # print OFFLINE "$host"unless $p->ping($host,1); # print ONLINE "$host online" unless $p->ping($host,0); } $p->close();

    Sgt
Re: Pingger
by grinder (Bishop) on Apr 26, 2001 at 11:37 UTC

    Damn! This code is posted twice in the Monastery and I just happened to comment on the dead thread. Anyway I just wanted to point out that I have code that does much the same thing, with a few more bells and whistles. You may find it of use.


    --
    g r i n d e r