web-dev-qa-db-ja.com

Bashはpingの成功を待つ

さまざまなサーバーを再起動するスクリプトを書いています。再起動後、すべてのサーバーがオンラインに戻るまで「待機」します。 (物事を単純にするために、私はオンライン= ping可能と定義しました)

サーバーごとに

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

私が期待する(そして好きな)ものは、例えば.

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

ここで、ドットは1つずつ表示されます。

しかし、実際に起こることは最初にあるだけです

waiting for ServerXY ...

しばらくの間、サーバーが戻ったら、最後のドットと最後の行を取得します

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

Whileループは、pingが失敗して1回、pingが成功して1回のように2回しか実行されないのはなぜですか? whileループでさらにドットを追加するには、何を変更する必要がありますか?

存在しないIPでもテストを行いました。しかし、それは動けなくなった

waiting for NonExistentServer...

もちろん終了しません。しかし、なぜ........が追加されないのですか?

8
derHugo

問題

問題は、-w 0.2を設定したことです。値が1未満の場合、期限(-w)およびタイムアウト(-W)の値は無視されます。これは、以前に この質問 で言及されています。 -w 1を使用すると、スクリプト(役に立たないビットを削除するために少し変更しました)が正常に機能します。

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

解決

明らかな解決策は、-w 1を使用することです。 1秒未満の値を使用する場合は、timeoutコマンドの方が優れているはずです。

$ 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

繰り返しになりますが、ループで!演算子を使用してください:

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