J
Jim Moser
I'm trying to write a simple network monitoring tool in Perl. The
source code is below. The script parses the /etc/hosts file (or a
similarly formated file) and pings each host, giving it a designation
of UP or DOWN. The script repeats this at whatever interval I
designate.
So far the script is functional; however, at each interval I'm calling
system(clear) to clear the screen and update the list. This looks very
sloppy to the end user and I would like the script to keep the IP and
hostname on screen and only update the UP|DOWN field one at a time. If
this is simple to do, could someone provide some sample code? If it's
not quite so simple could someone point me in the right direction to
get started. I am using O'Reilly Programming Perl 3rd Ed and O'Reilly
Perl Cookbook as references.
Also, any conductive criticism is appreciated.
#!/usr/bin/perl
use Net:ing;
# Process arguements
while (@ARGV and $ARGV[0] =~ /^-/) {
$_ = shift;
last if /^--$/;
if (/^-f(.*)/) { $hostfile = $1 }
if (/^-i(.*)/) { $int = $1 }
if (/^-\?|^-h/) { usage(); }
}
sub usage() {
print "Usage: ping.pl options
ping.pl [ -f | -i | -h | -? ]
Options:
-f<filename>
File should be a space delimited file with a list of IP addresses
and hostnames. Use /etc/hosts as an example. If there are multiple
hostnames associated with a single IP address only the first
hostname will be processed. If a file is not specified, the
/etc/hosts file will be used by default.
-i<interval>
This is the interval in seconds to refreshing the server list.
If no interval is specified, a default interval of 30 seconds is
used.
-h display this help screen
-? display this help screen
Examples:
ping.pl -f/etc/hosts -i30\n";
exit;
}
# Set default values if no arguments were supplied
unless (defined($hostfile)) { $hostfile = "/etc/hosts" }
unless (defined($int)) { $int = "30" }
open(HOSTFILE, $hostfile);
# Create a hash of the hostfile; omitting comments, localhost, and
blank lines
LINE: while (<HOSTFILE>) {
next LINE if /^#/;
next LINE if /^127/;
next LINE if /^\s/;
($ip, $hostname) = split /\s/;
@fields = split ' ', $hostname;
$list{$ip} = [ @fields ];
}
# Ping each host once and label UP or DOWN
sub getstatus {
$p = Net:ing->new("icmp");
foreach $server ( keys %list ) {
if ($p->ping($server, 1)) {
$status = "UP";
}else{
$status = "DOWN";
}
write STDOUT;
}
}
# Make it pretty
format STDOUT =
@<<<<<<<<<<<<<<<< @<<<<<<<<<<<<<<<< @<<<<
@{ $list{$server} }, $server, $status
}
while (1) {
system(clear);
getstatus();
sleep($int);
}
source code is below. The script parses the /etc/hosts file (or a
similarly formated file) and pings each host, giving it a designation
of UP or DOWN. The script repeats this at whatever interval I
designate.
So far the script is functional; however, at each interval I'm calling
system(clear) to clear the screen and update the list. This looks very
sloppy to the end user and I would like the script to keep the IP and
hostname on screen and only update the UP|DOWN field one at a time. If
this is simple to do, could someone provide some sample code? If it's
not quite so simple could someone point me in the right direction to
get started. I am using O'Reilly Programming Perl 3rd Ed and O'Reilly
Perl Cookbook as references.
Also, any conductive criticism is appreciated.
#!/usr/bin/perl
use Net:ing;
# Process arguements
while (@ARGV and $ARGV[0] =~ /^-/) {
$_ = shift;
last if /^--$/;
if (/^-f(.*)/) { $hostfile = $1 }
if (/^-i(.*)/) { $int = $1 }
if (/^-\?|^-h/) { usage(); }
}
sub usage() {
print "Usage: ping.pl options
ping.pl [ -f | -i | -h | -? ]
Options:
-f<filename>
File should be a space delimited file with a list of IP addresses
and hostnames. Use /etc/hosts as an example. If there are multiple
hostnames associated with a single IP address only the first
hostname will be processed. If a file is not specified, the
/etc/hosts file will be used by default.
-i<interval>
This is the interval in seconds to refreshing the server list.
If no interval is specified, a default interval of 30 seconds is
used.
-h display this help screen
-? display this help screen
Examples:
ping.pl -f/etc/hosts -i30\n";
exit;
}
# Set default values if no arguments were supplied
unless (defined($hostfile)) { $hostfile = "/etc/hosts" }
unless (defined($int)) { $int = "30" }
open(HOSTFILE, $hostfile);
# Create a hash of the hostfile; omitting comments, localhost, and
blank lines
LINE: while (<HOSTFILE>) {
next LINE if /^#/;
next LINE if /^127/;
next LINE if /^\s/;
($ip, $hostname) = split /\s/;
@fields = split ' ', $hostname;
$list{$ip} = [ @fields ];
}
# Ping each host once and label UP or DOWN
sub getstatus {
$p = Net:ing->new("icmp");
foreach $server ( keys %list ) {
if ($p->ping($server, 1)) {
$status = "UP";
}else{
$status = "DOWN";
}
write STDOUT;
}
}
# Make it pretty
format STDOUT =
@<<<<<<<<<<<<<<<< @<<<<<<<<<<<<<<<< @<<<<
@{ $list{$server} }, $server, $status
}
while (1) {
system(clear);
getstatus();
sleep($int);
}