Re: [SLE] emailing myself when a ping command fails via crontab????

Michael.James_at_csiro.au
Date: 10/14/03

  • Next message: Carlos E. R.: "Re: [SLE] Problem with postfix"
    To: suse-linux-e@suse.com
    Date: Tue, 14 Oct 2003 10:14:04 +1000
    
    

    > The 03.10.13 at 15:54, Damian Buckley wrote:
    >
    > > want to set a command up to email me via sendmail
    > > when the ping command fails....

    This is a bit of overkill for what you asked
     but I have a perl script to monitor a webserver.

    Set it up in crontab to run as often as you like, eg: 5 minutely.
    Without "-d" it should run silently.
    Put in another daily job to cat the logfile it generates.
    That will get mailed to the user who has the crontab.
    You need to be in the group "trusted" to have a crontab.

     First the script tries to ping it's DNS servers,
     (to test it's own network connection)
     then resolves the target host,
     then pings the target host
     then http GETs a small test file
     and compares it to the local copy.
    (you will need a similarly named copy of the file you are GETing)

    It logs the sucess (in lowercase)
     or failure (uppercase) of each step.

    Logfiles don't grow too big as it only adds a line
     if the success or failure of any step changes.
    Then it leaves a line in the log showing
     the time of the last old-state run.
    If nothing changes it just updates the timestamp
     of the last line.

    -- 
    Michael James				michael.james@csiro.au
    System Administrator			voice:	02 6246 5040
    CSIRO Bioinformatics Facility	fax:		02 6246 5166
    Script follows:
    #!/usr/bin/perl
    # timekeeper    a script to monitor a webhost
    #
    #                      GPL by michael@james.st 2003-02-21
    # Set some formal variables
    my $INDEX = 'index.html';
    my $RESOLV_CONF = '/etc/resolv.conf';
    my $PING = 'ping';
    # Linux Ping
    my @PING_ARGS =('-c2', '-w2');
    my @POST_ARGS = ();
    # SunOS Ping
    #my @PING_ARGS = ('-s');
    #my @POST_ARGS = ('64', '2');
    $ENV{'PATH'}='/bin:/usr/bin:/usr/sbin';
    # That's most of what should need tuning
    use strict;
    use Socket;
    use Time::localtime;
    use File::Basename;
    use LWP::Simple;
    chdir dirname($0) or die "Couldn't cd to script directory\n";
    my $user=`whoami`; chop($user);
    my($debug, @url_list, $url);
    # Get the target list of URLs, and any flags
    foreach (@ARGV)
    {
            s/^-d.*//i and $debug='on';
            $_ or next;
            push(@url_list, $_);
    }
    @url_list or die "Usage: $0 <target url list>\n";
    foreach $url (@url_list)
    {
            my $host = $url;
            my $file = $INDEX;
            unless ( $host =~ s%http://%%i or $host =~ s%ftp://%%i )
            {       print "Only ftp or http URLs allowed!\n";
                    next;
            }
            $host =~ s%/(.*)$%% and $file = $1;
            $debug and print "$0 running for $user\n\nTarget host:\t$host\n";
            my $tm = localtime;
            my $date = sprintf "%4d-%02d-%02d",
                            $tm->year+1900, $tm->mon+1, $tm->mday;
            my $time = sprintf "%02d:%02d", $tm->hour, $tm->min;
            my $time*** = "$host";
            my $temp = ".$host";
            -r $time*** or create($time***, $date, $time);
            -r $temp and die "$temp file found, another copy is running\n";
            my $self = ping_a_nameserver();
            my $dns = resolve(\$host);
            my $ping = test_ping($host) || 'PING';
            my $get = http_get($url, $file);
            my $result = join("\t", $self, $dns, $ping, $get);
            $debug and print "Complete result:\t(", $result, " )\n\n\n";
            open(IN, "< $time***") or die "can't read $time***\n";
            open(OUT, "> $temp") or die "can't write $temp\n";
            my $lastline = <IN>;
            while(<IN>)
            {
                    print OUT $lastline;
                    $lastline = $_;
            }
            # We have printed out all the log except the last line
            chop($lastline);
            # Split the datestamp off the results
            my ($lastdate, $lasttime, $lastresult) = split(/\s+/, $lastline, 3);
            $debug and print "Date\t=($date)\nLast\t=($lastdate $lasttime)\n",
                    "Result\t=($result)\nLast\t=($lastresult)\n";
            # If they're different or it's a new day, print out the old line
            if ( ($result ne $lastresult) or ($lastdate ne $date) )
                    { print OUT $lastline, "\n"; }
            print OUT join("\t", $date, $time, $result), "\n";
            close(IN);
            close(OUT);
            rename($temp, $time***);
    }
    sub create
    {
            my($file, $date, $time) = @_;
            open(OUT, "> $file") or die "Can't create a new time*** $file\n";
            print OUT join("\t", 'Time of last check', 'Self', 'DNS', 'Ping',
                    "Get\n\n$date", $time, "  Started Running...\n");
            close OUT;
    }
    sub ping_a_nameserver
    {
            open(IN, "$RESOLV_CONF") or die "Can't read $RESOLV_CONF\n";
            while (<IN>)
            {       chop;
                    s/^nameserver\s+//i or next;
                    $debug and print "Nameserver:\t[", $_, "]\n";
                    test_ping($_) or next;
                    close(IN);
                    return 'self';
            }
            return 'SELF';
    }
    sub resolve
    # expects a ref to a hostname
    # replaces it with the IP number
    # returns "dns" or "DNS" followed by the IP
    {
            my $ref = shift;
            $debug and print "Resolving:\t[", $$ref, "]\n";
            if ( my $ip = inet_aton($$ref) )
            {       $$ref = inet_ntoa($ip);
                    return 'dns';
            }
            $debug and print "\t no answer\n";
            return 'DNS';
    }
    sub test_ping
    # expects a host by name or number
    # returns "ping" or "PING"
    #       depending if the ping worked or NOT
    {
            my $host = shift;
            my($out, $in);
            $debug and print "Pinging:\t[$host]\n";
            defined( my $pid = open(PING, "-|") ) or die "Can't fork: $!";
            unless ( $pid ) # Child command that generates the output
                    { exec($PING, @PING_ARGS, $host, @POST_ARGS); }
            else
            {       while (<PING>)
                    {       $debug and print $_;
                            ($out, $in) =
                                    /(\d+).*?transmitted.*?(\d+).*?received/
                                    and last;
                    }
                    close(PING);
            }
            $debug and print "Final count Out: $out, In: $in\n";
            $in > 0 and $in == $out and return 'ping';
            $debug and print "\tNo ping\n";
            return;
    }
    sub http_get
    {
            my($url, $file) = @_;
            my $content;
            $debug and print "Getting:\t$url\n";
            defined( $content = get($url) ) or return 'GET';
            $debug and print "Here's the file we got:\n\n\n",
                                    $content, "\n\n\n";
            # Get the correct content from a local file
            open(FILE, "< $file") or warn "Can't read $file\n";
            my $correct =  join('', <FILE>);
            close(FILE);
            $content eq $correct or return 'GARBLE';
            return 'get';
    }
    -- 
    Check the headers for your unsubscription address
    For additional commands send e-mail to suse-linux-e-help@suse.com
    Also check the archives at http://lists.suse.com
    Please read the FAQs: suse-linux-e-faq@suse.com
    

  • Next message: Carlos E. R.: "Re: [SLE] Problem with postfix"