1: #!/usr/bin/perl
   2: use warnings;
   3: use Net::Ping;
   4: use Socket;
   5: 
   6: print "Enter the subnet you wish to scan just the first 3 octet's\n";
   7: $ipnumber =<STDIN>;
   8: chomp $ipnumber;
   9: @iparray = map $ipnumber. ".$_",1..254 ;
  10: #print @iparray;
  11: #open (ERRORLOG, ">errorlog");
  12: open (OFFLINE,">offline");
  13: #open (ONLINE,">online");
  14: 
  15: #my @iparray = qw( www.slashdot.org www.deja.com  www.perlmonks.org );
  16: 
  17: 
  18: my $proto = 'icmp';
  19: my $def_timeout = '0';
  20: my $bytes = '64';
  21: 
  22: my $p = Net::Ping->new($proto,  $def_timeout , $bytes);
  23: $! = 1;
  24: foreach my $host (@iparray) {
  25:      print ONLINE "$host online \n" if $p->ping($host);
  26:      print ERRORLOG "$host offline \n" unless $p->ping($host,1);
  27:      print OFFLINE "$host \n" unless $p->ping($host,1);
  28: }
  29: $p->close();
  30: close OFFLINE;
  31: close ERRORLOG;
  32: close ONLINE;
  33: 
  34: open (IPLIST, "offline");
  35: #open (OFFLINEHOST, ">offlinehost");
  36: @list=<IPLIST>;
  37: $list = @list;
  38: #print "@list\n";
  39: chomp @list;
  40: my $i;
  41: my $peer_host;
  42: format STDOUT_TOP =
  43: IP#              Machine name           
  44: ---------------- ------------------------------------ -------
  45: .
  46: format STDOUT =
  47: @<<<<<<<<<<<<<<< ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ^<<<<<< 
  48: $i,         $peer_host,                              "offline"
  49: .
  50: foreach $i (@list) {
  51: $peer_host = gethostbyaddr(inet_aton($i), AF_INET);
  52: #$peer_host = gethostbyaddr(inet_aton($i), AF_INET);
  53: #print OFFLINEHOST "$peer_host and ipaddress $i\n";
  54: #print OFFLINEHOST "$peer_host and ipaddress $i\n";
  55: write
  56: }
  57: close OFFLINE;

Replies are listed 'Best First'.
Re: Pingger Script4
by Chmrr (Vicar) on Apr 26, 2001 at 07:03 UTC

    We talked about this in the CB a bit. I'll just re-iterate what I said there:

    • use strict; is always a good thing. Get in the habit of using it.
    • This code doesn't work as written. You need to uncomment your open statements at lines 11 and 13.
    • Regardless, you're writing to file some information (to three seperate files, in fact!), which is only going to be read back in later. You should just be using variables for this. There is no reason to do file I/O. I suggest you push the ip addresses onto various arrays as you find their status.
    • You're pinging the host three times. Not only is this a waste of bandwidth, it might also cause a sort of network race condition. That is, if your host is online for the first ping, but the connection drops before your second ping, your host will turn up being both up and down. Which is a mite confusing.
    • For all the effort of writing to three files, you only open back up one of them. Do you really need these three files, two of which are near duplicates of each other?

    After talking to you some more,. it seems that you do want at least one file output at the end. I suggest you go through, ping everything (once each!), while writing to your log file. At the same time, push stuff onto an array so you can pretty-print it out later.

    Update: Here's one possible way to go about going it. Do also look at Clownburner's suggestion, as well -- it's a little more complicated, but probably a lot faster. Anyways, this code will spit out two output files, as well as telling you, in real-time, which hosts are up. Note the $SIG{INT} handler so you can drop out early if you want to. The command line options are just icing.

    #!/usr/bin/perl -w use strict; use Net::Ping; use Getopt::Std; $|++; my %opts; getopts('?ht:s:',\%opts); if ($opts{'h'} or $opts{'?'}) { print "Usage:\n"; print "\t$0 [-t timeout] [-s subnet]\n"; exit; } $opts{'t'} ||= 5; unless ($opts{'s'}) { print "Enter subnet: "; chomp($opts{'s'} = <STDIN>); } $opts{'s'} =~ s/^(\d+)\.(\d+)\.(\d+).*/$1.$2.$3/ or die "Bad subnet fo +rmat: use xxx.xxx.xxx"; my (@up,@down); my @ips = map {"$opts{'s'}.$_"} 1..254; my $ping = Net::Ping->new("icmp",$opts{'t'}); $SIG{INT} = \&cleanup; for (@ips) { if ($ping->ping($_)) { print "Host $_ is UP\n"; push @up, $_; } else { print "Host $_ is DOWN\n"; push @down, $_; } } cleanup(); sub cleanup { print "Cleaning up and writing output files.."; open UP_FILE, ">ips_online" or die "Can't create online ip file: $!" +; print UP_FILE map {"$_\n"} @up; close UP_FILE or die "Can't close online ip file: $!"; open DOWN_FILE, ">ips_offline" or die "Can't create offline ip file: + $!"; print DOWN_FILE map {"$_\n"} @down; close DOWN_FILE or die "Can't close offline ip file: $!"; print "Done.\n"; exit; }

     
    perl -e 'print "I love $^X$\"$]!$/"#$&V"+@( NO CARRIER'

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

    I uploaded something similar a little while back. It seems to work pretty well (it's been in production for 18 months so I'm pretty confident it's bug-free).


    --
    g r i n d e r
Re: Pingger Script4
by Clownburner (Monk) on Apr 26, 2001 at 07:39 UTC
    Go check out my ForkingPinger here and see if it helps.
    Signature void where prohibited by law.