Как пинговать в Linux, пока не будет известен хост?

Вопрос или проблема

Как я могу пинговать определенный адрес и, когда он будет найден, прекратить пинговать.

Я хочу использовать это в bash-скрипте, чтобы, когда хост запускается, скрипт продолжал пинговать, и в момент, когда хост становится доступным, скрипт продолжает…

Дальнейшее упрощение ответа Мартиняса:

до тех пор, пока ping -c1 www.google.com >/dev/null 2>&1; делать :; закончить

обратите внимание, что ping сам используется в качестве теста цикла; как только он удался, цикл заканчивается. Тело цикла пустое, с помощью команды “делать” используется, чтобы избежать синтаксической ошибки.

Обновление: Я придумал способ сделать так, чтобы Control-C корректно завершал цикл пинга. Это запустит цикл в фоновом режиме, поймает сигнал прерывания (Control-C) и убьет фоновый цикл, если он возникнет:

ping_cancelled=false    # Следим за тем, была ли отменена итерация или завершена успешно
пока ping -c1 "$1" >/dev/null 2>&1; делать :; закончить &    # "&" запускает его в фоновом режиме
trap "kill $!; ping_cancelled=true" SIGINT
wait $!          # Ждем, пока цикл завершится, одним способом или другим
trap - SIGINT    # Удалить ловушку, теперь мы с ней закончили
echo "Завершено пингование, отменено=$ping_cancelled"

Это немного запутано, но если вы хотите, чтобы цикл был отменяемым, это должно сработать.

Я знаю, что вопрос старый… и конкретно спрашивает о ping, но я хотел поделиться своим решением.

Я использую это при перезагрузке хостов, чтобы знать, когда я смогу снова войти в SSH. (Поскольку ping будет отвечать в течение нескольких секунд, прежде чем будет запущен sshd.)

до тех пор, пока nc -vzw 2 $host 22; делать спать 2; закончить

Вы можете сделать цикл, отправить один пинг и в зависимости от статуса прервать цикл, например (bash):

пока правда; делать ping -c1 www.google.com > /dev/null && прервать; закончить

Размещение этого где-то в вашем скрипте будет блокировать до тех пор, пока www.google.com не станет доступным для пинга.

Пинговать целевой хост один раз. Проверьте, удался ли пинг (возвратное значение пинга равно нулю). Если хост не доступен, пинговать снова.

Следующий код может быть сохранен в файл и вызван с именем хоста в качестве аргумента, или лишен первой и последней строки и использован как функция в существующем скрипте (waitForHost hostname).

Код не оценивает причину сбоя, если пинг не приводит к ответу, таким образом, зацикливаясь навсегда, если хост не существует. Моя страница man для BSD перечисляет значение каждого возвращаемого значения, в то время как для Linux этого не делает, так что я предполагаю, что это может не быть переносимым, поэтому я это опустил.

#!/bin/bash

PING=`which ping`

function waitForHost
{
    if [ -n "$1" ]; 
    then
        waitForHost1 $1;
    else
        echo "waitForHost: Ожидался аргумент имени хоста"
    fi
}

function waitForHost1
{
    reachable=0;
    пока [ $reachable -eq 0 ];
    do
    $PING -q -c 1 $1
    if [ "$?" -eq 0 ];
    then
        reachable=1
    fi
    done
    sleep 5
}
waitForHost $1

UNREACHEABLE=1;
пока [ $UNREACHEABLE -ne "0" ]; 
   делать ping -q -c 1 HOST &> /dev/null; UNREACHEABLE=$?; sleep 1;
закончить

Вы можете убрать sleep 1, он здесь только для предотвращения каких-либо проблем с затоплением в случае, если хост был бы доступен, но пинг не вышел с кодом 0.

Пожалуйста, смотрите хорошие варианты на stackoverflow. Вот пример на bash, вы должны зациклить следующий код, пока он не вернет успешный результат пинга.


ping -c 1 -t 1 192.168.1.1;
если [ $? -eq 0 ]; тогда
    echo "192.168.1.1 работает";
другой 
    echo "ip не работает";
fi

любой из вышеуказанных циклов также можно использовать с fping вместо ping, который, по моему мнению, лучше подходит для использования в скриптах, чем сам ping. См. fping(1) для деталей.

пока ! fping -q $HOSTNAMES ; делать :; закончить

также полезно для проверки, работают ли машины, прежде чем что-то с ними делать. Простой пример:

для h в HOST1 HOST2 HOST3 ; делать
  если fping -q $h ; тогда
     echo -n "$h : "
     ssh $h "uname -a"
  fi
закончить

Для пользователей macOS, ping имеет опцию -o, специально для этого:

-o      Успешно завершить после получения одного пакета ответа.

Так что команда проста:

ping -o www.google.com

Она возвращает 0, когда хост был успешно пингован один раз.

Это попытается несколько раз.

t=4; c=0; r=0; до тех пор, пока ping -c 1 hostname.com >/dev/null 2>&1 || ((++c >= t)); делать r=$?; закончить; echo $r

Вместо того чтобы выводить $r, вы можете протестировать это и действовать в зависимости от его значения:

если ((r)); тогда echo 'Не удалось связаться с хостом'; еще echo 'Продолжаем выполнение скрипта'; fi

В общем, я хочу дождаться запуска моей базы данных или другого сервера, но я не хочу ждать слишком долго. Следующий код ждет 10 секунд, а затем устанавливает код выхода, если сервер не появился в установленный срок.

Если сервер появится до срока, цикл будет сокращен, чтобы следующий фрагмент кода мог выполниться.

для i в `seq 1 10`; делать date ; sleep 1 ; ping -c1 ${HOST} &>/dev/null && break ; закончить

Для корректной обработки SIGINT на BSD ping.

HOST=google.com NO=1; пока [ $NO -не 0 ]; делать ping -W1 -c1 $HOST &>/dev/null; NO=$?;echo "$(date) ($HOST) $NO" ; закончить; echo "$(date) ($HOST) доступен"

в качестве функции

ping_until(){
  local NO=1
  пока [ $NO -не 0 ]; делать
    ping -W1 -c1 $1 &>/dev/null; NO=$?
    # Опционально блокировать затопление ICMP
    # sleep 1
    echo "$(date) ($1) ($NO)"
  закончить
}

Друзья, да, это старое. Здесь много хороших ответов.

Но я только что нашел то, что я называю красотой! На случай, если кому-то нравится нативный ping счетчик:

ping $HOST | sed "/ ms$/ q"

Разве это не fascinирующее? 🙂

[p@localhost ~]$ VBoxManage startvm VGTU-2021-LDVM1 --type headless && \
> ping 192.168.10.14 | sed "/ ms$/ q"
Ожидание, когда ВМ "VGTU-2021-LDVM1" включится...
ВМ "VGTU-2021-LDVM1" успешно запущена.
PING 192.168.10.14 (192.168.10.14) 56(84) байт данных.
От 192.168.10.8 icmp_seq=1 Недостижимость хоста назначения
От 192.168.10.8 icmp_seq=2 Недостижимость хоста назначения
  ...
От 192.168.10.8 icmp_seq=35 Недостижимость хоста назначения
От 192.168.10.8 icmp_seq=36 Недостижимость хоста назначения
64 байта от 192.168.10.14: icmp_seq=37 ttl=64 time=2003 ms

Я использовал следующую функцию. Мне она нравится, потому что я могу сказать ей, чтобы прекратила попытки через некоторое время:

#!/usr/bin/env bash

function networkup {
  # Инициализировать количество попыток
  reachable=$1
  пока [ $reachable -не 0 ]; делать
    # Пинговать указанный хост
    ping -q -c 1 -W 1 "$2" > /dev/null 2>&1
    # Проверка кода возврата
    если [ $? -eq 0 ]; тогда
      # Успех, мы можем выйти с правильным кодом возврата
      echo 0
      вернуться
    fi
    # Сеть не работает, уменьшаем счетчик и пробуем снова
    let reachable-=1
    # Спим одну секунду
    sleep 1
  закончить
  # Сеть не работает, количество попыток исчерпано, выходим
  echo 1
}

Это можно использовать следующим образом, чтобы запустить что-то:

# Запустите веб-браузер, если сеть работает
если [ $(networkup 60 www.google.com) -eq 0 ]; тогда
  firefox &
fi

Дальнейшее усовершенствование ответа Гордона Дэвисона:

до тех пор, пока $(ping -c1 www.google.com &>/dev/null); делать :; закончить

с окружающим ‘$()’ запускается подпроцесс, и поэтому вы можете использовать Control-C, чтобы завершить цикл в случае, если хост не станет доступным.

$ cat bin/check_host_up.sh
HOST=$1
PINGCMD="ping -c1 $HOST >/dev/null 2>&1"
пока правда; делать
    eval $PINGCMD && sleep 1 && echo -n . ||    \
    (                                           \
        echo && echo "(${HOST}) не работает:" $(date) &&         \
            до тех пор, пока eval $PINGCMD; делать :; закончить &&  \
        echo "(${HOST}) работает  :" $(date)
    );
закончить

ping $HOSTNAME | grep from -m 1

grep работает по строкам, так что:

ping google.com | grep "not"

Вот решение, которое не требует сборки оболочки скрипта:

watch -n 1 -g -- ping -W 1 -c 1 192.0.2.1

Каждую секунду watch будет запускать ping, который отправит один ICMP эхо-запрос на 192.0.2.1, откажется, если не получит ответа в течение одной секунды.

watch выйдет, когда вывод этой команды изменится, т.е. когда хост станет доступным.

Я взял ответ Гордон Дэвисон и упаковал решение в CLI-подобное приложение с использованием argc. Теперь можно также настроить тайм-аут. Наберите ./script.sh --help для справки.

#!/usr/bin/env bash

