Bash chờ đợi một thành công ping


10

Tôi đang viết trên một kịch bản khởi động lại nhiều máy chủ khác nhau. Sau khi khởi động lại, tôi muốn "đợi" cho đến khi tất cả các Máy chủ hoạt động trở lại. (Để đơn giản, tôi đã xác định cho tôi trực tuyến = pingable)

Vì vậy, đối với mỗi máy chủ tôi làm

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

Những gì tôi mong đợi (và thích) sẽ là một đầu ra như vd

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

trong đó các chấm .... sẽ xuất hiện từng cái một.

Nhưng những gì thực sự xảy ra là đầu tiên chỉ có

waiting for ServerXY ...

Trong một thời gian và khi Máy chủ hoạt động trở lại, tôi nhận được dấu chấm cuối cùng và dòng cuối cùng như

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

Tại sao vòng lặp while chỉ được thực hiện hai lần như một lần với ping không thành công và một lần với ping thành công? Tôi phải thay đổi gì để có thêm nhiều dấu chấm được thêm vào trong vòng lặp while?

Tôi đã làm bài kiểm tra với một IP không tồn tại. Nhưng nó đã bị mắc kẹt với

waiting for NonExistentServer...

và không bao giờ chấm dứt tất nhiên. Nhưng cùng một câu hỏi tại sao không ........được thêm vào?


Hoạt động tốt với tôi ...: /
Ravexina

Câu trả lời:


9

Vấn đề

Vấn đề là bạn đã đặt ra -w 0.2. Khi giá trị dưới 1, giá trị thời hạn ( -w) và thời gian chờ ( -W) bị bỏ qua. Điều này đã được đề cập trước đây trong câu hỏi này . Khi bạn sử dụng -w 1, tập lệnh của bạn (mà tôi đã sửa đổi một chút để loại bỏ các bit vô dụng) hoạt động chính xác:

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

Giải pháp

Giải pháp rõ ràng là sử dụng -w 1. Nếu bạn có ý định sử dụng giá trị thấp hơn 1 giây, timeoutlệnh sẽ tốt hơn:

$ 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

Một lần nữa, sử dụng nó với !toán tử trong vòng lặp:

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

Tất nhiên, điều ngược lại có thể được áp dụng để hiển thị thông báo chỉ khi máy chủ hoạt động và báo cáo khi máy chủ ngừng hoạt động, ví dụ:

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

Lưu ý, tuy nhiên, điều này không hoàn hảo:

  • chúng tôi đang ping chỉ với 1 gói mỗi giây. Băng thông thấp, kết nối kém, phần cứng kém ở giữa máy chủ và máy khách ping máy chủ sẽ kích hoạt vòng lặp để thoát và đưa ra thông báo dương tính giả

  • Chúng tôi đang dựa vào ping, đó là sử dụng ICMP echo. Tường lửa hoặc thậm chí các máy chủ riêng lẻ chặn phản hồi với tiếng vang ping / ICMP. Bạn có thể sử dụng nccác ncat(đó là một phiên bản cải tiến của nc). Một cái gì đó giống như trong vòng lặp ở trên sẽ hoạt động tốt thay vì ping:

    nc -w5 -z 172.16.127.2 80

    Những gì nó làm là kết nối với máy chủ trên 172.16.127.2 trên cổng 80. -zlà để tránh I / O - chỉ cần kết nối và ngắt kết nối. -wlà đợi trong 5 giây trước khi báo cáo kết nối không thành công. Tất nhiên điều này khá tốt khi bạn có máy chủ dưới sự kiểm soát của mình và bạn biết cổng 80 đang mở. CẬP NHẬT có thể được sử dụng tốt, nhưng nếu có tường lửa, TCP có thể được ưu tiên.

    Một lợi ích tiềm ẩn ở đây là nếu bạn có một số dịch vụ chạy trên cổng cụ thể (chẳng hạn như HTTP trên cổng 80 hoặc RTSP trên 554), việc không kết nối với cổng có thể đóng vai trò là chỉ báo dịch vụ của bạn cần khởi động lại.

  • Tất nhiên, ncpingcó thể là một chút spam. Cách tốt hơn là để máy chủ đăng ký với một máy chủ trung tâm khác, gửi báo cáo định kỳ, có thể mỗi giờ; theo cách đó nếu máy chủ của bạn bỏ lỡ "thời gian đột xuất", bạn có thể tạo ra lỗi. Cách tốt hơn là sử dụng một dịch vụ như Nagios, thực hiện điều đó. Nhưng tại thời điểm này, chúng ta đang đi vào lĩnh vực điện toán cấp doanh nghiệp với nhiều máy chủ. Nếu bạn có thứ gì đó như Raspberry Pi ở nhà, có lẽ bạn không cần bất cứ thứ gì phức tạp.


Hi cảm ơn bạn rất nhiều vì đã xóa điều đó -w! Có cách nào khác với làm trong điều kiện vòng lặp không? Thật hoàn hảo để chờ đợi một máy chủ nhưng như đã đề cập Tôi đang đợi nhiều máy chủ sau này Tôi sẽ làm một cái gì đó giống như while (( $ServerA_W==1 || $ServerB_W==1 || .....))giữ khi mọi máy chủ hoạt động trở lại.
derHugo

Sau khi một máy chủ quay lại chờ những máy chủ khác tôi không muốn ping máy chủ đã hoạt động trở lại;)
derHugo

Tôi khuyên bạn nên viết rằng dưới dạng hàm và khởi chạy thể hiện của từng hàm với địa chỉ ip làm đối số trong nền. Nhưng tôi khuyên bạn không nên in dấu chấm, chỉ để mỗi chức năng in thông báo khi máy chủ xuất hiện. Hãy cho tôi biết nếu bạn muốn tôi viết một ví dụ về chức năng như vậy
Sergiy Kolodyazhnyy

1
@Joanne Vâng, nó có thể. Tôi có thể cập nhật câu trả lời của tôi sau hôm nay hoặc ngày mai. Cá nhân, tôi sẽ không ping máy chủ liên tục vì nó hơi spam, mặc dù vậy
Sergiy Kolodyazhnyy

1
@Joanne Xem cập nhật của tôi trong câu trả lời. Hãy cho tôi biết nếu điều đó có ích hay nếu có bất kỳ câu hỏi nào khác
Sergiy Kolodyazhnyy
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.