Pings

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;