Home > front end >  Bash script to ping IP address and report with a datestamp when the station changes ping result in a
Bash script to ping IP address and report with a datestamp when the station changes ping result in a

Time:12-20

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;
  • Related