Pings


This ain't no smokeping. It works though and isn't very complex. The core script is called by Cron every 5 minutes. It cycles through a targets file sending out 20 ICMP echo requests to each target and dumping the results into an RRD. It then calls a second script that generates these graphs:

 
To monitor a new host, you just add it to the targets file and call pings.sh with "create" as its first argument. After this, the next time the main program is called from Cron, it will begin collecting stats.

The core is pings.sh:

#!/usr/local/bin/bash
# Cron entry:
# */5     *       *       *       *       /home/flow/Code/Pings/pings.sh run > /dev/null 2>&1

export PATH="/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin"

args=$@

baseDir="/home/flow/Code/Pings"

targets=`cat ${baseDir}/targets.txt | sed '/#/d'`
rrd_dir="${baseDir}/RRDs"

dses="
    ploss
    pmin
    pavg
    pmax
    pstddev
"

## Timestamp for RRD
step=300
now=`date +"%s"`
unixTime=`awk "BEGIN {print ($step * int(($now / $step) + 0.5))}"`

if [ ! $args ]; then

    echo "Usage: ping_times.sh <create>|<run>"

## Create RRD's
elif [ $args = "create" ]; then

    for x in $targets; do

        name=`echo $x | awk -F "," '{print $2}'`

        for y in $dses; do
            if [ ! -e $rrd_dir/pings_${name}_${y}.rrd ]; then
                echo "Creating $rrd_dir/pings_${name}_${y}.rrd"
                rrdtool create $rrd_dir/pings_${name}_${y}.rrd --step 300 --start `date -v0H -v0M -v0S "+%s"` \
                DS:${y}:GAUGE:400:U:U \ RRA:MAX:0.5:1:105120
            fi
        done
    done

## Establish ping stats
elif [ $args = "run" ]; then

    for x in $targets; do

        go="no"
        ip=`echo $x | awk -F "," '{print $1}'`
        name=`echo $x | awk -F "," '{print $2}'`

        loss=U; min=U; avg=U; max=U; stddev=U
 
        base=`ping -n -W 6 -c 20 -q $ip | tail -n 2`

        if [ ${base:0:1} = "-" ]; then
            loss=`echo "$base" | sed 1d | awk -F "," '{print $3}' | awk '{print $1}' | tr -d "%"`
            go="yes"
        else
            stats=`echo "$base" | sed 1d | awk -F "=" '{print $2}'`
            loss=`echo "$base" | sed 2d | awk -F "," '{print $3}' | awk '{print $1}' | tr -d "%"`
            min=`echo "$stats" | awk -F "/" '{print $1}' | tr -d " "`
            avg=`echo "$stats" | awk -F "/" '{print $2}'`
            max=`echo "$stats" | awk -F "/" '{print $3}'`
            stddev=`echo "$stats" | awk -F "/" '{print $4}' | tr -d "ms"`
            go="yes"
        fi

        # Update RRD's
        if [ $go = "yes" ]; then
                rrdtool update ${rrd_dir}/pings_${name}_ploss.rrd $unixTime:$loss
                rrdtool update ${rrd_dir}/pings_${name}_pmin.rrd $unixTime:$min
                rrdtool update ${rrd_dir}/pings_${name}_pavg.rrd $unixTime:$avg
                rrdtool update ${rrd_dir}/pings_${name}_pmax.rrd $unixTime:$max
                rrdtool update ${rrd_dir}/pings_${name}_pstddev.rrd $unixTime:$stddev
        fi

        # Update Graphs
        $baseDir/gr_pings.sh 800 50 $name

    done

else

    echo "Invalid args!"

fi


Once this completes, it fires this piece which generates the graphs:

 #!/usr/local/bin/bash

args=("$@")

if [ "$#" -ne 3 ]; then

echo "Usage: <width> <height> <RRD prefix>"
echo "Example: ${0}.sh 800 150 blah"

