Comment exécuter la commande ssh jusqu'à ce qu'elle réussisse?

28

Parfois, je redémarre un appareil et j'ai besoin de sshrevenir quand il est prêt.

Je veux exécuter la commande ssh toutes les 5 secondes jusqu'à ce que la commande réussisse.

Ma première tentative:

watch -n5 ssh [email protected] && exit 1

Comment puis-je faire ceci?

Philip Kirkbride
la source
Voulez-vous une session SSH interactive?
Personne
@Personne, oui
Philip Kirkbride,
D'accord, j'ai d'abord pensé que mon idée ne fonctionnerait pas de manière interactive, mais un court test a montré que c'était le cas, j'ai quand même écrit une réponse. :)
Personne

Réponses:

30

Une autre option serait d'utiliser until.

until ssh me@device.local; do
    sleep 5
done

Si vous faites cela à plusieurs reprises pour un certain nombre d'hôtes, mettez-le dans une fonction de votre ~/.bashrc.

repeat()
{
read -p "Enter the hostname or IP of your server :" servername
until ssh $servername; do
    sleep 5
done
}
Hunter.S.Thompson
la source
1
merci, je vais utiliser le script de répétition mais avec $au lieu de l'invite :-)
Philip Kirkbride
14
Il convient de noter que vous sshpouvez quitter avec un état différent de zéro après vous être connecté avec succès si quelque chose d'extérieur à la connexion met fin à la session, auquel cas ce script tentera de se reconnecter. Cela peut ou non être un effet secondaire souhaitable.
Austin Hemmelgarn
17
ssh me@device.local
until !!; do sleep 5 ; done

Le !!pour répéter la dernière commande.

GAD3R
la source
4
Utilisation créative de l'histoire du shell! +1
David Foerster
15

OpenSSH a un ConnectionAttemptsparamètre qui fait presque ce que vous voulez. La valeur par défaut est 1 mais vous pouvez la modifier dans ssh_configou sur la ligne de commande:

ssh -o 'ConnectionAttempts 10' ...

Malheureusement, vous ne pouvez pas régler l'intervalle de tentative qui est fixé à 1 seconde, mais vous pouvez régler le délai d'expiration de la connexion ConnectTimeout(en secondes) de la même manière.

David Foerster
la source
Cela ne semble pas fonctionner pour moi: /
Freedo
@Freedo: Pourriez-vous s'il vous plaît expliquer exactement ce que vous avez essayé et ce qui n'a pas fonctionné exactement? En outre, il serait probablement préférable d' écrire une nouvelle question sur votre problème. Vous êtes invités à attirer mon attention sur elle via un lien dans les commentaires.
David Foerster
14
while ! ssh user@host.example.com true; do
    sleep 5
done; echo "Host is back up at $(date)!"
DopeGhoti
la source
2
Ou, si vous ne voulez pas vous connecter réellement jusqu'à ce que le service est en place, while ! nc -w5 -z host.example.com 22; do [...].
DopeGhoti
4

autosshmaintient les sessions ssh en vie. Avec les bons paramètres, vous pouvez également le lancer lorsqu'il est actuellement impossible de se connecter et il essaiera jusqu'à ce qu'il réussisse. Cela fonctionne bien, mais si vous voulez que la partie re connect fonctionne correctement avec les sessions interactives, vous devrez la combiner avec screenou équivalent.

Je recommande ceci:

AUTOSSH_POLL=5 AUTOSSH_GATETIME=0 autossh -M 0 -o ServerAliveInterval=5 -o ServerAliveCountMax=1 user@host

Mais consultez sa page de manuel pour plus de détails. Avec les paramètres ci-dessus, autosshessaiera de lancer ssh toutes les AUTOSSH_POLLsecondes, le AUTOSSH_GATETIME=0fera réessayer si le premier essai échoue (donc définitivement ce que vous voulez), -M 0désactive la vérification de connexion par autossh, toutes les options ultérieures sont passées à ssh. Les deux -ooptions font quitter ssh si les connexions chutent pendant plus de 5 secondes.

Personne
la source
2

Au risque de simplement lancer du code sur une réponse, ce script fonctionne pour moi au quotidien. Je l'appelle resshet il peut être utilisé aussi simplement ressh {hostname}ou avec précaution,ressh -S {session_name} {hostname}

#!/bin/bash
#
# Repeatedly attempt to reconnect to a remote ssh server
########################################################################
#
prefix="${0/*\/}"
port=
session=
action=ssh              # How to connect remotely

while getopts 'l:Lp:P:S:' OPT
do
    case "$OPT" in
        l)      [[ s == "$OPTARG" ]] && action=list ;;
        L)      action=list ;;
        [Pp])   port="$OPTARG" ;;
        S)      session="$OPTARG";; ## ; [[ $session =~ ^[0-9]+$ ]] && session="${prefix}-$session" ;;
    esac
done
shift $(($OPTIND - 1))

host="$1"
shift

if [[ -z "$host" ]]
then
    echo "ERROR: Missing hostname" >&2
    exit 1
fi


if [[ list == "$action" ]]
then
    ssh ${port:+-p $port} "$host" "screen -ls"
    exit 0
fi

# Connect repeatedly to the target host system
#
[[ -z "$session" ]] && session="${prefix}-$$.$host"

while :
do
    ssh -tt ${port:+-p $port} "$host" "screen -dr $session || screen -S $session $*"
    ss=$?
    [[ 0 -eq $ss ]] && break

    [[ 255 -eq $ss ]] && sleep 4
    sleep 1
    echo "Reconnecting to session $session on $host..."
done


# All done
#
exit 0
roaima
la source