Назад | Перейти на главную страницу

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

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

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

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

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"

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

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

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

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

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

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

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

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

Следующий код можно сохранить как файл и вызвать с именем хоста в качестве аргумента или удалить первую и последнюю строку и использовать в качестве функции в существующем скрипте (имя хоста 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
UNREACHEABLE=1;
while [ $UNREACHEABLE -ne "0" ]; 
   do ping -q -c 1 HOST &> /dev/null; UNREACHEABLE=$?; sleep 1;
done

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

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


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

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

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

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

for h in HOST1 HOST2 HOST3 ; do
  if fping -q $h ; then
     echo -n "$h : "
     ssh $h "uname -a"
  fi
done

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

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

Чтобы правильно обрабатывать SIGINT на BSD ping.

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
}

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

-o      Exit successfully after receiving one reply packet.

Итак, команда проста:

ping -o www.google.com

Он возвращает 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

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

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

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

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

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

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

$ cat bin/check_host_up.sh
HOST=$1
PINGCMD="ping -c1 $HOST >/dev/null 2>&1"
while true; do
    eval $PINGCMD && sleep 1 && echo -n . ||    \
    (                                           \
        echo && echo "(${HOST}) down:" $(date) &&         \
            until eval $PINGCMD; do :; done &&  \
        echo "(${HOST}) up  :" $(date)
    );
done

ping $ HOSTNAME | grep from -m 1

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

ping google.com | grep "not"