# Следующие @-аннотации принадлежат https://github.com/sigoden/argc
#
# @describe
# Ожидает, пока хост станет доступным, проверяя, отвечает ли он на ping
# сообщения. Разница с `ping -W` в том, что это не отправляет единственный
# запрос сети с долгим временем ожидания, а отправляет много запросов. Это
# особенно полезно, когда ждут, чтобы хосты снова онлайн, например
# при запуске ВМ или живой миграции ВМ на другой хост.
#
# @arg host!
# @option --timeout=60 Таймаут в секундах
# @option --request-delay=0.05 Задержка между запросами в секундах.

set -euo pipefail

# магия argc CLI
eval "$(argc --argc-eval "$0" "$@")" # Должен появиться после всех директив "@cmd"!

ping_cancelled=false
# секунды с момента UNIX эпохи
timestamp_begin=$(date +%s)

echo "Ожидание, пока хост станет доступным"
до тех пор, пока ping -c 1 -W 0.05 "$argc_host" >/dev/null 2>&1; делать
  DIFF=$(($(date +%s) - $timestamp_begin))
  если [ $DIFF -ge $argc_timeout ]; тогда
    echo "Таймаут!"
    exit 1
  fi
делать &    # "&" запускает его в фоновом режиме
trap "kill $!; ping_cancelled=true" SIGINT
wait $!          # Ждем, пока цикл завершится, одним способом или другим
trap - SIGINT    # Удалить ловушку, теперь мы с ней закончили
echo "Хост доступен"

Ответ или решение

Как отправить ping в Linux до тех пор, пока хост не станет доступен

Отправка команды ping в Linux — это распространенная задача, особенно когда необходимо удостовериться в доступности определенного хоста (например, сервера или устройства) перед выполнением последующих действий, таких как подключение по SSH или выполнение каких-либо операций. Вы можете автоматизировать этот процесс, используя скрипт на Bash.

Основная концепция

Для того чтобы проверять доступность хоста, нужно периодически отправлять ICMP-эхо запросы и проверять, был ли получен ответ. Как только ответ будет получен, вы можете прекратить выполнение скрипта или перейти к следующему шагу.

Простой вариант использования ping

Один из самых простых способов реализовать подобный функционал — использовать команду ping в цикле. Ниже приведен пример такого подхода:

#!/bin/bash

HOST=$1  # Хост передается как аргумент

until ping -c 1 "$HOST" &>/dev/null; do
    echo "Ожидание доступности хоста $HOST..."
    sleep 2  # Пауза между запросами
done

echo "Хост $HOST доступен."

В этом примере скрипт будет отправлять одно эха каждую секунду и выводить сообщение, пока хост не станет доступен.

Исполнение в фоновом режиме с обработкой сигнала

Если вы хотите, чтобы ваш скрипт можно было прервать (например, нажав Ctrl+C), вы можете расширить код, добавив обработку сигналов:

#!/bin/bash

HOST=$1  # Хост передается как аргумент

ping_cancelled=false

# Запускаем ping в фоновом режиме
until ping -c 1 "$HOST" &>/dev/null; do
    echo "Ожидание доступности хоста $HOST..."
    sleep 2
done &

# Обработка сигнала SIGINT (Ctrl+C)
trap "kill $!; ping_cancelled=true" SIGINT
wait $!          # Ожидаем завершения фонового процесса ping
trap - SIGINT    # Убираем обработчик сигнала

echo "Хост $HOST доступен. cancelled=$ping_cancelled"

В данном варианте скрипт будет работать в фоновом режиме и позволит завершить его, если это потребуется.

Использование nc для детекции доступности порта

Если вы хотите проверить не только доступность самого хоста, но и конкретного порта (например, для SSH), вы можете использовать утилиту nc (netcat):

#!/bin/bash

HOST=$1  # Хост передается как аргумент
PORT=22  # Порт SSH по умолчанию

until nc -z -v -w5 "$HOST" "$PORT"; do
    echo "Ожидание подключения к $HOST на порту $PORT..."
    sleep 2
done

echo "Порт $PORT на хосте $HOST доступен."

Этот метод также позволяет более точно проверять доступность сервиса на хосте.

Заключение

Использование скриптов для автоматизации проверки доступности хоста в Linux — это эффективный способ управления сетевыми ресурсами. Вы можете адаптировать предложенные решения в зависимости от ваших потребностей, добавляя дополнительные проверки или используя другие утилиты. Находите наиболее подходящий для вас подход, чтобы гарантировать, что ваши скрипты работают эффективно и без сбоев.

SEO-Оптимизация

  • Ключевое слово: ping в Linux
  • Метатег: "Узнайте, как отправлять ping в Linux, чтобы дождаться доступности хоста перед выполнением действий."
  • Заголовок: "Как использовать ping в Linux для проверки доступности хоста"

Эти элементы помогут улучшить видимость вашего контента в поисковых системах и привлечь целевую аудиторию.

Оцените материал
Добавить комментарий

Капча загружается...