I scraped together a bash script to do multi-ping logging on Centos/Debian, when run from console it works fine, but run under crontab, the variable $NUM is left blank which should be a number such as 02 or 03, which lets the script find the IP address to ping from the config file.
More info: The goal is to provide bare basic ping data to an ISP that refuses to recognize advanced tools like MTR or router logs/graphs for troubleshooting. The ISP is having packet loss on several circuits, and they check it and say "looks good to us", they recognize ping data as a valid troubleshooting tool, so my ping script saves ping data in 10 minute increments to timestamped files, then another script sorts those files for any high latency or packet loss, which I send to the ISP as proof that the failure is inside their network. I have a backup ISP that I also log at the same time as proof that the destinations are generally available via other providers. My scripting skills are not fantastic, so I definitely consider any improvements.
Script has 2 components, a cfg file:
### Main program variables:
SPOOLDIR="/var/spool/pingstats"
BADPINGSDIR="/tmp/badpings"
BADPINGLOG="$BADPINGSDIR/badpings.log"
PINGLOG="$PROGRAMDIR/ping.log"
##### Set NODE NAMES (its just a name), host can be IP or hostname ie abc.com and maxping latency thresholds (edit/add nodes as needed)
NODENAME01=router
HOST01=10.0.0.1
MAXPING01=5
NODENAME02=dns1
HOST02=68.6.16.30
MAXPING02=35
NODENAME03=dns2
HOST03=1.1.1.1
MAXPING03=35
NODENAME04=fibergw
HOST04=77.77.77.74
MAXPING04=10
## Several more....
The script:
#!/bin/bash
## Base variables
PROGRAMDIR="/root/pingstats"
PINGCONF="$PROGRAMDIR/PingConfig.cfg"
TIMESTAMP="$(date +%Y%m%d%H%M)"
TIMESTAMP2() {
date +"%Y-%m-%d_%H:%M:%S" # current time
}
source $PINGCONF
## check dir structure:
if [ ! -d $SPOOLDIR ]; then
mkdir $SPOOLDIR
fi
## Loop through each nodename listed in cfg
for n in `grep NODENAME $PINGCONF`
do
echo "Processing Node: $n"
echo "$(TIMESTAMP2) : Processing Node: $n" >> $PINGLOG
#### The next couple of lines are the problem, because $NUM ends up blank via cron
NUM=$(grep -oE '[N]ODENAME.{,2}' <<< "$n" | grep -o '[0-9]+')
echo "Node number for $n is $NUM" >> $PINGLOG
HOSTTMP=HOST$NUM
HOSTIP=${!HOSTTMP}
echo "NODE is $n and HOSTIP is $HOSTIP"
if [ ! -d "$SPOOLDIR/$NODENAME" ]; then
mkdir "$SPOOLDIR/$NODENAME"
fi
echo "$(TIMESTAMP2) : Pinging NODE: $NODENAME at $HOSTIP logging to file:
$SPOOLDIR/$NODENAME/$TIMESTAMP" >> $PINGLOG
echo " Starting ping to $HOSTIP"
ping -i 2 -s 8000 -c 300 $HOSTIP > "$SPOOLDIR/$NODENAME/$TIMESTAMP" &
sleep 1
done
Expected to see several processes to be running pings. The logging shows me this:
2024-09-05_13:08:03 : Processing Node: NODENAME02=dns1
Node number for NODENAME02=dns1 is
2024-09-05_13:08:03 : Pinging NODE: at logging to file:
/var/spool/pingstats//202409051308
There is a blank after the is and at, which should show $NUM and $HOSTIP, which was found via nested var $HOST$NUM
My /etc/crontab is:
*/10 * * * * root /root/pingstats/ping-nodes
Successful run from console spawns several processes such as:
ps aux | grep ping
root 14533 0.0 0.1 1952 580 pts/8 S 13:19 0:00 ping -i 2 -s 8000 -c 300 10.0.0.1
root 14550 0.0 0.1 1952 584 pts/8 S 13:19 0:00 ping -i 2 -s 8000 -c 300 68.6.16.30
root 14560 0.0 0.1 1952 580 pts/8 S 13:19 0:00 ping -i 2 -s 8000 -c 300 1.1.1.1
root 14570 0.0 0.1 1952 580 pts/8 S 13:19 0:00 ping -i 2 -s 8000 -c 300 77.77.77.74
2
Answers
Thanks for everyone's patience, I did some revisions and cleanup and came up with this working method that works the same on console or crontab:
Ping.cfg file (used in a few other scripts)
Script:
Sorry if my code isn't great, I have written ~5000 lines of bash over the last 20 years, I'm probably 6/10 on expertise.
Simply by sourcing your
PingConfig.cfg
If you’re confident with content of
$PINGCONF
, you could source them. (Care, this will execute commands, if present in your config file!)Notes:
printf '%(date format string)T'
instead of fork todate
, for date time print.