web-dev-qa-db-fra.com

Bash attend le succès du ping

J'écris sur un script en redémarrant divers serveurs. Après le redémarrage, je veux "attendre" jusqu'à ce que tous les serveurs soient de nouveau en ligne. (Pour que les choses restent simples, j'ai défini pour moi en ligne = pingable)

Donc, pour chaque serveur que je fais

ServerXY_W=1
echo -n "waiting for ServerXY ..."
while (($ServerXY_W == 1))
do
   if ping -c 1 -w 0.2 192.168.123.123 &> /dev/null
   then
      echo "ServerXY is back online!"
      ServerXY_W=0
   else
      echo -n "."
   fi
done

Ce que j'attendrais (et aimerais) serait un résultat comme par exemple.

waiting for ServerXY .................
ServerXY is back online!

où les points ... apparaissent un à un.

Mais ce qui se passe réellement, c’est d’abord

waiting for ServerXY ...

pendant un moment et quand le serveur est de retour je reçois le dernier point et la dernière ligne comme

waiting for ServerXY ....
ServerXY is back online!

Pourquoi la boucle while n'est-elle exécutée que deux fois, une fois avec échec du ping et une fois avec succès du ping? Que dois-je changer pour obtenir plus de points dans la boucle while?

J'ai aussi fait le test avec une adresse IP non existante. Mais il s'est coincé avec

waiting for NonExistentServer...

et jamais terminé bien sûr. Mais la même question, pourquoi le ........ n'est-il pas ajouté?

6
derHugo

Le problème

Le problème est que vous avez défini -w 0.2. Lorsque la valeur est inférieure à 1, les valeurs de date limite (-w) et de délai d'attente (-W) sont ignorées. Cela a été mentionné précédemment dans cette question . Lorsque vous utilisez -w 1, votre script (que j'ai légèrement modifié pour supprimer les bits inutiles) fonctionne correctement:

$ ./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

La solution évidente consiste à utiliser -w 1. Si vous envisagez d'utiliser une valeur inférieure à 1 seconde, la commande timeout devrait être meilleure:

$ 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

De nouveau, utilisez-le avec l'opérateur ! dans la boucle:

#!/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"
5