Jak mogę pingować określony adres, a gdy go znajdziesz, przestań pingować.
Chcę go używać w skrypcie bash, więc gdy host się uruchamia, skrypt kontynuuje pingowanie i od momentu, gdy host jest dostępny, skrypt kontynuuje ...
Jak mogę pingować określony adres, a gdy go znajdziesz, przestań pingować.
Chcę go używać w skrypcie bash, więc gdy host się uruchamia, skrypt kontynuuje pingowanie i od momentu, gdy host jest dostępny, skrypt kontynuuje ...
Odpowiedzi:
Dalsze uproszczenie odpowiedzi Martynas:
until ping -c1 www.google.com >/dev/null 2>&1; do :; done
zauważ, że sam ping jest używany jako test pętli; gdy tylko się powiedzie, pętla kończy się. Ciało pętli jest puste, a komenda „ :
” pusta służy do zapobiegania błędowi składni.
Aktualizacja: Pomyślałem o sposobie, aby Control-C opuścił pętlę ping w czysty sposób. Spowoduje to uruchomienie pętli w tle, zatrzymanie sygnału przerwania (Control-C) i zabicie pętli w tle, jeśli się pojawi:
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"
Jest trochę okrężny, ale jeśli chcesz, aby pętla mogła zostać anulowana, powinno wystarczyć.
ping
odczeka 10 sekund, zanim zrezygnuje z pingowania. Jeśli chcesz to skrócić do 1 sekundy, możesz użyć -w1
.
-W1
kill %1
go zabić.
Możesz zrobić pętlę, wysłać jeden ping i w zależności od stanu przerwać pętlę, na przykład (bash):
while true; do ping -c1 www.google.com > /dev/null && break; done
Umieszczenie tego gdzieś w skrypcie zablokuje, dopóki nie www.google.com
będzie możliwe pingowanie.
while true
i break
to rozwiązanie czystsze, IMO.
while true; do sleep 5; ping ...
Wiem, że pytanie jest stare ... i konkretnie dotyczy ping
, ale chciałem podzielić się moim rozwiązaniem.
Używam tego podczas ponownego uruchamiania hostów, aby wiedzieć, kiedy mogę ponownie włączyć SSH. (Ponieważ ping
będzie reagować przez kilka sekund przed sshd
uruchomieniem).
until nc -vzw 2 $host 22; do sleep 2; done
Wyślij ping do hosta docelowego jeden raz. Sprawdź, czy ping się powiódł (zwracana wartość ping wynosi zero). Jeśli host nie żyje, ping ponownie.
Poniższy kod może zostać zapisany jako plik i wywołany z nazwą hosta jako argumentem lub usunięty z pierwszego i ostatniego wiersza i użyty jako funkcja w istniejącym skrypcie (nazwa hosta waitForHost).
Kod nie ocenia przyczyny niepowodzenia, jeśli ping nie skutkuje odpowiedzią, a zatem zapętla się na zawsze, jeśli host nie istnieje. Moja strona podręczna BSD wymienia znaczenie każdej zwracanej wartości, podczas gdy linux nie, więc myślę, że to może nie być przenośne, dlatego ją pominąłem.
#!/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
Zobacz dobre opcje w Stackoverflow . Oto przykład w bash, będziesz musiał zapętlić następujący kod, aż zwróci pomyślny wynik 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
dowolna z powyższych pętli może być również używana z fping zamiast pingowania, co IMO lepiej nadaje się do użycia w skryptach niż pingowanie. Szczegóły w fping (1) .
while ! fping -q $HOSTNAMES ; do :; done
przydatne również do testowania, czy maszyny działają, zanim coś na nich zrobią. Prosty przykład:
dla godz. w HOST1 HOST2 HOST3; zrobić jeśli fping -q $ h; następnie echo -n "$ h:" ssh $ h „uname -a” fi gotowy
Spróbuje to podaną liczbę razy.
t=4; c=0; r=0; until ping -c 1 hostname.com >/dev/null 2>&1 || ((++c >= t)); do r=$?; done; echo $r
Zamiast echa $r
możesz go przetestować i działać zgodnie z jego wartością:
if ((r)); then echo 'Failed to contact host'; else echo 'Continuing with script'; fi
Aby ładnie obsługiwać SIGINT na 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"
jako funkcja
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
}
Korzystałem z następującej funkcji. Podoba mi się, ponieważ mogę powiedzieć, żeby przestał próbować po chwili:
#!/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
}
Można go użyć w ten sposób do uruchomienia czegoś:
# Start-up a web browser, if network is up
if [ $(networkup 60 www.google.com) -eq 0 ]; then
firefox &
fi
Zasadniczo chcę czekać na uruchomienie bazy danych lub innego serwera, ale nie chcę czekać zbyt długo. Poniższy kod czeka przez 10 sekund, a następnie ustawia kod wyjścia, jeśli serwer nie pojawi się w wyznaczonym terminie.
Jeśli serwer pojawi się przed upływem terminu, pętla ulegnie zwarciu, aby można było uruchomić kolejny bit kodu.
for i in `seq 1 10`; do date ; sleep 1 ; ping -c1 ${HOST} &>/dev/null && break ; done