I started with needing to ping a remote office Cisco Catalyst over my SD/WAN network. Basic ping commands work acceptably well, however the pile of output is both daunting and not very useful. More specifically what I need are date and time stamps of when the remote Catalyst changes its ping state. The date and time when it is unreachable, and the date and time when it becomes reachable again. I don't need any of the ping details, just to know when the UP and DOWN happen. I have a script that I wrote, it didn't work properly, and so I tried to simplify it, and it also didn't work properly. So I turn to you folks, has anyone else tried this with ping?
#!/bin/bash
skip=no
while :
do
if [[ `ping -c 1 $1 &> /dev/null` ]] && [[ skip = "no" ]]
then
echo "Target is up at: $(TZ='America/New_York' date)"
skip=yes
else
echo "Target is down at: $(TZ='America/New_York' date)"
skip=yes
fi
if ping -c 1 $1 &> /dev/null
then
skip=no
else
skip=yes
fi
sleep 5
done
Thanks :)
What I got out of it didn't do what I expected. I have another catalyst locally, I configured that to be 10.1.1.51 on my LAN, and when I have it connected to the rest of the network I get the datestamp and the ping response that it is up, and that behaves fine, and then I unplug it, and in a few moments, I get a another timestamp that it's down. Then another report that it's down, and another, and another. I think it's an edge case and the fault I think is in my if-then-else-fi logic, but I've tried many other arrangements and either the "Ping success" message repeats, or the "Ping Failure" messge repeats, but not the way I want, which is just report when the state changes and otherwise just sit there testing and pinging and waiting for the state to change. It's been years since I did anything like this, heh, necessity is the mother of invention, I guess. :)
CodePudding user response:
The first thing I see is that [[ `ping -c 1 $1 &> /dev/null` ]]
will always fail, because it's testing to see if the output from ping -c 1 $1 &> /dev/null
is non-empty, and since the output is discarded by &> /dev/null
it'll never be anything but empty. I think you just want ping -c 1 $1 &> /dev/null
(like the other if
statement) without any of the other faff.
The logic with skip
also looks weird; I'd just remove that entirely, and have two separate subloops: one for while it's working, one for while it's failing. Something like this:
#!/bin/bash
# If the target is initially up, we need to print that
# before going into the monitor loop.
if ping -c 1 $1 &> /dev/null
then
echo "Target is up at: $(TZ='America/New_York' date)"
fi
while :
do
# At this point in the script, the target is either
# up and we need to wait for it to go down, or we
# just started and it's down (in which case this
# loop will exit immediately).
while ping -c 1 $1 &> /dev/null
do
sleep 5
done
# At this point, it's gone down; print a note, and
# wait for it to come back up.
echo "Target is down at: $(TZ='America/New_York' date)"
until ping -c 1 $1 &> /dev/null
do
sleep 5
done
# It's back up! Print another note, then go back to
# waiting for it to fail.
echo "Target is up at: $(TZ='America/New_York' date)"
done
CodePudding user response:
I asked around on Mastodon and someone posted this as a solution. It works just like I wanted it to. So my original effort was rubbish and is off to the big bit bucket in the sky.
Here's the script, it works, I'm walkin away.
#!/bin/bash
TZ='America/New_York'
export TZ
ping -i 5 "$1" 2>&1 | awk '/Host/{ state="Down" } /time/{ state="Up" } prev_state!=state{prev_state=state; print strftime(), host, state}' host=$1;