Як пінг в linux, поки хост не буде відомий?


46

Як я можу ввести певну адресу і, коли її знайдуть, припиніть писати.

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

Відповіді:


84

Подальше спрощення відповіді Мартинаса:

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

зауважте, що сам ping використовується як цикл тестування; як тільки це вдається, петля закінчується. Тіло циклу порожнє, з нульовою командою " :" використовується для запобігання синтаксичної помилки.

Оновлення: я продумав спосіб змусити Control-C вийти з циклу ping чисто. Це запустить цикл у фоновому режимі, захопить сигнал переривання (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; зроблено
lepe

4
За замовчуванням pingзачекайте 10 секунд, перш ніж відмовитися від свого пінгу. Якщо ви хочете скоротити це до 1 секунди, можете скористатися -w1.
Джек О'Коннор

2
@ JackO'Connor Використовуючи BSD ping, це столиця-W1
Люк Екстон

Моя єдина проблема з цією відповіддю - це те, що вона не справляється з SIGINT добре. Ви не можете зупинити це з командного рядка, якщо він ніколи не збирається з'єднуватися з будь-якої причини.
Люк Екстон

@LukeExton Це пов’язано з способами обробки bash та ping SIGINT та способів їх взаємодії (див. Це питання ). У мене не дуже хороше рішення, але є клубок: використовуйте Control-Z, щоб зупинити скрипт, а потім kill %1вбити його.
Гордон Девіссон

25

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

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

Якщо розмістити це десь у вашому сценарії, він буде заблокований, поки www.google.comне з'явиться pingable.


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

Один раз відправте цільовий хост. Перевірте, чи ping вдався (повернене значення ping дорівнює нулю). Якщо хост не живий, знову пінг.

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

Код не оцінює причину відмови, якщо ping не призведе до відповіді, таким чином, назавжди циклічно, якщо хост не існує. Моя сторінка 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.


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

також корисно для тестування, якщо машини стоять, перш ніж робити щось на них. Простий приклад:

за год у HOST1 HOST2 HOST3; робити
  якщо fping -q $ h; тоді
     відлуння -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 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
}

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.