Bash wait for a ping success

Solution 1:

The issue

The problem is that you've set -w 0.2. When value is below 1, deadline (-w) and timeout (-W) values are ignored. This has been mentioned previously in this question. When you use -w 1 , your script (which I slightly modified to remove useless bits) works properly:

$ ./ping_server.sh                                                 
waiting for ServerXY ....................
Server is back online

$ cat ./ping_server.sh
#!/bin/bash
printf "%s" "waiting for ServerXY ..."
while ! ping -c 1 -n -w 1 147.153.237.192 &> /dev/null
do
    printf "%c" "."
done
printf "\n%s\n"  "Server is back online"

Solution

Obvious solution is to use -w 1. If you do intend on using a value lower than 1 second, the timeout command should be better:

$ timeout 0.2 ping -c 1 147.153.237.192                            
PING 147.153.237.192 (147.153.237.192) 56(84) bytes of data.
64 bytes from 147.153.237.192: icmp_seq=1 ttl=124 time=2.61 ms

--- 147.153.237.192 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 2.612/2.612/2.612/0.000 ms

Again, use it with ! operator in the loop:

#!/bin/bash
printf "%s" "waiting for ServerXY ..."
while ! timeout 0.2 ping -c 1 -n 147.153.237.192 &> /dev/null
do
    printf "%c" "."
done
printf "\n%s\n"  "Server is back online"

Of course the opposite can be applied to showing message only if server is up and report when server goes down, example:

$ while ping -q -c 1 172.16.127.2 >/dev/null ; do sleep 1; done ; echo "Server stopped responding"
Server stopped responding

Note however, this is not perfect:

  • we're pinging with just 1 packet every second. Low bandwidth, poor connectivity, bad hardware in between the server and client pinging the server will trigger the loop to exit and make false positive notification

  • We're relying on pinging, that is using ICMP echo. Firewalls or even individual servers block responses to ping/ICMP echo. You could use nc of ncat (which is an improved version of nc). Something like in the loop above will work fine instead of ping:

    nc -w5 -z 172.16.127.2 80
    

    What this does is connect to server on 172.16.127.2 on port 80. -z is to avoid I/O - just connect and disconnect. -w is to wait for 5 seconds before reporting failed connection. Of course this is a pretty good for when you have server under your control and you know the port 80 is open. UPD can be used fine, but if there's firewall in place, TCP is probably preferred.

    A hidden benefit here is that if you have some service running on specific port ( such as HTTP on port 80 or RTSP on 554 ), failing to connect to port may serve as indicator your service needs a restart.

  • Of course, nc and ping can be a bit spammy. Better way would be to have server check-in with another central server, send a periodic report, maybe each hour; that way if your server misses a "punch time" you can generate errors. Better way is to use a service such as Nagios, which does that. But at this point we're getting into the realm of enterprise-level computing with multiple servers. If you have something like Raspberry Pi at home, you probably don't need anything complex.