297

I found this question, but I'm sorry I don't quite understand the settings on the two variables ServerAliveInterval and ClientAliveInterval mentioned in the accepted response. If my local server is timing out, should I set this value to zero? Will it then never time out? Should I instead set it to 300 seconds or something?

My question is simply, some of my connections time out when I suspend & then unsuspend my laptop with the response Write failed: Broken pipe and some don't. How can I correctly configure a local sshd so that they don't fail with a broken pipe?

7 Answers 7

367

ServerAliveInterval: number of seconds that the client will wait before sending a null packet to the server (to keep the connection alive).

ClientAliveInterval: number of seconds that the server will wait before sending a null packet to the client (to keep the connection alive).

Setting a value of 0 (the default) will disable these features so your connection could drop if it is idle for too long.

ServerAliveInterval seems to be the most common strategy to keep a connection alive. To prevent the broken pipe problem, here is the ssh config I use in my .ssh/config file:

Host myhostshortcut
     HostName myhost.com
     User barthelemy
     ServerAliveInterval 60
     ServerAliveCountMax 10

The above setting will work in the following way,

  1. The client will wait idle for 60 seconds (ServerAliveInterval time) and, send a "no-op null packet" to the server and expect a response. If no response comes, then it will keep trying the above process till 10 (ServerAliveCountMax) times (600 seconds). If the server still doesn't respond, then the client disconnects the ssh connection.

ClientAliveCountMax on the server side might also help. This is the limit of how long a client are allowed to stay unresponsive before being disconnected. The default value is 3, as in three ClientAliveInterval.

11
  • 1
    Ok, so I would interpret zero seconds to imply "don't keep alive" which is why it doesn't poll the client/server?
    – M. Tibbits
    Commented Oct 12, 2010 at 16:33
  • 5
    yup 0 = don't send a null packet. Another different would be that ServerAliveInterval is set in the client config whereas ClientAliveInternal is set in the server config.
    – Barthelemy
    Commented Oct 12, 2010 at 16:37
  • 12
    This seems like good advice to prevent idleness causing timeouts, but I don't understand how it relates to the OP question of preventing broken pipes when the client suspends. When asleep, the client would not be able to send a null packet, so surely this setting is moot?
    – Sparhawk
    Commented Oct 6, 2013 at 2:12
  • 4
    Looking back at this old answer, I believe responded to the question in the title and not the question in the second paragraph, hence the comments about ServerAliveInternal not being helpful for suspend, which I agree with. @JonasWielicki ClientAliveInterval could be bad in a case of suspend because the suspended client would not answer the server and the server would eventually disconnect the client after ClientAliveCountMax.
    – Barthelemy
    Commented Jan 16, 2017 at 10:35
  • 2
    "Setting a value of 0 (the default) will disable these features so your connection could drop if it is idle for too long." No, a zero value means that your connection will NOT be broken when you lost connectivity between the client and the server, as when the route is down temporarily. This has nothing to do with the connection being dropped because of idleness.
    – user313992
    Commented Jan 24, 2021 at 13:03
73

This is explained in sshd_config manual (man sshd_config):

ClientAliveInterval

Sets a timeout interval in seconds after which if no data has been received from the client, sshd will send a message through the encrypted channel to request a response from the client. The default is 0, indicating that these messages will not be sent to the client. This option applies to protocol version 2 only.

ClientAliveCountMax

The default value is 3. If ClientAliveInterval (see below) is set to 15, and ClientAliveCountMax is left at the default, unresponsive SSH clients will be disconnected after approximately 45 seconds. This option applies to protocol version 2 only.

For the client options, see the explanation in man ssh_config:

ServerAliveInterval

Sets a timeout interval in seconds after which if no data has been received from the server, ssh will send a message through the encrypted channel to request a response from the server. The default is 0, indicating that these messages will not be sent to the server. This option applies to protocol version 2 only.

ServerAliveCountMax

The default value is 3. If, for example, ServerAliveInterval is set to 15 and ServerAliveCountMax is left at the default, if the server becomes unresponsive, ssh will disconnect after approximately 45 seconds. This option applies to protocol version 2 only.

Based on above, 0 means it's disabled. Therefore you should set these values high enough to avoid Broken pipe error.

