Как я могу пинговать определенный адрес и, когда он найден, перестать пинговать.
Я хочу использовать его в сценарии 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"