Bash, tunggu ping sukses

10

Saya menulis pada skrip yang me-reboot berbagai Server. Setelah reboot saya ingin "menunggu" sampai semua Server kembali online. (Untuk menjaga hal-hal sederhana yang saya definisikan untuk saya online = pingable)

Jadi untuk setiap Server saya lakukan

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

Apa yang saya harapkan (dan sukai) akan menjadi output seperti misalnya

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

di mana titik-titik .... akan muncul satu per satu.

Tetapi yang sebenarnya terjadi adalah pertama hanya ada

waiting for ServerXY ...

untuk sementara dan ketika Server kembali saya mendapatkan titik terakhir dan baris terakhir seperti

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

Mengapa loop sementara hanya dilakukan dua kali seperti sekali dengan ping gagal dan sekali dengan ping berhasil? Apa yang harus saya ubah untuk mendapatkan lebih banyak titik dalam loop sementara?

Saya melakukan tes juga dengan IP yang tidak ada. Tapi itu macet dengan

waiting for NonExistentServer...

dan tentu saja tidak pernah dihentikan. Tetapi pertanyaan yang sama mengapa tidak ........ditambahkan?

derHugo
sumber
Bekerja dengan baik untuk saya ...: /
Ravexina

Jawaban:

9

Masalah

Masalahnya adalah Anda telah mengatur -w 0.2. Ketika nilai di bawah 1, nilai batas waktu ( -w) dan batas waktu ( -W) diabaikan. Ini telah disebutkan sebelumnya dalam pertanyaan ini . Saat Anda menggunakan -w 1, skrip Anda (yang saya sedikit modifikasi untuk menghilangkan bit yang tidak berguna) berfungsi dengan baik:

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

Larutan

Solusi yang jelas adalah menggunakan -w 1. Jika Anda bermaksud menggunakan nilai yang lebih rendah dari 1 detik, timeoutperintahnya harus lebih baik:

$ 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

Sekali lagi, gunakan dengan !operator di 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"

Tentu saja yang sebaliknya dapat diterapkan untuk menampilkan pesan hanya jika server naik dan melaporkan ketika server turun, contoh:

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

Namun perlu dicatat, ini tidak sempurna:

  • kami melakukan ping hanya dengan 1 paket setiap detik. Bandwidth rendah, konektivitas buruk, perangkat keras buruk di antara server dan ping klien server akan memicu loop untuk keluar dan membuat pemberitahuan positif palsu

  • Kami mengandalkan ping, yaitu menggunakan gema ICMP. Firewall atau bahkan server individual memblokir respons terhadap gema ping / ICMP. Anda bisa menggunakan ncdari ncat(yang merupakan versi perbaikan dari nc). Sesuatu seperti pada loop di atas akan berfungsi dengan baik alih-alih ping:

    nc -w5 -z 172.16.127.2 80

    Apa yang dilakukan adalah terhubung ke server pada 172.16.127.2 pada port 80. -zadalah untuk menghindari I / O - cukup sambungkan dan lepaskan. -wadalah menunggu 5 detik sebelum melaporkan koneksi gagal. Tentu saja ini cukup bagus ketika Anda memiliki server di bawah kendali Anda dan Anda tahu port 80 terbuka. UPD dapat digunakan dengan baik, tetapi jika ada firewall, TCP mungkin lebih disukai.

    Manfaat tersembunyi di sini adalah bahwa jika Anda memiliki beberapa layanan berjalan pada port tertentu (seperti HTTP pada port 80 atau RTSP pada 554), gagal menyambung ke port dapat berfungsi sebagai indikator layanan Anda perlu restart.

  • Tentu saja, ncdan pingbisa sedikit spam. Cara yang lebih baik adalah melakukan check-in server dengan server pusat lain, mengirim laporan berkala, mungkin setiap jam; dengan cara itu jika server Anda melewatkan "waktu punch" Anda dapat menghasilkan kesalahan. Cara yang lebih baik adalah dengan menggunakan layanan seperti Nagios, yang melakukan itu. Tetapi pada titik ini kita memasuki ranah komputasi tingkat perusahaan dengan beberapa server. Jika Anda memiliki sesuatu seperti Raspberry Pi di rumah, Anda mungkin tidak perlu sesuatu yang rumit.

Sergiy Kolodyazhnyy
sumber
Hai, terima kasih banyak sudah membereskannya! Apakah ada cara yang berbeda dari melakukannya dalam kondisi loop? Ini sempurna untuk menunggu satu server tetapi seperti yang disebutkan saya menunggu beberapa server nanti saya akan melakukan sesuatu seperti while (( $ServerA_W==1 || $ServerB_W==1 || .....))yang berlaku ketika setiap server kembali.
derHugo
Setelah mis. Satu server kembali menunggu yang lain, saya tidak ingin melakukan ping yang sudah kembali;)
derHugo
Saya sarankan menulis itu sebagai fungsi dan meluncurkan instance dari setiap fungsi dengan alamat ip sebagai argumen di latar belakang. Tapi saya akan merekomendasikan untuk tidak mencetak titik-titik, biarkan setiap fungsi mencetak pesan ketika server muncul. Beri tahu saya jika Anda ingin saya menulis contoh fungsi tersebut
Sergiy Kolodyazhnyy
1
@ Joanne Ya, itu mungkin. Saya dapat memperbarui jawaban saya hari ini atau besok. Secara pribadi, saya tidak akan melakukan ping server terus menerus karena ini sedikit spam, meskipun
Sergiy Kolodyazhnyy
1
@ Joanne Lihat pembaruan saya dalam jawabannya. Biarkan saya tahu jika itu membantu atau jika ada pertanyaan lain
Sergiy Kolodyazhnyy