Requirement: Run extended pings from a number of cisco devices to generate a simple report on current latency and loss without using IP SLA commands. Allow the specification of source addresses where needed. SNMP write access is not available.
Solution: Expect and a shell script.
Funnily enough I found that this also ended up being quite useful for testing ISDN lines. You see some packet loss while the call is being set up but the SUCCESS message is what’s important there.
Configuration file: pingdevices.csv
#Router,Target IP,Description,Source IP (if desired)
10.0.0.254,10.0.0.101,Lab Gateway to Lab Server
10.0.0.253,192.168.1.64,LAB Switch to User PC,10.0.0.253
10.0.0.254,10.0.0.252,Lab 8kbps link router
Output:
[networks@nettools ~]$ ./pingcheck.sh
Timeout for Expect ping test is 30 seconds
Data will be read from pingdevices.csv in current directory (/home/networks) for tests.
Tacacs user:cisco
Tacacs pass:
Working on 10.0.0.254, Target IP 10.0.0.101.
[truncated expect output here to assist in debugging issues]
Time Device Target IP Status PKT% Min/Avg/Max Description
--------+---------------+---------------+--------+----+------------|-----------------------------
15:33:19|10.0.0.254 |10.0.0.101 |SUCCESS |100 |1/9/16 |Lab Gateway to Lab Server
15:33:19|10.0.0.253 |192.168.1.64 |SUCCESS |100 |20/28/40 |LAB Switch to User PC
15:33:21|10.0.0.254 |10.0.0.252 |SUCCESS |90 |4/9/20 |Lab Gateway to R7 router
--------+---------------+---------------+--------+----+------------+-----------------------------
Script: pingcheck.sh
#!/bin/bash
#
# Extended ping tester.
#
# v3.1 sol@subnetzero.org
#
# This script allows you to run extended pings across a large
# amount of devices, resulting in a report table once complete.
#
# Create a pingdevices.csv config file to use with this script
# in the following format:
#
# #Device,Ping-IP,Description#Source_Address(Optional)
# testrtr1,172.17.1.1,TEST-1,192.168.10.221
# testrtr2,10.10.10.1,TEST-2
#
# DO NOT USE COMMAS in the description field, or this will break
# any source address configuration in the final field.
pingexp_ssh(){
/usr/bin/expect << EOF
spawn ssh $USNAME@$DEVICE
#login handles cases:
# user/pass
# login with keys (first time verification)
expect {
"continue connecting (yes/no)?" {send "yes\r" ; exp_continue}
"assword:" { send "$PASS\r" }
}
expect -re "(>|#)" {send "term len 0\r"}
expect -re "(>|#)" {send "enable\r"}
expect "assword:" { send "$PASS\r" }
expect -re "(>|#)" {send "ping\r"}
expect {
"otocol" {send "ip\r"}
timeout {puts "\nRESULT:$TSTAMP\t$DEVICE\t$DESTIP\tFAIL\tNA\tNA\tERROR 01 - CMDERROR"
exit}
}
expect {
"address:" {send "$DESTIP\r"}
timeout {puts "\nRESULT:$TSTAMP\t$DEVICE\t$DESTIP\tFAIL\tNA\tNA\tERROR 02 - CMDERROR"
exit}
}
expect "count" {send "$PKTCNT\r"}
expect "size" {send "$PKTLEN\r"}
expect "seconds" {send "3\r"}
expect "commands" {send "n\r"}
expect "range" {send "n\r"}
# Check for success marks
set timeout 30
expect {
-re "Success rate is.*\n" {puts "latency"
puts \$expect_out(0,string)
puts [lindex \$expect_out(0,string) 3]
puts "\nRESULT:$TSTAMP\t$DEVICE\t$DESTIP\tSUCCESS\t[lindex \$expect_out(0,string) 3]\t[lindex \$expect_out(0,string) 9]\t$DESCRP"
puts "End of Output"
}
timeout {puts "\nRESULT:$TSTAMP\t$DEVICE\t$DESTIP\tFAIL\tNA\t$DESCRP"}
}
set timeout 7
# Logout
expect {
"#" { send "exit\r" }
timeout { exit }
}
EOF
}
pingexp_ssh_srcip(){
/usr/bin/expect << EOF
spawn ssh $USNAME@$DEVICE
#login handles cases:
# user/pass
# login with keys (first time verification)
expect {
"continue connecting (yes/no)?" {send "yes\r" ; exp_continue}
"assword:" { send "$PASS\r" }
}
expect -re "(>|#)" {send "term len 0\r"}
expect -re "(>|#)" {send "enable\r"}
expect "assword:" { send "$PASS\r" }
expect -re "(>|#)" {send "ping\r"}
expect {
"otocol" {send "ip\r"}
timeout {puts "\nRESULT:$TSTAMP\t$DEVICE\t$DESTIP\tFAIL\tNA\tNA\tERROR 03 - CMDERROR"
exit}
}
expect {
"address:" {send "$DESTIP\r"}
timeout {puts "\nRESULT:$TSTAMP\t$DEVICE\t$DESTIP\tFAIL\tNA\tNA\tERROR 04 - CMDERROR"
exit}
}
expect "count" {send "$PKTCNT\r"}
expect "size" {send "$PKTLEN\r"}
expect "seconds" {send "3\r"}
expect "commands" {send "y\r"}
expect "ource address" {send "$SRCADD\r"}
expect "ype of service" {send "\r"}
expect "DF bit in IP header" {send "\r"}
expect "alidate reply data" {send "\r"}
expect "ata pattern" {send "\r"}
expect "erbose" {send "\r"}
expect "range" {send "n\r"}
# Check for success marks
set timeout 30
expect {
-re "Success rate is.*\n" {puts "latency"
puts \$expect_out(0,string)
puts [lindex \$expect_out(0,string) 3]
puts "\nRESULT:$TSTAMP\t$DEVICE\t$DESTIP\tSUCCESS\t[lindex \$expect_out(0,string) 3]\t[lindex \$expect_out(0,string) 9]\t$DESCRP"
puts "End of Output"
}
timeout {puts "\nRESULT:$TSTAMP\t$DEVICE\t$DESTIP\tFAIL\tNA\t$DESCRP"}
}
set timeout 7
# Logout
expect {
"#" { send "exit\r" }
timeout { exit }
}
EOF
}
########### SET VARS ##########
#
# Number of and size of packets
#
PKTCNT=10
PKTLEN=100
#
# Set inut file to be used
if [ "$1" ]; then
if [ -r "$1" ]; then
DEVICEFILE=$1
else
echo "Input file $1 not found or is not readable."
exit 1
fi
else
DEVICEFILE=pingdevices.csv
fi
########### Sanity ############
#
if [ ! -w . ]; then
echo "Error: Can't write to current directory."
exit 1
fi
########### Cleanup ###########
#
cat /dev/null > pingcheck.log
######### USER INPUT ##########
#
printf "Data will be read from $DEVICEFILE in current directory ($PWD) for tests.\n\n"
printf "Tacacs user:" ; read USNAME; stty -echo
printf "Tacacs pass:" ; read PASS ; printf "\n" ; stty echo
# Set IFS to newline so we can read whole lines as elements
#
IFS="
"
# Loop through each line and run the ping check
#
for DATALINE in `egrep -v "^$|^#" $DEVICEFILE`; do
TSTAMP=`date +%H:%M:%S`
DEVICE=`echo $DATALINE | awk -F"," '{print $1}' | egrep -v "^#|^$"`
DESTIP=`echo $DATALINE | awk -F"," '{print $2}'`
DESCRP=`echo $DATALINE | awk -F"," '{print $3}'`
SRCADD=`echo $DATALINE | awk -F"," '{print $4}' |\
egrep '^[[:digit:]]{1,3}\.[[:digit:]]{1,3}\.[[:digit:]]{1,3}\.[[:digit:]]{1,3}$'`
ERRMSG="\nRESULT:$TSTAMP\t$DEVICE\t$DESTIP\tFAIL"
printf "Working on $DEVICE, Target IP $DESTIP.\n"
ping -c1 -w1 $DEVICE > /dev/null
if [ "$?" -eq "0" ]; then
if [ "$SRCADD" ]; then
pingexp_ssh_srcip | tee -a pingcheck.log
else
pingexp_ssh | tee -a pingcheck.log
fi
else
printf "\nRESULT:$TSTAMP\t$DEVICE\t$DESTIP\tFAIL\tNA\tNA\t$DESCRP\n" >> pingcheck.log
fi
done
echo "
Time Device Target IP Status PKT% Min/Avg/Max Description
--------+---------------+---------------+--------+----+------------|-----------------------------" > pingresults.txt
grep "^RESULT" pingcheck.log |\
cut -d":" -f2- | \
awk '{tail = substr ($0,length($1 $2 $3 $4 $5 $6) +7)}
{printf ("%8.8s|%-15.15s|%-15.15s|%-8.8s|%-4.4s|%-12.12s|%-30.30s\n",$1,$2,$3,$4,$5,$6,tail);
}'>> pingresults.txt
echo "--------+---------------+---------------+--------+----+------------+-----------------------------" >> pingresults.txt
clear
cat pingresults.txt