Wie führe ich den Befehl ssh aus, bis er erfolgreich war?

28

Manchmal starte ich ein Gerät neu und muss sshzurück, wenn es bereit ist.

Ich möchte den Befehl ssh alle 5 Sekunden ausführen, bis der Befehl erfolgreich ist.

Mein erster Versuch:

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

Wie kann ich das machen?

Philip Kirkbride
quelle
Möchten Sie eine interaktive SSH-Sitzung?
Niemand
@ Niemand ja, das tue ich
Philip Kirkbride
Ok, ich dachte zuerst, dass meine Idee nicht interaktiv funktionieren würde, aber ein kurzer Test zeigte, dass dies der Fall ist. Ich schrieb trotzdem eine Antwort. :)
Niemand

Antworten:

30

Eine andere Option wäre zu verwenden until.

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

Wenn Sie dies für eine Reihe von Hosts wiederholt ausführen, fügen Sie es in eine Funktion in Ihrer Datenbank ein ~/.bashrc.

repeat()
{
read -p "Enter the hostname or IP of your server :" servername
until ssh $servername; do
    sleep 5
done
}
Hunter.S.Thompson
quelle
1
Danke, ich werde das Wiederholungsskript verwenden, aber $anstelle der Eingabeaufforderung :-)
Philip Kirkbride
14
Es ist zu beachten, dass sshdas Skript nach einer erfolgreichen Verbindung mit einem Status ungleich Null beendet werden kann, wenn etwas außerhalb der Verbindung die Sitzung beendet. In diesem Fall versucht das Skript, die Verbindung wiederherzustellen. Dies kann eine wünschenswerte Nebenwirkung sein oder auch nicht.
Austin Hemmelgarn
17
ssh me@device.local
until !!; do sleep 5 ; done

Das !!, um den letzten Befehl zu wiederholen.

GAD3R
quelle
4
Kreative Nutzung der Shell-Geschichte! +1
David Foerster
15

OpenSSH hat eine ConnectionAttemptsEinstellung, die fast das macht, was Sie wollen. Der Standardwert ist 1, Sie können ihn jedoch in ssh_configoder über die Befehlszeile ändern :

ssh -o 'ConnectionAttempts 10' ...

Leider können Sie das Versuchsintervall, das auf 1 Sekunde festgelegt ist, nicht anpassen, aber Sie können das Zeitlimit für Verbindungsversuche ConnectTimeout(in Sekunden) auf dieselbe Weise anpassen .

David Foerster
quelle
Dies scheint nicht für mich zu arbeiten: /
Freedo
@Freedo: Kannst du bitte erklären, was genau du versucht hast und was genau nicht funktioniert hat? Außerdem ist es wahrscheinlich besser , eine neue Frage zu Ihrem Problem zu schreiben . Gerne können Sie mich durch einen Link in den Kommentaren darauf aufmerksam machen.
David Foerster
14
while ! ssh user@host.example.com true; do
    sleep 5
done; echo "Host is back up at $(date)!"
DopeGhoti
quelle
2
Oder, wenn Sie sich erst dann anmelden möchten, wenn der Dienst aktiv ist while ! nc -w5 -z host.example.com 22; do [...].
DopeGhoti
4

autosshhält ssh-Sessions am Leben Mit den richtigen Parametern können Sie es auch starten, wenn es derzeit nicht möglich ist, eine Verbindung herzustellen, und es wird versucht, bis es erfolgreich ist. Dies funktioniert gut, aber wenn Sie wollen , dass die wieder an der Arbeit gut mit interaktiven Sitzungen connect Teil Sie es mit kombinieren werden müssen screenoder gleichwertig.

Ich empfehle dies:

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

Weitere Informationen finden Sie auf der Manpage. Mit den oben genannten Parametern autosshwird versucht, ssh alle AUTOSSH_POLLSekunden zu starten. AUTOSSH_GATETIME=0Wenn der erste Versuch fehlschlägt (also definitiv, was Sie wollen), wird -M 0die Verbindungsprüfung durch Autossh deaktiviert. Alle späteren Optionen werden an ssh übergeben. Die beiden -oOptionen bewirken, dass ssh beendet wird, wenn die Verbindungen länger als 5 Sekunden unterbrochen werden.

Niemand
quelle
2

Da ich die Gefahr habe, nur Code auf eine Antwort zu werfen, funktioniert dieses Skript täglich für mich. Ich nenne es resshund es kann so einfach ressh {hostname}oder mit Sorgfalt verwendet werden,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
quelle