447

I frequently ssh into my box at home from school, but usually when I change classes and my computer suspends, the pipe will be broken. However, ssh simply locks up - Ctrl+c, Ctrl+z and Ctrl+d have no effect.

It's annoying to have to restart my terminal, and even more annoying to have to close and re-create a new screen window.

So my question, is there an easy way to make ssh die properly (i.e. when the pipe fails "normally" it will exit with a message about a broken pipe)? Or do I have to figure out what the PID is and manually kill it?

4
  • If I got disconnected with an active SSH session, it freezes. I just kill it and start a new session. No information is lost because I use GNU screen.
    – Lekensteyn
    Mar 11, 2011 at 16:33
  • Me too - screen is the best. But it's still annoying to have to screen -x :P Mar 12, 2011 at 6:43
  • [mosh](mosh.mit.edu) is a neat alternative to avoid this problem. It "stays connected" even with intermittent internet connectivity.
    – jaynp
    Dec 13, 2014 at 9:52
  • @jaynp The drawback of me using mosh (since two minutes ago) is that I don't know how to disconnect it. I'm using a tmux+irssi session on a remote host (as an IRC bouncer, sort of) and I do want to disconnect sometimes (while keeping the tmux+irssi running) and that I did with <enter>+~+. using SSH but won't work using mosh. Jan 28, 2017 at 15:24

3 Answers 3

641

Normal keys are forwarded over the ssh session, so none of those will work. Instead, use the escape sequences. To kill the current session hit subsequently Enter, ~, ..

(Keep in mind that in international keyboards where ~ is set to be a composing character, you have to hit it twice: Enter, ~, ~, .)

More of these escape sequences can be listed with Enter, ~, ?:

Supported escape sequences:
     ~.   - terminate connection (and any multiplexed sessions)
     ~B   - send a BREAK to the remote system
     ~C   - open a command line
     ~R   - request rekey
     ~V/v - decrease/increase verbosity (LogLevel)
     ~^Z  - suspend ssh
     ~#   - list forwarded connections
     ~&   - background ssh (when waiting for connections to terminate)
     ~?   - this message
     ~~   - send the escape character by typing it twice
(Note that escapes are only recognized immediately after newline.)

You can close the list of Escape sequences by hitting Enter.

Notice that because hitting ~~ causes ssh to send the ~ instead of intercepting it, you can address N nested ssh connections by hitting ~ N times. (This only applies to ~s that directly follow an Enter.) That is to say that Enter~~~~~. terminates an ssh session 5 layers deep and keeps the other 4 intact.

8
  • 51
    For keyboard layouts where ~ is a dead key, the key sequence is Enter ~ Space .. Nov 20, 2012 at 12:55
  • 5
    Note that you need to uncomment the line EscapeChar ~ in /etc/ssh/ssh_config (or ~/.ssh/ssh_config if you prefer).
    – Aditya M P
    Aug 3, 2013 at 6:19
  • 6
    @Hitechcomputergeek Enter ~ ~ . Since ~ ~ sends a literal ~ through your SSH session, the second SSH session will receive it as a single tilde and will interpret the . as part of the escape. To send to the 5th nested ssh session, just use 5 tildes in your escape sequence. Apr 9, 2016 at 23:41
  • 6
    life changing ;)
    – artm
    Mar 17, 2017 at 0:11
  • 2
    How have I never heard of this before? These escape sequences can even change port forwards on the fly, which I need somewhat frequently. My mind is totally blown
    – Xandaros
    Mar 2, 2020 at 17:13
69
+50

You may also want to setup application-level keep-alives for SSH to prevent it from freezing on connection issues. My ~/.ssh/config contains this:

Host *
ServerAliveInterval 15
# ServerAliveCountMax 3

This makes ssh client send application-level keep-alives every 15 seconds. Whenever three of them fail consecutively (the default of ServerAliveCountMax), the client considers the connection as hung and closes it.

Opposed to the other option TCPKeepAlive, this is checked within the encrypted channel and is not spoofable.


It is being noted that those keep-alives also help to, uhm, keep long-idling connections alive, i.e. prevent you from having half-closed tcp sessions hanging for hours untouched.

I highly recommend turning this feature on if you run into this regularly, but you should also know about the slight security risk it may impose. A known-plaintext attack might become easier if the attacker knows the interval and contents of an idle connection. This might be the reasons for why it isn't enabled by default.

8
  • 3
    Security reasons. You could go have drink and leave ssh sessio opened and your lab partner who you have worked with in the past 20 years might use your session to hijack the server and destroy it... while you were drinking in your 10 minute break. Mar 11, 2011 at 19:16
  • 2
    @CYREX, eh? And how can turned off by default option prevent you from having unfair lab partners? %)
    – ulidtko
    Mar 11, 2011 at 21:31
  • 1
    @ulidtko: Is there any reason for not setting ServerAliveInterval to 1 so that a lost connection is detected immediately?
    – krlmlr
    Jan 19, 2013 at 8:01
  • 2
    @gertvdijk: Thank you. For me, it works even without the Host line. Also, "Modern ciphers such as Advanced Encryption Standard are not currently susceptible to known-plaintext attacks." (from the link you added)...
    – krlmlr
    Jan 19, 2013 at 22:32
  • 3
    you can also replace SSH with Mosh (mobile shell). Mosh connects to the server via SSH, but then establishes an UDP based channel that is resiliant against connection problems. Mosh has also a local echo, so you can see what you are typing, even if the server is not answering. When the keystrokes are delivered, Mosh marks the echoed text. mosh.mit.edu Oct 15, 2014 at 13:32
47

As noted in geekosaur's answer, the escape sequence ~. will terminate the connection.

The full list of escape sequences and what they do can be displayed by typing ~?:

Supported escape sequences:
  ~.  - terminate connection (and any multiplexed sessions)
  ~B  - send a BREAK to the remote system
  ~C  - open a command line
  ~R  - Request rekey (SSH protocol 2 only)
  ~^Z - suspend ssh
  ~#  - list forwarded connections
  ~&  - background ssh (when waiting for connections to terminate)
  ~?  - this message
  ~~  - send the escape character by typing it twice
(Note that escapes are only recognized immediately after newline.)
2
  • 1
    How do I close the list of escape sequences?
    – kristianp
    Oct 18, 2013 at 22:19
  • 4
    You dont, after it prints the escape sequence list, its ready to accept the next one.
    – Tejas Kale
    Mar 24, 2017 at 15:15

You must log in to answer this question.

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