Skip to content

Instantly share code, notes, and snippets.

@microlinux
Last active December 10, 2021 16:37
Show Gist options
  • Save microlinux/77feda4449a8041a19a7 to your computer and use it in GitHub Desktop.
Save microlinux/77feda4449a8041a19a7 to your computer and use it in GitHub Desktop.
Pings multiple hosts concurrently and prints results in CSV format
#!/bin/bash
# this program is placed into the public domain
# https://gist.github.com/microlinux/77feda4449a8041a19a7
#
# THIS FILE MUST BE IN YOUR SYSTEM PATH
#
# defaults
COUNT=5
INTERVAL=1
WORKERS=25
targets=''
function usage()
{
echo
echo 'ping targets concurrently and display ordered csv results'
echo
echo 'usage: mping.sh [option] ... [target] ...'
echo
echo 'options:'
echo ' -c ping count (5)'
echo ' -i ping interval (1)'
echo ' -w max workers (25)'
echo
echo 'examples:'
echo ' mping.sh -c10 -i.5 google.com yahoo.com askjeeves.com bing.com'
echo ' cat targets.conf | mping.sh -w50'
echo
echo 'output:'
echo ' <target>,<sent>,<recvd>,<pctloss>,<min>,<avg>,<max>'
echo
exit 0
}
# if the first arg is mpingworker, this is a ping request
if [ $1 = 'mpingworker' ]
then
output=$(ping -c "$3" -i "$4" -W 1 -q "$2" 2> /dev/null)
if [ -z "$output" ]
then
echo "$2,,,,,"
exit 0
fi
recvd=($(grep -o '[0-9]\+ received' <<< "$output"))
recvd="${recvd[0]}"
if [ "$recvd" -eq 0 ]
then
echo "$2,$3,0,100,,,"
exit 0
fi
stats=($(grep -o '[0-9.]\+/[0-9.]\+/[0-9.]\+' <<< "$output" | tr '/' ' '))
# sed 's/....$//' chops off the fractional part of an rtt
min=$(sed 's/....$//' <<< ${stats[0]})
avg=$(sed 's/....$//' <<< ${stats[1]})
max=$(sed 's/....$//' <<< ${stats[2]})
pctloss=$(grep -o '[0-9]*%' <<< "$output" | cut -d ' ' -f 6 | tr -d '%')
echo "$2,$3,$recvd,$pctloss,$min,$avg,$max\n"
exit 0
fi
# if we get here, this is the main process
while getopts 'hc:i:w:' opt
do
case "$opt" in
h)
usage
exit 0
;;
c)
if [ ! -z "$OPTARG" ]
then
COUNT="$OPTARG"
fi
;;
i)
if [ ! -z "$OPTARG" ]
then
INTERVAL="$OPTARG"
fi
;;
w)
if [ ! -z "$OPTARG" ]
then
WORKERS="$OPTARG"
fi
;;
esac
done
# chop opts from arg list
shift $((OPTIND - 1))
if [ $# -eq 0 ]
then
# if no args left, read targets from stdin
while read target
do
targets="$targets\n$target"
done
else
# otherwise use remaining args as targets
for target in "$@"
do
targets="$targets\n$target"
done
fi
# mass ping targets
results=$(echo -e "$targets" | xargs -n 1 -I ^ -P "$WORKERS" ./mping.sh mpingworker ^ "$COUNT" "$INTERVAL")
# convert targets into an array
targets=($(sed 's/\\n/ /g' <<< "$targets"))
# display results in the order targets were given
for target in "${targets[@]}"
do
echo -e "$results" | grep "$target" 2> /dev/null
done
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment