Como executar o comando ssh até obter êxito?

28

Às vezes, reinicio um dispositivo e preciso sshvoltar quando estiver pronto.

Eu quero executar o comando ssh a cada 5 segundos até que o comando seja bem-sucedido.

Minha primeira tentativa:

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

Como posso fazer isso?

Philip Kirkbride
fonte
Deseja uma sessão SSH interativa?
Ninguém
@Nobody yes I do
Philip Kirkbride
Ok, primeiro pensei que minha ideia não funcionaria interativamente, mas um pequeno teste mostrou que funciona, então escrevi uma resposta de qualquer maneira. :)
Ninguém

Respostas:

30

Outra opção seria usar until.

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

Se você fizer isso repetidamente para vários hosts, coloque-o em uma função no seu ~/.bashrc.

repeat()
{
read -p "Enter the hostname or IP of your server :" servername
until ssh $servername; do
    sleep 5
done
}
Hunter.S. Thompson
fonte
1
obrigado, eu vou usar o script de repetição, mas com $em vez do prompt de :-)
Philip Kirkbride
14
Vale ressaltar que sshpode sair com um status diferente de zero após a conexão bem-sucedida se algo externo à conexão terminar a sessão. Nesse caso, o script tentará se reconectar. Isso pode ou não ser um efeito colateral desejável.
Austin Hemmelgarn
17
ssh me@device.local
until !!; do sleep 5 ; done

O !!para repetir o último comando.

GAD3R
fonte
4
Uso criativo do histórico do shell! +1
David Foerster
15

O OpenSSH tem uma ConnectionAttemptsconfiguração que faz quase o que você deseja. O padrão é 1, mas você pode alterá-lo na ssh_configlinha de comando:

ssh -o 'ConnectionAttempts 10' ...

Infelizmente, você não pode ajustar o intervalo de tentativa fixado em 1 segundo, mas pode ajustar o tempo limite da tentativa de conexão ConnectTimeout(em segundos) da mesma maneira.

David Foerster
fonte
Isso não parece estar funcionando para mim: /
Freedo
@ Freedo: Você poderia explicar o que exatamente você tentou e o que exatamente não funcionou? Além disso, provavelmente seria melhor escrever uma nova pergunta sobre o seu problema. Você pode chamar minha atenção através de um link nos comentários.
David Foerster
14
while ! ssh user@host.example.com true; do
    sleep 5
done; echo "Host is back up at $(date)!"
DopeGhoti
fonte
2
Ou, se você realmente não quiser fazer login até que o serviço seja iniciado while ! nc -w5 -z host.example.com 22; do [...],.
DopeGhoti
4

autosshmantém sessões ssh vivas. Com os parâmetros corretos, você também pode iniciá-lo quando atualmente não for possível conectar-se e tentará até conseguir. Esta multa funciona, mas se você quiser o re parte de conexão para trabalho bem com sessões interativas que você precisa para combiná-lo com screenou equivalente.

Eu recomendo isso:

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

Mas veja sua página de manual para detalhes. Com os parâmetros acima, autosshtentará iniciar o ssh a cada AUTOSSH_POLLsegundo , fará AUTOSSH_GATETIME=0com que tente novamente se a primeira tentativa falhar (definitivamente o que você deseja), -M 0desativa a verificação de conexão por autossh, todas as opções posteriores são passadas para o ssh. As duas -oopções fazem com que o ssh saia se as conexões caírem por mais de 5s.

Ninguém
fonte
2

Correndo o risco de apenas jogar código em uma resposta, esse script funciona para mim diariamente. Eu chamo resshe pode ser usado da maneira mais simples ressh {hostname}, ou com cuidado,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
fonte