Bash loop ping successful

edumike picture edumike · May 25, 2011 · Viewed 99.3k times · Source

I'm thinking that this needs to be changed to a while clause, at the moment it'll wait till all 10000 pings are done, I need it to return when the ping is successful. The program "say" is on OSX it makes the computer speak.

#!/bin/bash
echo begin ping
if ping -c 100000 8.8.8.8 | grep timeout;
then echo `say timeout`;
else echo `say the internet is back up`;
fi

OK I don't have rights to answer my own question so here's my answer for it after playing around:

Thanks, yeah I didn't know about $? until now. Anyway now I've gone and made this. I like that yours doesn't go forever but in my situation I didn't need it to stop until it's finished.

#!/bin/bash
intertube=0
echo "begin ping"
while [ $intertube -ne 1 ]; do
        ping -c 3 google.com
        if [ $? -eq  0 ]; then
                echo "ping success";
                say success
                intertube=1;
        else
                echo "fail ping"
        fi
done
echo "fin script"

Answer

paxdiablo picture paxdiablo · May 25, 2011

You probably shouldn't rely on textual output of a command to decide this, especially when the ping command gives you a perfectly good return value:

The ping utility returns an exit status of zero if at least one response was heard from the specified host; a status of two if the transmission was successful but no responses were received; or another value from <sysexits.h> if an error occurred.

In other words, use something like:

((count = 100))                            # Maximum number to try.
while [[ $count -ne 0 ]] ; do
    ping -c 1 8.8.8.8                      # Try once.
    rc=$?
    if [[ $rc -eq 0 ]] ; then
        ((count = 1))                      # If okay, flag to exit loop.
    fi
    ((count = count - 1))                  # So we don't go forever.
done

if [[ $rc -eq 0 ]] ; then                  # Make final determination.
    echo `say The internet is back up.`
else
    echo `say Timeout.`
fi