Sometimes I restart a device and need to ssh back in when it's ready.

I want to run the ssh command every 5 seconds until the command succeeds.

My first attempt:

watch -n5 ssh me@device.local && exit 1

How can I do this?

  • Do you want an interactive SSH session? – Nobody Nov 16 '17 at 20:48
  • @Nobody yes I do – Philip Kirkbride Nov 16 '17 at 20:49
  • Ok, I first thought my idea wouldn't work interactively, but a short test showed that it does so I wrote an answer anyway. :) – Nobody Nov 16 '17 at 21:11

Another option would be to use until.

until ssh me@device.local; do
    sleep 5

If you do this repeatedly for a number of hosts, put it in a function in your ~/.bashrc.

read -p "Enter the hostname or IP of your server :" servername
until ssh $servername; do
    sleep 5
| improve this answer | |
  • 1
    thanks, I'm going to use the repeat script but with $ instead of the prompt :-) – Philip Kirkbride Nov 15 '17 at 18:00
  • 15
    It is worth noting that ssh can exit with a non-zero status after having connected successfully if something external to the connection terminates the session, in which case that script will attempt to reconnect. This may or may not be a desirable side effect. – Austin Hemmelgarn Nov 15 '17 at 20:22
ssh me@device.local
until !!; do sleep 5 ; done

The !! to repeat the last command.

| improve this answer | |
  • 5
    Creative use of the shell history! +1 – David Foerster Nov 16 '17 at 11:30

OpenSSH has a ConnectionAttempts setting that does almost what you want. The default is 1 but you can change it in ssh_config or on the command-line:

ssh -o 'ConnectionAttempts 10' ...

Unfortunately you can't adjust the attempt interval which is fixed at 1 second, but you can adjust the connection attempt time-out ConnectTimeout (in seconds) in the same fashion.

| improve this answer | |
  • This doesn't seem to be working for me :/ – Freedo Aug 17 '19 at 10:57
  • @Freedo: Could you please explain what exactly you tried and what exactly didn't work? Also, it would likely be better to write a new question about your issue. You're welcome to draw my attention to it through a a link in the comments. – David Foerster Aug 18 '19 at 11:36
  • If it wasn't for the spurious (in my opinion) 5 second interval, this would be the correct answer. It certainly gets my upvote. A suggested addition to make the thing even more convenient, put this ... alias YH="ssh -o 'ConnectionAttempts 20' you@yourhost" ... in your ${HOME}/.profile. Then, after reboot, you'd just have to type YH on the command line, pour another coffee, take a sip ... and you're in. – Martin Bramwell Jul 21 at 16:23
while ! ssh user@host.example.com true; do
    sleep 5
done; echo "Host is back up at $(date)!"
| improve this answer | |
  • 2
    Or, if you don't want to actually log in until the service is up, while ! nc -w5 -z host.example.com 22; do [...]. – DopeGhoti Nov 15 '17 at 17:46

autossh keeps ssh sessions alive. With the right parameters you can also launch it when it's currently impossible to connect and it will try until it succeeds. This works fine, but if you want the reconnect part to work nicely with interactive sessions you'll need to combine it with screen or equivalent.

I recommend this:

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

But see its man page for details. With the above parameters, autossh will try launching ssh every AUTOSSH_POLL seconds, AUTOSSH_GATETIME=0 makes it try again if the first try fails (so definitely what you want), -M 0 disables connection checking by autossh, all later options are passed to ssh. The two -o options make ssh exit if the connections drops for more than 5s.

| improve this answer | |

At the risk of just throwing code at an answer, this script works for me on a daily basis. I call it ressh and it can be used as simply as ressh {hostname}, or with care, ressh -S {session_name} {hostname}

# Repeatedly attempt to reconnect to a remote ssh server
action=ssh              # How to connect remotely

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


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

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

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

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

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

# All done
exit 0
| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.