#!/usr/bin/perl -w # ping a range of hosts preiodically and record average ping times # to in csv format to files named pinglog-yyyymmdd.csv # # also has capability of executing commands on host goind down / coming up # # # # # Copyright (C) 2008 Glen Pitt-Pladdy # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # # # # names and hosts (or ips) to monitor # ensure they are coma seperated %MONITOR = ( 'Localhost' => 'localhost', 'LocalIP' => '127.0.0.1' ); # do some action when the host goes up / down # ensure they are coma seperated %HOST_UP = ( 'LocalIP' => '/bin/echo up |/usr/bin/mutt -e "set record=" -s "LocalIP UP" "root@localhost"' ); %HOST_DOWN = ( 'LocalIP' => '/bin/echo down |/usr/bin/mutt -e "set record=" -s "LocalIP DOWN" "root@localhost"' ); # delay between ping cycles $DELAY = 30; # timeout waiting for return packet $TIMEOUT = 1; # number of missed pings to consider as down $COUNT = 2; # wait between pings $INTERVAL = 0.5; # ping program (not using per Net::Ping as this requires root - ping is suid) $PING = "/bin/ping -n -W $TIMEOUT -c $COUNT -i $INTERVAL"; # main loop $startday = 0; $targettime = $^T; while ( 1 ) { $sampletime = time; ( $sec,$min,$hour,$mday,$mon,$year ) = localtime ( $sampletime ); ++$mon; $year += 1900; $nextline = sprintf ( "%04d/%02d/%02d %02d:%02d:%02d", $year, $mon, $mday, $hour, $min, $sec ); # check if we need a new file if ( $startday != $mday ) { $startday = $mday; if ( fileno ( LOG ) ) { close LOG; } $file = sprintf ( "pinglog-%04d%02d%02d.csv", $year, $mon, $mday ); open LOG, ">>$file" or die "FATAL: can't write file \"$file\": $!\n"; # heading print LOG "time"; foreach $host (keys %MONITOR) { print LOG ",$host"; } print LOG "\n"; } # run monitoring cycle foreach $name (keys %MONITOR) { $host = $MONITOR{$name}; open PNG, "$PING $host |" or die "FATAL: can't start $PING: $!\n"; $last = "NULL"; while ( defined ( $line = ) ) { $last = $line; } close PNG; chomp $last; # match line if ( $last =~ /^rtt min\/avg\/max\/mdev = [0-9\.]+\/([0-9\.]+)\/[0-9\.]+\/[0-9\.]+ ms$/ ) { # good return - store data $nextline .= ",$1"; # check if we are doing any action if ( defined ($laststatus{$name}) and $laststatus{$name} eq 'down' ) { # host came up - execute HOST_UP if ( $HOST_UP{$name} ) { system $HOST_UP{$name}; } } $laststatus{$name} = 'up'; } else { # bad return - log null $nextline .= ",NULL"; # check if we are doing any action if ( defined ($laststatus{$name}) and $laststatus{$name} eq 'up' ) { # host went down - execute HOST_DOWN if ( $HOST_DOWN{$name} ) { system $HOST_DOWN{$name}; } } $laststatus{$name} = 'down'; } } print LOG "$nextline\n"; # work out next timing $targettime += $DELAY; $delay = $targettime - time; if ( $delay > 0 ) { sleep $delay; } else { print STDERR "WARNING: required delay $delay seconds\n"; } }