263

I'm executing a script connecting via password-less SSH on a remote host. I want to set a timeout, so that if the remote host is taking an infinite time to run, I want to come out of that ssh session and continue other lines in my sh script.

How can I set a timeout?

Rob Bednark
  • 25,981
  • 23
  • 80
  • 125
user57421
  • 7,091
  • 7
  • 25
  • 22
  • This should probably be closed to be in line with the closing of a complete duplicate of this [how to decrease ssh connection timeout value \[closed\]](https://stackoverflow.com/questions/18389367/how-to-decrease-ssh-connection-timeout-value) – Murmel Jan 15 '18 at 22:01
  • 1
    If you redirected here only to *"stay more time in your `ssh` session"* (question "How to increase SSH Connection timeout?"), this is the **wrong place**. The answer is at [this link about ssh-timeout](https://bjornjohansen.no/ssh-timeout). – Peter Krauss Feb 14 '18 at 10:04

8 Answers8

418
ssh -o ConnectTimeout=10  <hostName>

Where 10 is time in seconds. This Timeout applies only to the creation of the connection.

Eric Leschinski
  • 146,994
  • 96
  • 417
  • 335
user57421
  • 7,091
  • 7
  • 25
  • 22
  • 7
    ConnectTimeout only sets a timeout on the connection setup, right? – Mmmh mmh Sep 12 '14 at 14:23
  • 24
    This doesn't actually work for "the remote host is taking an infinite time to run": "ssh -o ConnectTimeout=5 host 'sleep 10'" waits for 10 seconds, not 5. – Ferry Boender Oct 11 '16 at 18:37
  • 4
    @FerryBoender It seems obvious that `ConnectTimeout` affects only the connection. Your example connects with success. – laconbass Jan 31 '23 at 13:53
119

Use the -o ConnectTimeout and -o BatchMode=yes -o StrictHostKeyChecking=no .

ConnectTimeout keeps the script from hanging, BatchMode keeps it from hanging with Host unknown, YES to add to known_hosts, and StrictHostKeyChecking adds the fingerprint automatically.

**** NOTE **** The "StrictHostKeyChecking" was only intended for internal networks where you trust you hosts. Depending on the version of the SSH client, the "Are you sure you want to add your fingerprint" can cause the client to hang indefinitely (mainly old versions running on AIX). Most modern versions do not suffer from this issue. If you have to deal with fingerprints with multiple hosts, I recommend maintaining the known_hosts file with some sort of configuration management tool like puppet/ansible/chef/salt/etc.

Doug
  • 3,472
  • 3
  • 21
  • 18
  • 25
    Not only does `-o StrictHostKeyChecking=no` not address the question, but it's a terrible idea if you care about security, which might be the reason you're using SSH in the first place. – Dolph Oct 21 '15 at 14:42
  • 10
    It is good to point out the possible security implications of -o StrictHostKeyChecking=no. However, it will prevent the script from hanging during execution. – Doug Oct 22 '15 at 00:48
  • 2
    WARNING!!!! As @Dolph wrote, do NOT use `StrictHostKeyChecking=no` if you care about security at all. @Doug: script will not hang - it will just insist that you ssh to remote host manually the first time, so it gets to know the host. But it will protect you against MITM attacks. Please edit this answer to reflect this as it is a very dangerous advice as it stands. And it wasn't even asked for. – johndodo Feb 18 '16 at 12:10
  • 2
    Updated my answer. From my experience, it can cause some clients to hang. – Doug Feb 21 '16 at 15:40
  • Use `-o StrictHostKeyChecking=accept-new` if you really must. As per [this answer](https://stackoverflow.com/questions/21383806/how-can-i-force-ssh-to-accept-a-new-host-fingerprint-from-the-command-line) – Steven de Salas Mar 21 '23 at 14:20
72

try this:

timeout 5 ssh user@ip

timeout executes the ssh command (with args) and sends a SIGTERM if ssh doesn't return after 5 second. for more details about timeout, read this document: http://man7.org/linux/man-pages/man1/timeout.1.html

or you can use the param of ssh:

ssh -o ConnectTimeout=3 user@ip
Lee HoYo
  • 1,217
  • 9
  • 9
  • 6
    If you're looking for this command on a Mac, try `brew install coreutils` and then use `gtimeout` (source: http://stackoverflow.com/questions/3504945/timeout-command-on-mac-os-x ). – larcher Jul 07 '16 at 20:16
  • 5
    This may not do what you want. Consider the command `timeout 3s ssh user@server 'sleep 5; echo blarg >> /tmp/blarg'` This kills the process on the SSH client side, but /tmp/blarg still gets modified on the remote server. This means that if you are running a runaway CPU-intensive job on the remote server, you will leak processes. – James Davis Feb 05 '18 at 15:08
  • 1
    @JamieDavis what about ssh user@server 'timeout 5s sleep 10' ? – FilipR Dec 06 '18 at 22:04
  • @FilipR this doesn't time out if the connection is never made ;) – xeruf Oct 13 '20 at 08:49
  • "this ... or this" should normally raise the question "why not both?" A combination of both is what I use in my own scripting. The threshold for `timeout $X` should be larger than the that for `ssh -o ConnectTimeout=$Y` (i.e. `X > Y`), naturally. This catches the situation where the remote machine is hanging after the connection is successfully made and you never get to your next machine in the queue. – Rich Oct 27 '20 at 22:17
28

You could also connect with flag

-o ServerAliveInterval=<secs>
so the SSH client will send a null packet to the server each <secs> seconds, just to keep the connection alive. In Linux this could be also set globally in /etc/ssh/ssh_config or per-user in ~/.ssh/config.
javabrett
  • 7,020
  • 4
  • 51
  • 73
Patrizio Bertoni
  • 2,582
  • 31
  • 43
3

If all else fails (including not having the timeout command) the concept in this shell script will work:

 #!/bin/bash
 set -u
 ssh $1 "sleep 10 ; uptime" > /tmp/outputfile 2>&1 & PIDssh=$!
 Count=0
 while test $Count -lt 5 && ps -p $PIDssh > /dev/null
 do
    echo -n .
    sleep 1
    Count=$((Count+1))
 done
 echo ""

 if ps -p $PIDssh > /dev/null
 then
    echo "ssh still running, killing it"
    kill -HUP $PIDssh
 else
    echo "Exited"
 fi
Philip Kearns
  • 377
  • 4
  • 14
1

just adding the following .ssh/config snippet that I use,

  ServerAliveInterval 20
  ServerAliveCountMax 5
  ConnectTimeout 10
Danie
  • 386
  • 3
  • 8
0

Well, you could use nohup to run whatever you are running on 'non-blocking mode'. So you can just keep checking if whatever it was supposed to run, ran, otherwise exit.

nohup ./my-script-that-may-take-long-to-finish.sh &
./check-if-previous-script-ran-or-exit.sh

echo "Script ended on Feb 15, 2011, 9:20AM" > /tmp/done.txt

So in the second one you just check if the file exists.

Eduardo
  • 7,631
  • 2
  • 30
  • 31
  • Makes sense. but, the script which is running gives me some output, which is displayed on the console.. how to check if my previous script ran or exit? $? or anything else ? – user57421 Feb 08 '11 at 18:42
  • Well you could make that script create a file when done. I've added the comment to the answer.... grrr – Eduardo Feb 15 '11 at 15:20
0

"timeout 5 ssh user@machine" worked fine for me.