Bashはpingの成功を待ちます


10

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

だから私はサーバーごとに

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が失敗した場合とpingが成功した場合の2回しか実行されないのはなぜですか?whileループにドットを追加するには、何を変更する必要がありますか?

存在しないIPでもテストを行いました。しかしそれは行き詰まった

waiting for NonExistentServer...

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


私にとってはうまく
いき

回答:


9

問題

問題は、あなたが設定したことです-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"

もちろん、サーバーが稼働している場合にのみメッセージを表示し、サーバーがダウンしたときにレポートする場合には、その逆が適用できます。例:

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

ただし、これは完全ではないことに注意してください。

  • 毎秒1パケットでpingを実行しています。低帯域幅、接続不良、サーバーとクライアント間のpingハードウェアがサーバーにpingを実行すると、ループがトリガーされて終了し、誤検知が発生します。

  • ICMPエコーを使用するpingに依存しています。ファイアウォールまたは個々のサーバーでさえ、ping / ICMPエコーへの応答をブロックします。あなたは使用することができますncncat(の改良版ですnc)。上記のループのようなものは、次の代わりに正常に動作しますping

    nc -w5 -z 172.16.127.2 80

    これは、ポート80の172.16.127.2でサーバーに接続することです。I -z/ Oを回避するためです。接続して切断するだけです。-w失敗した接続を報告する前に5秒間待つことです。もちろん、これはサーバーを制御下に置いていて、ポート80が開いていることがわかっている場合には非常に便利です。UPDは問題なく使用できますが、ファイアウォールが設置されている場合は、おそらくTCPが推奨されます。

    ここに隠された利点は、特定のポート(ポート80のHTTPまたは554のRTSPなど)でサービスを実行している場合、ポートへの接続に失敗すると、サービスを再起動する必要があることを示すことがあります。

  • もちろん、少しスパム行為ncpingする可能性があります。より良い方法は、別の中央サーバーでサーバーにチェックインし、定期的に、おそらく1時間ごとにレポートを送信することです。そうすることで、サーバーが「パンチタイム」を逃した場合、エラーが発生する可能性があります。より良い方法は、Nagiosなどのサービスを使用することです。しかし、この時点で、複数のサーバーを使用したエンタープライズレベルのコンピューティングの領域に入っています。自宅にRaspberry Piのようなものがある場合、複雑なものはおそらく必要ありません。


こんにちは-w事をクリアしていただきありがとうございます!ループ状態で行うのとは異なる方法はありますか?1つのサーバーを待機するのに最適ですが、前述のように、後で複数のサーバーを待機しているのでwhile (( $ServerA_W==1 || $ServerB_W==1 || .....))、すべてのサーバーが戻ってきたときにも同じように動作します。
derHugo 2017年

たとえば、あるサーバーが他のサーバーを待って戻った後、すでに戻っているサーバーにpingを実行したくありません;)
derHugo

これを関数として記述し、バックグラウンドで引数としてIPアドレスを使用して各関数のインスタンスを起動することをお勧めします。しかし、ドットを印刷しないことをお勧めします。サーバーが起動したときに、各関数にメッセージを印刷させるだけです。そのような関数の例を書いてほしいかどうか教えてください
Sergiy Kolodyazhnyy 2017年

1
@Joanneはい、それは可能です。今日または明日、回答を更新できます。個人的には、少しスパム
行為

1
@Joanne回答で私の更新を参照してください。それが役に立ったかどうか、または他に質問がある場合は
お知らせください
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.