web-dev-qa-db-fra.com

Commande Linux d'attendre qu'un serveur SSH soit en place

J'ai un script qui crée une machine virtuelle et me donne une adresse IP. Ensuite, je voudrais faire quelque chose comme ça:

waitforssh 192.168.2.38 && ssh 192.168.2.38

Et cela attendra que la machine soit en place et SSH réagisse, puis SSH dessus.

Waitforsh est la commande que j'ai besoin de trouver.

Nmap, Netcat, fing ou ping ferait-il le travail? J'ai essayé Netcat mais cela abandonne seulement quelques secondes si l'hôte est inaccessible.

Il doit gérer le fait que la machine elle-même démarre et peut prendre un certain temps pour répondre aux paquets réseau.

8
Weboide

Je n'ai pas d'hôte que je peux ssh et contrôler s'il s'agissait ou non, mais cela devrait fonctionner:

while ! ssh <ip>
do
    echo "Trying again..."
done

Ou un script shell qui est plus explicite:

#!/bin/sh

ssh $1
while test $? -gt 0
do
   sleep 5 # highly recommended - if it's in your local network, it can try an awful lot pretty quick...
   echo "Trying again..."
   ssh $1
done

Enregistrez-le comme (disons) waitforssh.sh Et puis appelez-le avec sh waitforssh.sh 192.168.2.38

11
Jon

Eh bien, je ne suis pas sûr de ce que vous entendez par être up, mais qu'en est-il:

$ ping Host.com | grep --line-buffered "bytes from" | head -1 && ssh Host.com

Première commande ping | ... | head -1 attend que le serveur a envoyé une réponse ping unique et existe. Puis ssh entre en jeu. Sachez que grep peut la sortie tampon, de sorte que c'est ce que --line-buffered est pour.

Vous pouvez envelopper cette commande avec la fonction Bash pour l'utiliser exactement comme vous l'avez décrit.

$ waitfor() { ping $1 | grep --line-buffered "bytes from" | head -1 }
$ waitfor server.com && ssh server.com
1
Denis Bazhenov

Ceci est un script 'ping_ssh' que j'utilise. Il gère les cas de délai d'expiration, le succès rapide et ne pas demander des mots de passe ou ne sera pas conçu par le port étant ouvert mais ne répondant pas comme avec les solutions basées sur les "NC". Cela combine plusieurs réponses trouvées sur divers sites liés à Stackoverflow.

#!/usr/bin/bash
Host=$1
PORT=$2
#Host="localhost"
#PORT=8022
if [ -z "$1" ]
  then
    echo "Missing argument for Host."
    exit 1 
fi

if [ -z "$2" ]
  then
    echo "Missing argument for port."
    exit 1 
fi
echo "polling to see that Host is up and ready"
RESULT=1 # 0 upon success
TIMEOUT=30 # number of iterations (5 minutes?)
while :; do 
    echo "waiting for server ping ..."
    # https://serverfault.com/questions/152795/linux-command-to-wait-for-a-ssh-server-to-be-up
    # https://unix.stackexchange.com/questions/6809/how-can-i-check-that-a-remote-computer-is-online-for-ssh-script-access
    # https://stackoverflow.com/questions/1405324/how-to-create-a-bash-script-to-check-the-ssh-connection
    status=$(ssh -o BatchMode=yes -o ConnectTimeout=5 ${Host} -p ${PORT} echo ok 2>&1)
    RESULT=$?
    if [ $RESULT -eq 0 ]; then
        # this is not really expected unless a key lets you log in
        echo "connected ok"
        break
    fi
    if [ $RESULT -eq 255 ]; then
        # connection refused also gets you here
        if [[ $status == *"Permission denied"* ]] ; then
            # permission denied indicates the ssh link is okay
            echo "server response found"
            break
        fi
    fi
    TIMEOUT=$((TIMEOUT-1))
    if [ $TIMEOUT -eq 0 ]; then
        echo "timed out"
        # error for jenkins to see
        exit 1 
    fi
    sleep 10
done
1
poleguy

La commande SSH peut recevoir une commande à effectuer sur la machine distante comme dernier paramètre. Alors appelez ssh $MACHINE echo dans une boucle. Sur le succès, il retourne 0 en $ ?, à l'échec 255. Vous devez bien sûr utiliser l'authentification sans mots-mots avec des certificats.

1
danatel