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 [email protected] && exit 1
How can I do this?
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 [email protected] && exit 1
How can I do this?
Another option would be to use until.
until ssh [email protected]; do
sleep 5
done
If you do this repeatedly for a number of hosts, put it in a function in your ~/.bashrc.
repeat()
{
read -p "Enter the hostname or IP of your server :" servername
until ssh $servername; do
sleep 5
done
}
$ instead of the prompt :-)
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.
ssh [email protected]
until !!; do sleep 5 ; done
The !! to repeat the last command.
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.
sshr() { ssh $1 -o "ConnectionAttempts 10" } so I can do this sshr destination
sshr() { ssh -o "ConnectionAttempts 10" $@ } so you can pass multiple arguments.
while ! ssh [email protected] true; do
sleep 5
done; echo "Host is back up at $(date)!"
while ! nc -w5 -z host.example.com 22; do [...].
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.
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}
#!/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
This is how I do it within a command for Shuttle App for Mac. Similar to David's answer. This command connects to and reboots the server and then tries to reconnect to it again until it succeeds.
{
"name": "Server - REBOOT",
"cmd": "ssh -t [email protected] 'reboot -p' ; sleep 1 ; echo 'Reconnecting. Standby...' ; sleep 2 ; ssh -o 'ConnectionAttempts 10' [email protected]"
},