Bash ждать пинга успеха

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 выполняется только два раза, как один раз с ошибкой ping и один раз с успешной проверкой ping? Что мне нужно изменить, чтобы добавить больше точек в цикл while?

Я сделал тест также с несуществующим IP. Но это застряло с

waiting for NonExistentServer...

и никогда не прекращается, конечно. Но тот же вопрос, почему не ........добавили?

derHugo
источник
У меня отлично работает ...: /
Равексина

Ответы:

9

Проблема

Проблема в том, что вы установили -w 0.2. Когда значение меньше 1, значения deadline ( -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 пакет в секунду. Низкая пропускная способность, плохая связь, плохое оборудование между сервером и клиентом, проверяющим связь с сервером, вызовет выход из цикла и выдаст ложное положительное уведомление

  • Мы полагаемся на пинг, который использует эхо 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
Например, после того, как один сервер вернулся, ожидая других, я не хочу пинговать тот, который уже вернулся;)
derHugo
Я бы предложил написать это как функцию и запустить экземпляр каждой функции с IP-адресом в качестве аргумента в фоновом режиме. Но я бы рекомендовал не печатать точки, просто дайте каждой функции печатать сообщение при запуске сервера. Дайте мне знать, если вы хотите, чтобы я написал пример такой функции
Сергей Колодяжный
1
@ Джоан Да, это возможно. Я могу обновить свой ответ позже сегодня или завтра. Лично я бы не стал пинговать сервер постоянно, так как он немного спамит
Сергей Колодяжный,
1
@Joanne Смотрите мои обновления в ответе. Дайте мне знать, если это поможет или есть какие-то другие вопросы
Сергей Колодяжный