Beefy Boxes and Bandwidth Generously Provided by pair Networks
The stupid question is the question not asked

Ping Monitor with Email Notification

by linebacker (Scribe)
on Feb 12, 2003 at 21:29 UTC ( #234828=CUFP: print w/replies, xml ) Need Help??

I did a search on the PM site for a ping monitor with email notification, but did not find one. So...I wrote this using Net::Ping and MIME::Lite. Improvements to this script are encouraged. Currently I run it from cron every 15 minutes.


As a backup Network / Firewall admin. I am responsible for 37 network access devices, only really need to take action if the device is down for over 15 minutes. This is important as the sleep statement in the tryagain sub routine could cause the program to take up to n times  sleep (60);   per down device. If your requirements are to be notified for every hiccup in the network (or if your provider doesn't drop a frame relay ckt. several times per day just modify the script).

#!/usr/local/bin/perl -w use strict; use Net::Ping; use MIME::Lite; unless(@ARGV) { print "Supply a file with hostnames \(example usage\)-- \n$0 /etc/ +hosts\n"; exit; } my @host_array=<>; my $p = Net::Ping->new("icmp"); foreach our $host (@host_array) { print "$host is "; &tryagain ($host) unless $p->ping($host, 5); print "reachable.\n"; } $p->close(); sub tryagain { print "NOT "; sleep (60); my ($host)=@_; my $p = Net::Ping->new("icmp"); foreach our $host (@_) { &notify ($host) unless $p->ping($host, 30); } $p->close(); } sub notify { my $date= localtime(time); my ($host)=@_; my $msg=MIME::Lite-> new( From =>'ICMP Monitor <>', To =>'', Subject =>'Ping Failure', Data =>"Ping failure for $host at $date" ); $msg->send; }

Replies are listed 'Best First'.
(jeffa) Re: Ping Monitor with Email Notification
by jeffa (Bishop) on Feb 13, 2003 at 07:39 UTC
    3 things:
    1. send all failures in one email message
    2. instantiate only one Net::Ping and re-use it
    3. get rid of the tryagain sub
    You have coded tryagain to accept and iterate through a list of hosts, but you always pass it one scalar. But like i said, it's not really necessary anyway. Here is a re-write that uses Getopt::Long and Pod::Usage. However, Pod::Usage and "icmp" pings don't play together in the sandbox very well. By that i mean that "Superuser must not run perldoc without security audit and taint checks." (perldoc error message) and "specifying the 'icmp' protocol requires that the program be run as root or that the program be setuid to root" (from the Net::Ping docs). What this boils down to is unless you set up those "security audit and taint checks", there is no reason to use a Pod::Usage -verbose setting higher than 1 (one), but i did anyway for the help message.
    use strict; use warnings; use Data::Dumper; use Net::Ping; use MIME::Lite; use Getopt::Long; use Pod::Usage; use vars qw( $ping $first $delay $second @host $file $help $to $from ); parse_args(); $to ||= ''; $from ||= 'ICMP Monitor <>'; $first ||= 5; $delay ||= 60; $second ||= 30; $ping = Net::Ping->new('icmp'); foreach my $host (@host) { print "$host is "; unless ($ping->ping($host, $first)) { sleep ($delay); unless ($ping->ping($host, $second)) { notify($host); print 'NOT '; } } print "reachable.\n"; } $ping->close(); sub notify { my @host = @_; my $data = "Ping failures:\n\t" . join("\n\t",@host) . "\n" . local +time; my $msg=MIME::Lite-> new( To => $to, From => $from, Subject => 'Ping Failure', Data => $data, ); $msg->send; } sub parse_args { GetOptions( 'host=s' => \@host, 'file=s' => \$file, 'to=s' => \$to, 'from=s' => \$from, 'first=i' => \$first, 'delay=i' => \$delay, 'second=i' => \$second, 'help|h|?' => \$help, ); pod2usage(-verbose=>2) if $help; pod2usage(-verbose=>1) unless @host or $file; @host = file2list($file) unless @host; } sub file2list { my $file = shift; open FH, $file or die "can't open $file: $!"; my @list = <FH>; chomp @list; return @list; } __END__ =head1 NAME - Ping Monitor with Email Notification =head1 SYNOPSIS -host <host> | -file <file> Options: -file read list of hosts from file -host provide host via command line -to email recepient -from email sender -first no. seconds for first time-out -delay no. seconds between first and second ping -second no. seconds for second time-out -help -h brief help message =head1 DESCRIPTION B<This program> will ping the provided hosts and send a email notifying which hosts (if any) were not reachable. Each host will first be pinged for an initial amount (set with the -first option). If that ping fails, the program will sleep for an amount of time (set with the -delay option) before a second ping attempt. The second ping's time-out is set with the -second option. You can also set the to and from fields for the email on the command line. Modify the source code to add default values. =head1 EXAMPLES 1 - ping contents of /etc/hosts ./ -file=/etc/hosts 2 - ping Google ./ 2 - ping Google and Perlmonks ./ =cut


    (the triplet paradiddle with high-hat)

      I may very well misread your code, but aren't you sending one mail for every failed host too?

      I'd expected something like

      [...] my @failed = []; foreach my $host (@host) { print "$host is "; unless ($ping->ping($host, $first)) { sleep ($delay); unless ($ping->ping($host, $second)) { push @failed, $host; print 'NOT '; } } print "reachable.\n"; } notify(@failed) if @failed; [...]
      may I humbly ask what I've overlooked?


        "may I humbly ask what I've overlooked?"

        The fact that i was half-asleep when i wrote that? :D

        May i humbly say, thanks? I will leave my code untouched, but you are absolutely correct. I wrote my code by modifying linebacker's, but i forgot to add that feature. Thanks for catching it, and better yet, offering a solution.

        However, don't initialize an array like this:
        my @array = []; # use empty parens instead ()
        That declared a new array whose first element is an anonymouse array reference. I have been bitten by that error before. ;)


        (the triplet paradiddle with high-hat)

        I read it the same as you. Good pick up ++Tomte




Re: Ping Monitor with Email Notification
by Mr. Muskrat (Canon) on Feb 12, 2003 at 21:51 UTC

    Is there a reason why you are using my $date=`/bin/date`; instead of my $date=localtime(time);?

      Updated the script. I was unenlightened about using localtime. Funny, I had been using cut before someone enlightened me to split.
Re: Ping Monitor with Email Notification
by Aristotle (Chancellor) on Feb 13, 2003 at 18:57 UTC
    Just adding a note that there are very capable and customizable packages like Nagios (formerly NetSaint), mon and Big Brother available freely to monitor just about everything you can think of in a network. I recommend you pick one of those instead of trying to roll your own - not only for reasons of robustness but also synergy. Any future improvements to them will benefit you automatically, and your own improvements to them will benefit many others as well.

    Makeshifts last the longest.

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: CUFP [id://234828]
Approved by particle
Front-paged by particle
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others lurking in the Monastery: (3)
As of 2019-10-17 03:20 GMT
Find Nodes?
    Voting Booth?