Bash attend un succès ping

10

J'écris sur un script qui redémarre différents serveurs. Après le redémarrage, je veux «attendre» jusqu'à ce que tous les serveurs soient de nouveau en ligne. (Pour garder les choses 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 à quoi je m'attendrais (et aimerais) serait une sortie comme par exemple

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

où les points .... apparaîtraient un par un.

Mais ce qui se passe réellement, c'est d'abord qu'il n'y a que

waiting for ServerXY ...

pendant un certain temps 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 comme une fois avec l'échec du ping et une fois avec le ping qui réussit? Que dois-je changer pour ajouter plus de points dans la boucle while?

J'ai également fait le test avec une adresse IP inexistante. Mais il s'est coincé avec

waiting for NonExistentServer...

et jamais terminé bien sûr. Mais la même question, pourquoi ne pas ........être ajouté?

derHugo
la source
Fonctionne bien pour moi ...: /
Ravexina

Réponses:

9

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 délai ( -w) et de délai ( -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 est d'utiliser -w 1. Si vous avez l'intention d'utiliser une valeur inférieure à 1 seconde, la timeoutcommande 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

Encore une fois, 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"

Bien sûr, le contraire peut être appliqué à l'affichage d'un message uniquement si le serveur est en marche et signaler quand le serveur tombe en panne, exemple:

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

Notez cependant que ce n'est pas parfait:

  • nous pingons avec seulement 1 paquet chaque seconde. Faible bande passante, mauvaise connectivité, mauvais matériel entre le serveur et le client cinglant le serveur déclenchera la boucle pour quitter et faire une fausse notification positive

  • Nous comptons sur le ping, qui utilise l'écho ICMP. Des pare-feu ou même des serveurs individuels bloquent les réponses aux échos ping / ICMP. Vous pouvez utiliser ncde ncat( ce qui est une version améliorée nc). Quelque chose comme dans la boucle ci-dessus fonctionnera bien au lieu de ping:

    nc -w5 -z 172.16.127.2 80

    Ce que cela fait, c'est de se connecter au serveur sur 172.16.127.2 sur le port 80. -zc'est d'éviter les E / S - il suffit de se connecter et de se déconnecter. -west d'attendre 5 secondes avant de signaler l'échec de la connexion. Bien sûr, c'est un très bon choix lorsque vous avez un serveur sous votre contrôle et que vous savez que le port 80 est ouvert. UPD peut être utilisé correctement, mais s'il y a un pare-feu en place, TCP est probablement préféré.

    Un avantage caché ici est que si vous avez un service en cours d'exécution sur un port spécifique (tel que HTTP sur le port 80 ou RTSP sur 554), l'échec de la connexion au port peut servir d'indicateur que votre service a besoin d'un redémarrage.

  • Bien sûr, ncet pingpeut être un peu spam. La meilleure façon serait d'avoir l'enregistrement du serveur avec un autre serveur central, d'envoyer un rapport périodique, peut-être toutes les heures; De cette façon, si votre serveur manque un "temps de punch", vous pouvez générer des erreurs. Le meilleur moyen est d'utiliser un service tel que Nagios, qui le fait. Mais à ce stade, nous entrons dans le domaine de l'informatique au niveau de l'entreprise avec plusieurs serveurs. Si vous avez quelque chose comme Raspberry Pi à la maison, vous n'avez probablement pas besoin de quelque chose de complexe.

Sergiy Kolodyazhnyy
la source
Salut merci beaucoup d'avoir effacé cette chose -w! Existe-t-il une manière différente que de le faire en boucle? Il est parfait pour attendre un serveur, mais comme mentionné, j'attends plusieurs serveurs plus tard, je ferais quelque chose comme while (( $ServerA_W==1 || $ServerB_W==1 || .....))ce qui se passe lorsque chaque serveur est de retour.
derHugo
Après, par exemple, un serveur est de retour en attente des autres, je ne veux pas cingler celui qui est déjà de retour;)
derHugo
Je suggère d'écrire cela en tant que fonction et de lancer une instance de chaque fonction avec l'adresse IP comme argument en arrière-plan. Mais je vous déconseille d'imprimer les points, laissez simplement chaque fonction imprimer un message lorsque le serveur démarre. Faites-moi savoir si vous voulez que
j'écrive
1
@Joanne Oui, c'est possible. Je peux mettre à jour ma réponse plus tard dans la journée ou demain. Personnellement, je ne ferais pas de ping sur le serveur en continu car il est un peu spam, cependant
Sergiy Kolodyazhnyy
1
@Joanne Voir mes mises à jour dans la réponse. Faites-moi savoir si cela aide ou s'il y a d'autres questions
Sergiy Kolodyazhnyy