Bash espera por um sucesso de ping

5

Estou escrevendo em um script reinicializando vários servidores. Após a reinicialização eu quero "esperar" até que todos os servidores estejam novamente online. (Para manter as coisas simples, eu defini para mim online = pingável)

Então, para cada servidor que eu faço

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

O que eu esperaria (e como) seria uma saída como, por exemplo,

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

onde os pontos .... apareceriam um por um.

Mas o que acontece é que primeiro só existe

waiting for ServerXY ...

por um tempo e quando o servidor está de volta eu recebo o último ponto e a última linha como

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

Por que o loop while é executado apenas duas vezes como uma vez com o ping falhando e uma vez com o êxito do ping? O que eu tenho que mudar para obter mais pontos adicionados no loop while?

Eu fiz o teste também com um IP inexistente. Mas ficou preso com

waiting for NonExistentServer...

e nunca terminado, é claro. Mas a mesma pergunta por que não é adicionado o ........ ?

    
por derHugo 27.06.2017 / 18:33

1 resposta

2

O problema

O problema é que você definiu -w 0.2 . Quando o valor está abaixo de 1, os valores de prazo final ( -w ) e tempo limite ( -W ) são ignorados. Isso foi mencionado anteriormente em esta pergunta . Quando você usa -w 1 , seu script (que eu modifiquei ligeiramente para remover bits inúteis) funciona corretamente:

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

Solução

A solução óbvia é usar -w 1 . Se você pretende usar um valor menor que 1 segundo, o comando timeout deve ser melhor:

$ 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

Novamente, use-o com o operador ! no 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"
    
por Sergiy Kolodyazhnyy 27.06.2017 / 22:07