sviluppo-web-qa.it

Come eseguire il ping in Linux fino a quando l'host non è noto?

Come posso eseguire il ping di un determinato indirizzo e, una volta trovato, interrompere il ping.

Voglio usarlo in uno script bash, quindi quando l'host si avvia, lo script continua a eseguire il ping e dal momento in cui l'host è disponibile, lo script continua ...

50
Sander Versluys

Un'ulteriore semplificazione della risposta di Martynas:

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

si noti che il ping stesso viene utilizzato come test di loop; non appena riesce, il ciclo termina. Il corpo del loop è vuoto, con il comando null ": "utilizzato per prevenire un errore di sintassi.

Aggiornamento: ho pensato a un modo per far sì che Control-C uscisse dal loop ping in modo pulito. Questo eseguirà il loop in background, intercetterà il segnale di interruzione (Control-C) e ucciderà il loop in background se si verifica:

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"

È un po 'tortuoso, ma se vuoi che il loop sia cancellabile dovrebbe fare il trucco.

87
Gordon Davisson

Puoi fare un loop, inviare un ping e, a seconda dello stato, interrompere il loop, ad esempio (bash):

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

Metterlo da qualche parte nel tuo script si bloccherà, finché www.google.com è pingabile.

25
Martynas Saint

So che la domanda è vecchia ... e in particolare chiede ping, ma volevo condividere la mia soluzione.

Lo uso quando riavvio gli host per sapere quando posso SSH di nuovo in loro. (Poiché ping risponderà per diversi secondi prima che sshd venga avviato.)

until nc -vzw 2 $Host 22; do sleep 2; done
22
Aaron Copley

Effettua il ping dell'host di destinazione una volta. Controlla se il ping è riuscito (il valore di ritorno del ping è zero). Se l'host non è attivo, eseguire nuovamente il ping.

Il seguente codice può essere salvato come file e chiamato con il nome host come argomento oppure rimosso dalla prima e dall'ultima riga e utilizzato come funzione all'interno di uno script esistente (waitForHost hostname).

Il codice non valuta la causa dell'errore se il ping non provoca una risposta, quindi esegue un ciclo continuo se l'host non esiste. La mia manpage BSD elenca il significato di ogni valore di ritorno, mentre quello di Linux no, quindi immagino che questo potrebbe non essere portatile, ecco perché l'ho lasciato fuori.

#!/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
11
Jan Jungnickel
UNREACHEABLE=1;
while [ $UNREACHEABLE -ne "0" ]; 
   do ping -q -c 1 Host &> /dev/null; UNREACHEABLE=$?; sleep 1;
done

Puoi rimuovere sleep 1, è qui solo per prevenire qualsiasi problema di allagamento nel caso in cui l'host fosse raggiungibile ma il ping non uscisse con il codice 0.

9
radius

Si prega di vedere buone opzioni a stackoverflow . Ecco un esempio in bash, dovrai scorrere il seguente codice fino a quando non restituisce un risultato ping riuscito.


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
4

uno qualsiasi dei loop di cui sopra può anche essere usato con fping piuttosto che con ping che, IMO, è più adatto per l'uso negli script rispetto al ping stesso. Vedi fping (1) per i dettagli.

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

utile anche per verificare se le macchine sono attive prima di fare qualcosa su di esse. Un semplice esempio:

 per h in Host1 Host2 Host3; fare 
 se fping -q $ h; quindi 
 echo -n "$ h:" 
 ssh $ h "uname -a" 
 fi 
 fatto 
3
cas

Per gestire bene il SIGINT sul ping 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"

come una funzione

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
}
1
Luke Exton

Questo proverà un determinato numero di volte.

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

Invece di fare eco $r, puoi testarlo e agire in base al suo valore:

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

Per gli utenti macOS, ping ha l'opzione -o appositamente per questo:

-o      Exit successfully after receiving one reply packet.

Quindi il comando è semplice:

ping -o www.google.com

Restituisce 0 quando l'host è stato eseguito correttamente il ping una volta.

1
Melebius

In generale, voglio aspettare che venga visualizzato il mio database o un altro server, ma non voglio aspettare troppo lungo. Il seguente codice attende per 10 secondi, quindi imposta il codice di uscita se il server non viene visualizzato entro il limite di tempo.

Se il server viene visualizzato prima del limite di tempo, il ciclo verrà cortocircuitato in modo che il prossimo bit di codice possa essere eseguito.

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

Sto usando la seguente funzione. Mi piace perché posso dire che smette di provare dopo un po ':

#!/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
}

Può essere usato in questo modo per lanciare qualcosa:

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

Un ulteriore miglioramento della risposta di Gordon Davisson:

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

con il '$ ()' circostante viene avviata una subshell e quindi è possibile utilizzare Control-C per terminare il ciclo nel caso in cui l'host non diventi disponibile.

0
Shawn