Bash aspetta il successo del ping


10

Sto scrivendo su uno script riavviando vari server. Dopo il riavvio, voglio "attendere" fino a quando tutti i server tornano online. (Per semplificare le cose, ho definito per me online = pingabile)

Quindi per ogni server che faccio

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

Quello che mi aspetterei (e mi piacerebbe) sarebbe un output come ad es

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

dove i punti .... apparirebbero uno per uno.

Ma ciò che realmente accade è che prima c'è solo

waiting for ServerXY ...

per un po 'e quando il Server è tornato ottengo l'ultimo punto e l'ultima riga come

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

Perché il ciclo while viene eseguito solo due volte come una volta con ping non riuscito e una volta con ping riuscito? Cosa devo modificare per ottenere più punti aggiunti nel ciclo while?

Ho fatto il test anche con un IP inesistente. Ma si è bloccato

waiting for NonExistentServer...

e ovviamente non è mai terminato. Ma la stessa domanda perché non ........vengono aggiunti?


Funziona bene per me ...: /
Ravexina,

Risposte:


9

Il problema

Il problema è che hai impostato -w 0.2. Quando il valore è inferiore a 1, i valori deadline ( -w) e timeout ( -W) vengono ignorati. Questo è stato menzionato in precedenza in questa domanda . Quando usi -w 1, il tuo script (che ho leggermente modificato per rimuovere i bit inutili) funziona correttamente:

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

Soluzione

La soluzione ovvia è usare -w 1. Se si intende utilizzare un valore inferiore a 1 secondo, il timeoutcomando dovrebbe essere migliore:

$ 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

Ancora una volta, usalo con l' !operatore nel ciclo:

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

Ovviamente si può applicare il contrario per mostrare il messaggio solo se il server è attivo e segnalare quando il server non funziona, ad esempio:

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

Nota, tuttavia, questo non è perfetto:

  • stiamo eseguendo il ping con solo 1 pacchetto al secondo. Bassa larghezza di banda, scarsa connettività, hardware difettoso tra il server e il client che eseguono il ping del server attiveranno il loop per uscire ed effettuare una notifica falsa positiva

  • Facciamo affidamento sul ping, ovvero sull'eco ICMP. I firewall o anche i singoli server bloccano le risposte all'eco ping / ICMP. Si potrebbe usare ncdi ncat(che è una versione migliorata del nc). Qualcosa come nel loop sopra funzionerà bene invece di ping:

    nc -w5 -z 172.16.127.2 80

    Quello che fa è connettersi al server su 172.16.127.2 sulla porta 80. -zè evitare l'I / O: basta connettersi e disconnettersi. -wdeve attendere 5 secondi prima di segnalare una connessione non riuscita. Naturalmente questo è abbastanza buono quando hai un server sotto il tuo controllo e sai che la porta 80 è aperta. UPD può essere usato bene, ma se è attivo un firewall, probabilmente è preferibile TCP.

    Un vantaggio nascosto qui è che se si dispone di un servizio in esecuzione su una porta specifica (come HTTP sulla porta 80 o RTSP su 554), la mancata connessione alla porta può servire come indicatore del servizio che deve essere riavviato.

  • Certo, nce pingpuò essere un po 'spammy. Il modo migliore sarebbe quello di fare il check-in del server con un altro server centrale, inviare un rapporto periodico, forse ogni ora; in questo modo se il tuo server perde un "punch time" puoi generare errori. Il modo migliore è utilizzare un servizio come Nagios, che lo fa. Ma a questo punto stiamo entrando nel regno dell'informatica di livello aziendale con più server. Se hai qualcosa come Raspberry Pi a casa, probabilmente non hai bisogno di nulla di complesso.


Ciao, grazie mille per aver chiarito quella cosa -w! C'è un modo diverso rispetto a farlo nella condizione di loop? È perfetto per l'attesa di un server, ma come detto sto aspettando più server in seguito, farò qualcosa del genere while (( $ServerA_W==1 || $ServerB_W==1 || .....))che vale quando ogni server è tornato.
derHugo,

Dopo ad esempio un server è di nuovo in attesa per gli altri non voglio il ping quello che è già di ritorno;)
derHugo

Suggerirei di scriverlo come funzione e di avviare l'istanza di ciascuna funzione con l'indirizzo IP come argomento in background. Ma sconsiglio di stampare i punti, lascia che ogni funzione stampi il messaggio quando viene visualizzato il server. Fammi sapere se vuoi che scriva un esempio di tale funzione
Sergiy Kolodyazhnyy,

1
@Joanne Sì, è possibile. Posso aggiornare la mia risposta più tardi oggi o domani. Personalmente, non farei il ping continuo del server perché è un po '
spammy

1
@Joanne Vedi i miei aggiornamenti nella risposta. Fammi sapere se questo aiuta o se ci sono altre domande
Sergiy Kolodyazhnyy
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.