Saturday, July 30, 2016

Ping-based Host Monitoring Script with Timestamps

In my previous post Server availability monitoring with email notifications I've used the same idea of monitoring. This script is a version 2.0 with some additional features:
  1. If you compare old and new version, you'll notice the script was completely rewritten. It's because I wanted it to run on my synology NAS.
  2. Next change is additional host states, instead of A-available and N-notAvailable I'm now using 2 additional states Going Up, Going Down. This will delay the notification about host state change and prevent frequent flapping of naughty hosts in network.
  3. Last feature added is hosts UP/DOWN times in notifications; see mail notification example:
Host krisko is UP at Jul 30 08:06:01 after 0 days 05:38:00

As in previous script version I also use state file to note the hosts changes. The syntax is following:
# SYNTAX: host STATE TSTAMP
# STATES: 1-available 2-goingUP 3-goingDOWN 4-down
krisko 1 1469858761
krisko-t 4 1460998141
When creating new entry, simply add hostname/IP, state and some timestamp.
NOTE: don't forget to adjust path to the file in script (STATFILE variable)

And here's the script. You should add this script to cron or create systemd timer to trigger it regularly.
#!/bin/sh
##################
# simple ping check with notifications
#
# Available  1
# Going UP   2
# Going DOWN 3
# Unavailabe 4
##################

CTSTAMP=$(date '+%s')
STATFILE=/path/to/monitor/monitor.stat
EMAIL=myEmail@gmail.com
# export TimeZone
#export TZ=UTC0

notify() {
    echo -e "subject: $1\n$2" | sendmail -t $EMAIL
}

state() {
    [[ -n "$3" ]] && sed -i "s/^\($1\)\s.*/\1 $2 $3/" $STATFILE ||
                     sed -i "s/^\($1\)\s[1-4]/\1 $2/" $STATFILE
}

while read HOST STATE HTSTAMP; do
    # skip comments
    echo $HOST | grep -q "^#" && continue
    unset PING
    # set ping if successfull
    ping -c 3 -W 2 $HOST &>/dev/null && PING=:
    if [[ $PING ]]; then
        [[ $STATE -eq 1 ]] && continue
        [[ $STATE -eq 2 ]] && { NTSTAMP=$(($CTSTAMP-$HTSTAMP)); state "$HOST" "1" "$CTSTAMP";
            notify "Host UP Alert for $HOST" \
                   "Host $HOST is UP at $(awk -v TSTAMP=$CTSTAMP 'BEGIN { print strftime("%b %d %T", TSTAMP); }') after $(TZ=UTC0 awk -v DAYS=$(($NTSTAMP/3600/24)) -v TSTAMP=$NTSTAMP 'BEGIN { print strftime(DAYS" days %H:%M:%S", TSTAMP); }')"; continue; }
        [[ $STATE -eq 3 ]] && { state "$HOST" "1"; continue; }
        [[ $STATE -eq 4 ]] && { state "$HOST" "2"; continue; }
    else
        [[ $STATE -eq 1 ]] && { state "$HOST" "3"; continue; }
        [[ $STATE -eq 2 ]] && { state "$HOST" "4"; continue; }
        [[ $STATE -eq 3 ]] && { NTSTAMP=$(($CTSTAMP-$HTSTAMP)); state "$HOST" "4" "$CTSTAMP"; 
            notify "Host DOWN Alert for $HOST" \
                   "Host $HOST is DOWN at $(awk -v TSTAMP=$CTSTAMP 'BEGIN { print strftime("%b %d %T", TSTAMP); }') after $(TZ=UTC0 awk -v DAYS=$(($NTSTAMP/3600/24)) -v TSTAMP=$NTSTAMP 'BEGIN { print strftime(DAYS" days %H:%M:%S", TSTAMP); }')"; continue; }
        [[ $STATE -eq 4 ]] && continue
    fi
done < $STATFILE

exit 0

############################################
# TODO/ChangeLog # Author     # Description
############################################
# 1.0.0 20151104 # Krisko     # Genesis
# 1.1.0 20160317 # Krisko     # Implemented Host Up/Down times
# 1.2.0 20160321 # Krisko     # Fixed date formatting using awk now
############################################

No comments:

Post a Comment