web-dev-qa-db-fra.com

Comment faire un ping sur Linux jusqu'à ce que l'hôte soit connu?

Comment puis-je cingler une certaine adresse et une fois trouvé, arrêtez de cingler.

Je veux l'utiliser dans un script bash, donc au démarrage de l'hôte, le script continue de cingler et à partir du moment où l'hôte est disponible, le script continue ...

50
Sander Versluys

Une nouvelle simplification de la réponse de Martynas:

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

notez que le ping lui-même est utilisé comme test de boucle; dès qu'il réussit, la boucle se termine. Le corps de la boucle est vide, avec la commande null ": "utilisé pour éviter une erreur de syntaxe.

Mise à jour: J'ai pensé à un moyen de faire en sorte que Control-C quitte la boucle ping proprement. Cela exécutera la boucle en arrière-plan, interceptera le signal d'interruption (Control-C) et tuera la boucle d'arrière-plan si elle se produit:

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"

C'est un peu détourné, mais si vous voulez que la boucle soit annulable, cela devrait faire l'affaire.

87
Gordon Davisson

Vous pouvez faire une boucle, envoyer un ping et selon le statut rompre la boucle, par exemple (bash):

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

Mettre cela quelque part dans votre script bloquera, jusqu'à ce que www.google.com est pingable.

25
Martynas Saint

Je sais que la question est ancienne ... et demande spécifiquement concernant ping, mais je voulais partager ma solution.

Je l'utilise lors du redémarrage des hôtes pour savoir quand je peux à nouveau les SSH. (Puisque ping répondra pendant plusieurs secondes avant que sshd ne démarre.)

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

Envoyez une requête ping à l'hôte cible une fois. Vérifiez si le ping a réussi (la valeur de retour de ping est zéro). Si l'hôte n'est pas vivant, exécutez à nouveau une commande ping.

Le code suivant peut être enregistré en tant que fichier et appelé avec le nom d'hôte comme argument, ou supprimé de la première et de la dernière ligne et utilisé comme fonction dans un script existant (nom d'hôte waitForHost).

Le code n'évalue pas la cause de l'échec si le ping n'aboutit pas à une réponse, bouclant ainsi indéfiniment si l'hôte n'existe pas. Ma page de manuel BSD répertorie la signification de chaque valeur de retour, contrairement à celle de Linux, donc je suppose que cela pourrait ne pas être portable, c'est pourquoi je l'ai laissé de côté.

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

Vous pouvez supprimer sleep 1, c'est seulement ici pour éviter tout problème d'inondation au cas où l'hôte serait accessible mais le ping ne sortirait pas avec le code 0.

9
radius

Veuillez voir les bonnes options sur stackoverflow . Voici un exemple en bash, vous devrez parcourir le code suivant jusqu'à ce qu'il retourne un résultat ping réussi.


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
Francois Wolmarans

n'importe laquelle des boucles ci-dessus peut également être utilisée avec fping plutôt qu'avec ping qui, IMO, est mieux adapté pour une utilisation dans les scripts que ping lui-même. Voir fping (1) pour plus de détails.

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

également utile pour tester si les machines sont en marche avant de faire quelque chose sur elles. Un exemple simple:

 pour h dans Host1 Host2 Host3; faire 
 si fping -q $ h; alors 
 echo -n "$ h:" 
 ssh $ h "uname -a" 
 fi 
 fait 
3
cas

Pour bien gérer le ping SIGINT sur 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"

en tant que fonction

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

Cela va essayer un certain nombre de fois.

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

Au lieu de faire écho à $r, vous pouvez le tester et agir en fonction de sa valeur:

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

Pour les utilisateurs de macOS, ping a l'option -o spécifiquement pour cela:

-o      Exit successfully after receiving one reply packet.

La commande est donc simple:

ping -o www.google.com

Il renvoie 0 lorsque l'hôte a été envoyé une fois avec succès.

1
Melebius

En général, je veux attendre que ma base de données ou un autre serveur apparaisse, mais je ne veux pas attendre trop longtemps. Le code suivant attend 10 secondes, puis définit le code de sortie si le serveur n'est pas apparu dans le délai imparti.

Si le serveur apparaît avant la limite de temps, la boucle sera court-circuitée afin que le bit de code suivant puisse s'exécuter.

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

J'utilise la fonction suivante. Je l'aime parce que je peux lui dire d'arrêter d'essayer après un certain temps:

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

Il peut être utilisé comme ceci pour lancer quelque chose:

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

Une autre amélioration de la réponse de Gordon Davisson:

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

avec le "$ ()" environnant, un sous-shell est démarré et vous pouvez donc utiliser Control-C pour terminer la boucle dans le cas où l'hôte ne deviendrait pas disponible.

0
Shawn