Баш чекати успіху пінгу


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!

де крапки .... з'являться одна за одною.

Але те, що насправді відбувається, спочатку є лише

waiting for ServerXY ...

на деякий час, і коли Сервер повертається, я отримую останню крапку і останній рядок, як

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

Чому цикл while виконується лише двічі, як один раз, коли не працює пінг, а один раз успішно пінг? Що потрібно змінити, щоб отримати більше точок у циклі while?

Я робив тест також з неіснуючим IP-адресою. Але воно застрягло

waiting for NonExistentServer...

і ніколи не припиняється, звичайно. Але те саме питання, чому не ........додають?


Для мене прекрасно працює ...: /
Ravexina

Відповіді:


9

Питання

Проблема в тому, що ви встановили -w 0.2. Якщо значення нижче 1, значення rok ( -w) та timeout ( -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 пакетом щосекунди. Низька пропускна здатність, погана підключеність, погане обладнання між сервером та клієнтом, що здійснює пінг-сервер, спровокують цикл для виходу з нього та подадуть помилкове позитивне сповіщення

  • Ми покладаємось на pinging, що використовує відлуння ICMP. Брандмауери або навіть окремі сервери блокують відповіді на відлуння ping / ICMP. Ви можете використовувати ncз ncat(який є покращеною версією nc). Щось на зразок циклу вище буде добре працювати замість ping:

    nc -w5 -z 172.16.127.2 80

    Для цього потрібно підключитись до сервера 172.16.127.2 на порту 80. -zУникати вводу-виводу - просто підключитися та відключитися. -w- чекати 5 секунд, перш ніж повідомити про невдале з'єднання. Звичайно, це дуже добре, коли у вас під контролем є сервер, і ви знаєте, що порт 80 відкритий. UPD можна використовувати чудово, але якщо на місці встановлений брандмауер, TCP, ймовірно, є кращим.

    Тут прихована перевага полягає в тому, що якщо у вас є якась служба, що працює на певному порту (наприклад, HTTP на порт 80 або RTSP на 554), невдача підключення до порту може послужити індикатором, що ваша служба потребує перезавантаження.

  • Звичайно, ncі pingможе бути трохи спамом. Кращим способом було б мати реєстрацію сервера на іншому центральному сервері, надсилати періодичний звіт, можливо, щогодини; таким чином, якщо ваш сервер не вистачає "часу пробивання", ви можете генерувати помилки. Кращим способом є використання такої послуги, як Nagios, яка робить це. Але в цей момент ми потрапляємо у сферу обчислень на рівні підприємства з декількома серверами. Якщо у вас є щось на кшталт Raspberry Pi вдома, вам, мабуть, не потрібно нічого складного.


Привіт, велике дякую за очищення цієї речі! Чи є інший спосіб, ніж це робити в умовах циклу? Це ідеально підходить для очікування одного сервера, але, як згадувалося, я чекаю пізніше декількох серверів, я зроблю щось на кшталт, while (( $ServerA_W==1 || $ServerB_W==1 || .....))що тримається, коли кожен сервер повертається.
derHugo

Наприклад, наприклад, один сервер знову чекає інших, я не хочу
надіслати

Я б запропонував написати це як функцію та запустити екземпляр кожної функції з ip адресою як аргументом у фоновому режимі. Але я б рекомендував не друкувати крапки, просто дозвольте друкувати кожне повідомлення функції, коли з'являється сервер. Повідомте мене, якщо ви хочете, щоб я написав приклад такої функції
Сергій Колодяжний,

1
@Joanne Так, це можливо. Я можу оновити свою відповідь пізніше сьогодні або завтра. Особисто я не став би пінг-сервер постійно, оскільки це трохи спам
Сергій Колодяжний

1
@Joanne Дивіться мої оновлення у відповіді. Повідомте мене, чи це допомагає чи є якісь інші запитання
Сергій Колодяжний
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.