Bash warten auf einen Ping-Erfolg

9

Ich schreibe über ein Skript, das verschiedene Server neu startet. Nach dem Neustart möchte ich "warten", bis alle Server wieder online sind. (Um die Dinge einfach zu halten, habe ich sie online definiert = pingbar)

Also für jeden Server, den ich mache

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

Was ich erwarten würde (und mag), wäre eine Ausgabe wie z

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

wo die Punkte ... würden eins nach dem anderen erscheinen.

Aber was tatsächlich passiert, ist, dass es zuerst nur gibt

waiting for ServerXY ...

für eine Weile und wenn der Server zurück ist, bekomme ich den letzten Punkt und die letzte Zeile wie

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

Warum wird die while-Schleife nur zweimal ausgeführt, einmal mit fehlgeschlagenem Ping und einmal mit erfolgreichem Ping? Was muss ich ändern, damit mehr Punkte in der while-Schleife hinzugefügt werden?

Ich habe den Test auch mit einer nicht vorhandenen IP durchgeführt. Aber es blieb hängen

waiting for NonExistentServer...

und natürlich nie gekündigt. Aber die gleiche Frage, warum wird das nicht ........hinzugefügt?

derHugo
quelle
Funktioniert gut für mich ...: /
Ravexina

Antworten:

8

Die Angelegenheit

Das Problem ist, dass Sie eingestellt haben -w 0.2. Wenn der Wert unter 1 liegt, werden die Werte für Deadline ( -w) und Timeout ( -W) ignoriert. Dies wurde bereits in dieser Frage erwähnt . Wenn Sie verwenden -w 1, funktioniert Ihr Skript (das ich leicht modifiziert habe, um nutzlose Bits zu entfernen) ordnungsgemäß:

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

Lösung

Offensichtliche Lösung ist zu verwenden -w 1. Wenn Sie einen Wert unter 1 Sekunde verwenden timeoutmöchten, sollte der Befehl besser sein:

$ 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

Verwenden Sie es erneut mit dem !Operator in der Schleife:

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

Natürlich kann das Gegenteil auf das Anzeigen von Nachrichten nur angewendet werden, wenn der Server aktiv ist, und melden, wenn der Server ausfällt. Beispiel:

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

Beachten Sie jedoch, dass dies nicht perfekt ist:

  • Wir pingen mit nur 1 Paket pro Sekunde. Geringe Bandbreite, schlechte Konnektivität und schlechte Hardware zwischen Server und Client, die den Server anpingen, lösen die Schleife aus und führen zu einer falsch positiven Benachrichtigung

  • Wir verlassen uns auf Ping, das ICMP-Echo verwendet. Firewalls oder sogar einzelne Server blockieren Antworten auf Ping / ICMP-Echo. Sie könnten verwenden ncvon ncat(das ist eine verbesserte Version von nc). Etwas wie in der obigen Schleife funktioniert einwandfrei anstelle von ping:

    nc -w5 -z 172.16.127.2 80

    Damit wird eine Verbindung zum Server unter 172.16.127.2 auf Port 80 hergestellt. -zUm E / A zu vermeiden, müssen Sie nur eine Verbindung herstellen und die Verbindung trennen. -wWarten Sie 5 Sekunden, bevor Sie eine fehlgeschlagene Verbindung melden. Dies ist natürlich ziemlich gut, wenn Sie den Server unter Ihrer Kontrolle haben und wissen, dass der Port 80 geöffnet ist. UPD kann problemlos verwendet werden, aber wenn eine Firewall vorhanden ist, wird TCP wahrscheinlich bevorzugt.

    Ein versteckter Vorteil besteht darin, dass, wenn auf einem bestimmten Port ein Dienst ausgeführt wird (z. B. HTTP auf Port 80 oder RTSP auf 554), die Nichtverbindung mit dem Port möglicherweise als Indikator dafür dient, dass Ihr Dienst neu gestartet werden muss.

  • Natürlich ncund pingkann ein bisschen spammig sein. Besser wäre es, wenn der Server bei einem anderen zentralen Server eincheckt und regelmäßig, möglicherweise stündlich, einen Bericht sendet. Auf diese Weise können Sie Fehler generieren, wenn Ihr Server eine "Punch Time" verpasst. Besser ist es, einen Dienst wie Nagios zu nutzen, der das tut. An diesem Punkt betreten wir jedoch den Bereich des Computing auf Unternehmensebene mit mehreren Servern. Wenn Sie so etwas wie Raspberry Pi zu Hause haben, brauchen Sie wahrscheinlich nichts Komplexes.

Sergiy Kolodyazhnyy
quelle
Hallo, vielen Dank, dass du das -w-Ding geklärt hast! Gibt es einen anderen Weg als im Loop-Zustand? Es ist perfekt, um auf einen Server zu warten, aber wie bereits erwähnt, warte ich später auf mehrere Server. Ich mache so etwas wie das, while (( $ServerA_W==1 || $ServerB_W==1 || .....))was gilt, wenn jeder Server zurück ist.
derHugo
Nachdem zB ein Server wieder auf die anderen wartet, möchte ich nicht den
anpingen, der
Ich würde vorschlagen, dies als Funktion zu schreiben und die Instanz jeder Funktion mit der IP-Adresse als Argument im Hintergrund zu starten. Ich würde jedoch empfehlen, die Punkte nicht zu drucken. Lassen Sie einfach jede Funktion eine Nachricht drucken, wenn der Server hochfährt. Lassen Sie mich wissen, wenn Sie möchten, dass ich ein Beispiel für eine solche Funktion schreibe
Sergiy Kolodyazhnyy
1
@ Joanne Ja, das ist möglich. Ich kann meine Antwort später heute oder morgen aktualisieren. Persönlich würde ich den Server nicht ständig anpingen, da er ein wenig spammig ist
Sergiy Kolodyazhnyy
1
@ Joanne Siehe meine Updates in der Antwort. Lassen Sie mich wissen, ob das hilft oder ob es irgendwelche anderen Fragen gibt
Sergiy Kolodyazhnyy