Как пинговать в linux, пока хост не известен?


46

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

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

Ответы:


84

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

until ping -c1 www.google.com >/dev/null 2>&1; do :; done

обратите внимание, что сам ping используется в качестве проверки цикла; как только это удастся, цикл заканчивается. Тело цикла пустое, с нулевой командой " :", используемой для предотвращения синтаксической ошибки.

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

ping_cancelled=false    # Keep track of whether the loop was cancelled, or succeeded
until ping -c1 "$1" >/dev/null 2>&1; do :; done &    # The "&" backgrounds it
trap "kill $!; ping_cancelled=true" SIGINT
wait $!          # Wait for the loop to exit, one way or another
trap - SIGINT    # Remove the trap, now we're done with it
echo "Done pinging, cancelled=$ping_cancelled"

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


6
Чтобы добавить «сон» (например, каждые 5 секунд): пока! ping -c1 www.google.com &> / dev / null; спать 5; сделано
— Лепе

4
По умолчанию pingбудет ждать 10 секунд, прежде чем отказаться от своего пинга. Если вы хотите уменьшить это до 1 секунды, вы можете использовать -w1.
— Джек О'Коннор

2
@ JackO'Connor Использование пинг BSD, это столица-W1
— Люк Экстон

Моя единственная проблема с этим ответом - он плохо обрабатывает SIGINT. Вы не можете остановить это из командной строки, если по какой-либо причине он никогда не подключится.
— Люк Экстон

@LukeExton Это связано с тем, как bash и ping обрабатывают SIGINT, и как они взаимодействуют (см. Этот вопрос ). У меня нет очень хорошего решения, но есть клочок: используйте Control-Z, чтобы остановить скрипт, а затем kill %1убить его.
— Гордон Дэвиссон

25

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

while true; do ping -c1 www.google.com > /dev/null && break; done

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


2
Это while trueи breakесть более чистое решение, ИМО.
— Дэн Карли

1
@DanCarley Я собираюсь не согласиться с вами по той причине, что в принятом ответе, нулевой версии команды, можно заменить сон / ожидание, чтобы дать вашему ЦП перерыв, и в этом случае я бы назвал это более чистым решением. Другая проблема, связанная с этим ответом, заключается в том, что он требует от читателя / пользователя понять, как работает &&, и как, если первая команда не сработает, она не будет вызвана. Это просто мнение, как и ваше собственное.
— Хамид

1
Основное различие, которое я вижу между этим решением и принятым, заключается в том, что оно будет отображать сообщение об ошибке «неизвестный хост ...» до тех пор, пока оно не будет найдено. Чтобы добавить сон (например, каждые 5 секунд):while true; do sleep 5; ping ...
— Лепе

20

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

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

until nc -vzw 2 $host 22; do sleep 2; done

2
Это именно то, что я искал, спасибо! Вы даже можете прервать вызов с помощью CTRL + C, чего нельзя сказать о некоторых других решениях в этом потоке.
— Алекс

1
Обратите внимание, что это работает для BSD-версий netcat. Версия nmap.org в дистрибутивах Linux реализована иначе, поэтому опция -z не существует, а опция -w ожидает подключения, но не закрывается при успешном завершении. Прекрасно работает в OSX, хотя.
— Пол

Вот почему вы не останавливаетесь на первом (хорошем) ответе. Это ответ на реальную проблему.
— Лев

11

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

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

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

#!/bin/bash

PING=`which ping`

function waitForHost
{
    if [ -n "$1" ]; 
    then
        waitForHost1 $1;
    else
        echo "waitForHost: Hostname argument expected"
    fi
}

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

9
UNREACHEABLE=1;
while [ $UNREACHEABLE -ne "0" ]; 
   do ping -q -c 1 HOST &> /dev/null; UNREACHEABLE=$?; sleep 1;
done

Вы можете удалить сон 1, это только здесь, чтобы предотвратить любую проблему с переполнением в случае, когда хост будет повторно подключен, но ping не будет выходить с кодом 0.


4

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


ping -c 1 -t 1 192.168.1.1;
if [ $? -eq 0 ]; then
    echo "192.168.1.1 is up";
else 
    echo "ip is down";
fi


3

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

while ! fping -q $HOSTNAMES ; do :; done

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

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

1

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

t=4; c=0; r=0; until ping -c 1 hostname.com >/dev/null 2>&1 || ((++c >= t)); do r=$?; done; echo $r

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

if ((r)); then echo 'Failed to contact host'; else echo 'Continuing with script'; fi

1

Чтобы приятно обрабатывать SIGINT на пинг BSD.

HOST=google.com NO=1; while [ $NO -ne 0 ]; do ping -W1 -c1 $HOST &>/dev/null; NO=$?;echo "$(date) ($HOST) $NO" ; done; echo "$(date) ($HOST) reachable"

как функция

ping_until(){
  local NO=1
  while [ $NO -ne 0 ]; do
    ping -W1 -c1 $1 &>/dev/null; NO=$?
    # Optionally block ICMP flooding
    # sleep 1
    echo "$(date) ($1) ($NO)"
  done
}

0

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

#!/usr/bin/env bash

function networkup {
  # Initialize number of attempts
  reachable=$1
  while [ $reachable -ne 0 ]; do
    # Ping supplied host
    ping -q -c 1 -W 1 "$2" > /dev/null 2>&1
    # Check return code
    if [ $? -eq 0 ]; then
      # Success, we can exit with the right return code
      echo 0
      return
    fi
    # Network down, decrement counter and try again
    let reachable-=1
    # Sleep for one second
    sleep 1
  done
  # Network down, number of attempts exhausted, quiting
  echo 1
}

Его можно использовать для запуска чего-либо:

# Start-up a web browser, if network is up
if [ $(networkup 60 www.google.com) -eq 0 ]; then
  firefox &
fi

0

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

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

for i in `seq 1 10`; do date ; sleep 1 ; ping -c1 ${HOST} &>/dev/null && break ; done

0

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

until $(ping -c1 www.google.com &>/dev/null); do :; done

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

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.