else
                                                                                                                                                            
# Set some dirs
rrd_dir="/home/flow/RRDs/Pings"
img_dest="/usr/local/www/graphs/pings"

# Colours
background="#ffffff"

# Size
width=${args[0]}
height=${args[1]}

# Data
rrd=${args[2]}
outfile=${args[2]}

echo "$height $width $rrd $outfile"

# Find out what day it is
ymd=`date "+%Y-%m-%d"`

# Today at midnight
mark00=`date -v0H -v0M -v0S "+%s"`

# Timestamp
stamp=`date | sed  's/:/\\:/g' | sed 's/ /\\,,/g'`
sign="%"

reps=".--end=23:59.$ymd.--x-grid=MINUTE:30:HOUR:1:HOUR:2:0:%R.$stamp \
.--end=now.${ymd}_24..24Hrs. \
--start=end-3h.--end=now.3..3Hrs. \
--start=end-1w.--end=now.w.--x-grid=DAY:1:DAY:1:DAY:1:0:%b%d.weekly \
--start=end-1m.--end=now.m.--x-grid=DAY:1:WEEK:1:WEEK:1:0:%b%d.monthly \
--start=end-1y.--end=now.y..yearly"

y=0;

for x in $reps; do

start=`echo $x | awk -F . '{print $1}'`
end=`echo $x | awk -F . '{print $2}'`
char=`echo $x | awk -F . '{print $3}'`
axis=`echo $x | awk -F . '{print $4}'`
title=`echo $x | awk -F . '{print $5}' | sed 's/,,/ /g'`

rrdtool graph $img_dest/pings_${outfile}_${char}.png \
 $start \
 $end \
 --width=$width \
 --height=$height \
 --vertical-label="ms" \
 --imgformat=PNG \
 --interlace \
 --c=CANVAS$background \
 --watermark "$title" \
 $axis \
 DEF:ploss=$rrd_dir/pings_${rrd}_ploss.rrd:ploss:MAX \
 DEF:pmin=$rrd_dir/pings_${rrd}_pmin.rrd:pmin:MAX \
 DEF:pavg=$rrd_dir/pings_${rrd}_pavg.rrd:pavg:MAX \
 DEF:pmax=$rrd_dir/pings_${rrd}_pmax.rrd:pmax:MAX \
 DEF:pstddev=$rrd_dir/pings_${rrd}_pstddev.rrd:pstddev:MAX \
 CDEF:fmax=pmax,pavg,- \
 COMMENT:"$rrd\l" \
 \
 LINE1:pavg \
 \
 AREA:fmax#b1bdcd::STACK \
 \
 LINE1:pmin#b1bdcd \
 \
 LINE3:pavg#003366:"median rtt\t\t" \
 GPRINT:pavg:AVERAGE:"%5.2lf ms avg  " \
 GPRINT:pavg:MIN:"%5.2lf ms min  " \
 GPRINT:pavg:MAX:"%5.2lf ms max  " \
 GPRINT:pavg:LAST:"%5.2lf ms now\l" \
 \
 LINE1:pstddev#000000:"deviation\t\t\t" \
 GPRINT:pstddev:AVERAGE:"%5.2lf ms avg  " \
 GPRINT:pstddev:MIN:"%5.2lf ms min  " \
 GPRINT:pstddev:MAX:"%5.2lf ms max  " \
 GPRINT:pstddev:LAST:"%5.2lf ms now\l" \
 \
 AREA:ploss#FF5B00:"packet loss\t\t" \
 GPRINT:ploss:AVERAGE:"%5.2lf  %% avg  " \
 GPRINT:ploss:MIN:"%5.2lf  %% min  " \
 GPRINT:ploss:MAX:"%5.2lf  %% max  " \
 GPRINT:ploss:LAST:"%5.2lf  %% now\l" \
 VRULE:$mark00#a50000
 let y=y+1;
done;
fi;


Download