#!/usr/bin/perl -T -w # $Id: ping-state-trace,v 1.2 2008/05/17 07:00:42 suter Exp $ # [MJS 29 Mar 2000] Based on Chris Teakle's "ping_trace" (shell/awk) # [MJS 23 May 2000] Major rewrite - now intended to be used as "mesh" in BigBrother. # [MJS 17 Sep 2003] Slight modifications to use on a Debian GNU/Linux host # [MJS 6 Aug 2004] Added timestamp use strict; use Getopt::Long; use Socket; use Net::Ping; use Time::HiRes qw ( time sleep ); use POSIX qw(strftime); my ($type, $lost, $slow, $period, $report, $debug, $host) = ("icmp", 4.7, 0.5, 5.0, 4 * 60, 0, 0, ""); $| = 1; sub send_event { my (%event) = @_; my ($colour, $string) = ("green", "Packets are returning."); if ($event{timeout} == $lost or $event{timeout} == $slow) { $colour = $event{timeout} == $lost ? "red" : "yellow"; $string = sprintf "Over the last %.2fs, %d pkts to %s did not return within %.1fs.", time() - $event{start}, $event{count}, $event{host}, $event{timeout}; } print strftime "%Y-%m-%d %H:%M:%S $colour $string\n", localtime; } my $result = Getopt::Long::GetOptions("type=s" => \$type, "lost=f" => \$lost, "slow=f" => \$slow, "period=f" => \$period, "report=i" => \$report, "debug!" => \$debug); if ($result == 1 and defined($ARGV[0])) { my $addr = gethostbyname($ARGV[0]); $addr and $host = inet_ntoa($addr) or die "Invalid host: $ARGV[0]\n"; } else { die "Usage: $0 [--type=(icmp|udp)] [--lost=f] [--slow=f] [--period=f] [--report=i] [--[no]debug] host\n"; } my $ping = Net::Ping->new($type); my $remainder; my %good = ( count => -2, host => $host, timeout => 0 ); my %slow = ( count => 0, host => $host, start => 0, timeout => $slow ); my %lost = ( count => 0, host => $host, start => 0, timeout => $lost ); while (1) { my $t1 = time(); if ($ping->ping($lost{host}, $lost{timeout})) { # STATE slow/good my $delay = time() - $t1; if ($lost{count} > 0) { # TRANS lost -> slow/good send_event %lost; $lost{count} = 0; } if ($delay > $slow{timeout}) { # STATE slow if ($slow{count} == 0) { # TRANS -> slow $slow{start} = $t1; $good{count} = -2; } $debug and print "SL: $t1\n"; ++$slow{count} % $report == 0 and send_event %slow; } else { # STATE good if ($slow{count} > 0) { # TRANS slow -> good send_event %slow; $slow{count} = 0; } $debug and print "OK: $t1\n"; ++$good{count} % $report == 0 and send_event %good; } } else { # STATE lost if ($lost{count} == 0) { # TRANS -> lost $lost{start} = $t1; $good{count} = -2; } $debug and print "LT: $t1\n"; ++$lost{count} % $report == 0 and send_event %lost; } ($remainder = $period + $t1 - time()) > 0 and sleep($remainder); }