4
  • 1
    Helpful post. But I'm so frustrated by this. I am setting large intervals all over the place and my connection is still getting broken after just a few minutes. (using openssh on Ubuntu, not sure if that's relevant) Commented Jul 21, 2017 at 22:18
  • 1
    @user7000 Configure both, the client (ssh) and the server (sshd). This may help: How to fix issues with 'The SSH connection was unexpectedly closed by the remote end'.
    – kenorb
    Commented Jul 21, 2017 at 23:08
  • I think I'm getting somewhere. It might be that I was not putting a space before ServerAliveInterval in my config file. Commented Jul 28, 2017 at 17:34
  • BTW, seems it's better to set ClientAliveInterval to be 0 or small, and also make ClientAliveCountMax small, otherwise, if there are a lot ssh logins, with time it will make ssh service stuck, and make ssh fail from time to time.
    – Eric
    Commented Dec 18, 2019 at 8:50
30

The Answer from Barthelemy is cool but doesn't really get to the root of the problem. You suspend your machine and want the SSH session to be still alive when you boot up your computer.

There is no such configuration for ssh that will keep the connection alive like that. SSH uses TCP, for a start you need the three way handshake and then keep alive after some idle time. When you shutdown/hibernate all your TCP connections are closed with FIN. No way to overcome that.

For a dirty workaround you can use VPS or another online box with screen to keep the connection. My advice don't do that for security reasons.

2
  • 1
    i think security is irrelavant, because it could be a more secure machine than the one logging on with. Just make sure its secure. Its how i do my every day work, keep several multi paned terms (gnus screen) opened up on a hardened jump host. So its not really dirty, its actually perfectly effective solution, use a jump host, and also have the ssh config on that include the keep alive params. Commented Apr 17, 2020 at 20:50
  • Actually there is a configuration - sort of - You can set up a UDP VPN between endpoints. I've done this, started a session, gone on a multi-hour long flight without Internet (I believe my laptop was suspended, but this was some years ago), hopped off in a new location and my SSH session continued as if nothing had happened.
    – davidgo
    Commented Sep 13, 2022 at 21:13
20

Since you can't guarantee that an SSH connection (being TCP) will remain alive once one end stops sending ACKs to received packets, I personally use http://www.harding.motd.ca/autossh/ to restart all my SSH connections almost as soon as I unsuspend.

Since GNU Screen will be in use on the server side, re-attaching gets me to where I was before.

You can have it listening on extra ports so that it continually checks the connections are still alive, but personally I find it works well enough with that disabled and just relying on SSH's own ServerAliveInterval / ServerAliveCountMax.

Another option is http://mosh.mit.edu/ which uses UDP and recovers seamlessly from long term lack of connectivity.

1
  • Why can’t that be guaranteed? Is it because the remote OS will kill the TCP connection once it stops receiving ACKs for sent packages? Doesn’t suspending your client machine cause the OS to kill all TCP connections locally?
    – Shuzheng
    Commented Jan 27, 2021 at 18:38
7

Put your long running session inside screen See screen -h for details

That way you can reconnect to the machine using ssh and reattach to the screen session

1
  • 2
    or tmux, which is similar to screen but has more active development Commented Feb 28, 2023 at 18:56
6

You could also run commands with nohup if you want them to run regardless of your SSH connection.

e.g.

$ nohup tar -xzf some_huge.tar.gz &

The & is, I think, not necessary, but it is convenient since it makes the process run in the background so you can do other stuff.

I always use nohup for any process that takes awhile, so that I don't have to start over if I lose the connection for whatever reason - power outage (at my remote location, not at the host obviously), network outage, whatever.

4
  • Note nohup on zsh doesn't work properly! Commented Jul 21, 2017 at 20:42
  • @user7000 what is improper about it? Commented Jul 21, 2017 at 22:11
  • I don't remember, I think it basically didn't keep the process running after the client got disconnected. It was a few years ago and I stopped using nohup and used disown instead. Commented Jul 21, 2017 at 22:17
  • 2
    I guess zsh users should stick with disown -h instead of nohup, unless the problem has been fixed since then. Commented Jul 21, 2017 at 22:19
-1

This is why Mosh was created:

Mosh (mobile shell)

Remote terminal application that allows roaming, supports intermittent connectivity, and provides intelligent local echo and line editing of user keystrokes.

Mosh is a replacement for interactive SSH terminals. It's more robust and responsive, especially over Wi-Fi, cellular, and long-distance links.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .