Netzwerkanalyse mit Ping und Gnuplot

ping stat image

Für Netzwerkanalyse in Echtzeit ist ping gut geeignet, besser noch mrt. Wenn es aber darum geht Schwankungen in der Übertragung zu dokumentieren wird das mit diesen Tools schwierig. Dieses Skript kann die Pings zu einem Host über längere Zeiträume machen. Das Ergebnis wird grafisch aufbereitet und in PDF Format dokumentiert. Wie in diesem Beispiel, wo das zeitweise Aussetzen der Netzwerkschnittstelle eines OKI-Druckers dokumentiert wird, das nur sporadisch auftritt, aber auf einen Defekt hinweist.

Dieser Skript erfordert GhostScript, Gnuplot lokal installiert. Der eigentliche Ping kann auch über eine SSH Verbindung von einem anderen Host aus geschehen, dort wird lediglich ping und ein ssh-server benötigt. Empfohlen ist natürlich eine eingerichtete Hostkey-Authentifizierung. Der Host könnte auch ein BSD oder OSX sein, das sollte prinzipiell auch gehen. Für Linux sollte man iputils-ping installiert haben, andere Varianten funktionieren wahrscheinlich nicht, weil die Ausgaben von ping andere Formatierung haben.

Im Ergebnis sieht man sogar das nichtmonotone Eintreffen der ICMP Antworten, da die Verbindungslinien der Punkte chronologisch sind, die Punke aber in der Reihenfolge der ICMP Anfragen sind. Paketverluste sind auffällig durch jeweils eine senkrechte Linie zu sehen. Das ist schon bedeutend aussagekräftiger als nur eine Zusammenfassung wie bei ping, wo man zwar sieht dass es Paketverluste gibt, aber nicht wo genau.

Auf einer zweiten Seite werden die Ergebnisse in einem Histogramm zusammengefasst, und auf einer dritten Seite sind statistische Parameter gelistet.

pingstat.sh:

download

#!/bin/bash
#   Ping-Statistik mit geringem Aufwand (Vergleich zu smokeping)
#  erfordert GhostScript, Gnuplot
#
usage() {
    echo "usage: pingstat.sh [source hostname/ip] [target hostname/ip] [number of pings] [time interval between pings] [psize]"
    echo "   default:                 -                    -                  100                       0.1               56"
    echo " you need rights to execute sudo on ping and if your source is a remote host you need ssh to it."
    exit 0
}
if [ "$1" = "-h" ]
then usage
fi

if [ -n "$1" ]
then QUELLHOST=$1
    if [ "$QUELLHOST" != "$(hostname)" ]
    then REMOTEHOST=$QUELLHOST
	 echo "run from remote host: $REMOTEHOST"
    fi
else usage
fi
if [ -n "$2" ]
then ZIEL=$2
else usage
fi
if [ -n "$3" ]
then ANZAHL=$3
else ANZAHL=100
fi
if [ -n "$4" ]
then INTV=$4
else INTV=0.1
fi
if [ -n "$5" ]
then PSIZE=$5
else PSIZE=56
fi
#

DAUER=$(echo "$INTV * $ANZAHL" | bc)
echo "Testdauer: $DAUER s"
PDFDATUM=$(date +%Y%m%d%H%M%S:%z)
DATUM=$(date +%Y%m%d%H%M%S)
CREDATUM=$PDFDATUM
TITLE="Pingtest $QUELLHOST - $ZIEL"
USERNAME=$(getent passwd "$USER"|cut -d':' -f5|cut -d',' -f1)   # Benutzername ermitteln
FNAME=ping+${QUELLHOST}+X$ZIEL-$DATUM
PDFMETADATA=$FNAME.pdfmeta
PINGAUSGABE=$FNAME.ping
PDFDATEI=$FNAME.pdf
STATDATEI=$FNAME.stats
CSV1=$FNAME.csv
CSV2=$FNAME-missing.csv
TMPPDF1=$FNAME-temp1.pdf
TMPPDF2=$FNAME-temp2.pdf
TMPPDF3=$FNAME-temp3.pdf
GnuPlotFile=$FNAME.p
#------------------------------------------
CreateMetaDataFile() {
#   Jetzt Datei mit Metadaten vorbereiten
cat > "$1" <<EOF
[ /Title ($TITLE)
  /Author ($USERNAME)
  /Subject (ping $ZIEL from $QUELLHOST)
  /Keywords (io performance,benchmark,ping,icmp)
  /ModDate (D:$PDFDATUM)
  /CreationDate (D:$CREDATUM)
  /Creator (ping and gnuplot, modified by GhostScript)
  /Producer (gnuplot and poppler)
  /DOCINFO pdfmark
EOF
}
CreateGnuplotFile() {
#  PDF-Datei nachbearbeiten, dazu Datei vornbereiten…
cat > "$1" <<EOF
title1='Pingzeit $QUELLHOST to $ZIEL, ($PSIZE b). $INTV s, $RESULT'
title2='Pingstatistik $BREITE'
datum='$(date -Is)'
datei1='$CSV1'
datei2='$CSV2'
ausgabe1='$TMPPDF1'
ausgabe2='$TMPPDF2'
miss='$MISS'
EOF
}

run_test() {
#    echo "Teste $1"
    if [ -n "$REMOTEHOST" ]
    then ssh "root@$REMOTEHOST" "ping -n -s \"$PSIZE\" -i \"$INTV\" -c \"$ANZAHL\" \"$1\" " >"$2"
    else sudo ping -n -s "$PSIZE" -i "$INTV" -c "$ANZAHL" "$ZIEL" >"$2"
    fi
}
get_missing()  {
YYY=0
grep "time=" "$1"|awk '{print $5}'|cut -d'=' -f2|sort -n|while read -r XXX
do
#	echo $XXX : $YYY
	YYY=$((YYY+1))
	while [ $YYY -lt "$XXX" ]
	do
		echo "$YYY"
		YYY=$((YYY+1))
	done
done
}
#
echo "Pingtest von $QUELLHOST auf $ZIEL mit $PSIZE × $ANZAHL pings im Intervall $INTV"
run_test  "$ZIEL"   "$PINGAUSGABE"
RESULT=$(grep received "$PINGAUSGABE")
#
awk '{printf "%s,%s\n",$5,$7}' "$PINGAUSGABE" |sed -e "s/time=//g" -e "s/icmp_[sr]eq=//g" |head -n -4|tail -n +2 >"$CSV1"
get_missing "$PINGAUSGABE" >"$CSV2"
MISS=$(awk '{x++}END{ print x}' "$CSV2")
CreateMetaDataFile "$PDFMETADATA"
CreateGnuplotFile "$GnuPlotFile"
cat /usr/lib/pingstat/pingstat.gnu >> "$GnuPlotFile"
#
#gnuplot -e "includefile='$GnuPlotFile'" pingstat.p 2>$STATDATEI || exit 1
gnuplot "$GnuPlotFile" 2>"$STATDATEI" || exit 1
txt2pdf.py --landscape 1 --output "$TMPPDF3" "$STATDATEI"
# Nachbearbeting der PDF Dateien
gs -dSAFER -dBATCH -dNOPAUSE -sDEVICE=pdfwrite -sOutputFile="$PDFDATEI" "$TMPPDF1" "$TMPPDF2" "$TMPPDF3" "$PDFMETADATA"
# Aufräumen
rm "$TMPPDF1" "$TMPPDF2" "$TMPPDF3" "$PDFMETADATA" #"$PINGAUSGABE" #"$STATDATEI"  #temp.inc

Dazu gehört die Datei, die GnuPlot verwendet. pingstat.p:

download