Clearing hung ssh sessions
I frequently connect to remote servers at work using SSH. Instead of opening a new SSH connection each time I need to access the remote box, I've configured my ~/.ssh/config to persist a single master connection and simply re-use that same one each time instead of wasting time spinning up a new connection every time I want to do something involving that remote box.
Host * ControlMaster auto ControlPath ~/.ssh/cm_socket/%r@%h:%p ControlPersist yes TCPKeepAlive yes
To be honest, I'm not perfectly clear on all of the details. The first line means "apply these settings for all hosts," and the ControlPath line tells it where to store a file that (somehow) represents the persisted master connection.
Anyway, on OS X, the ssh connections to remote boxes reliably hang when resuming from a Sleep state. I've been too lazy to adjust when my computer sleeps, so this happens every night while it sleeps during idle phases and whenever I manually activate sleep. To solve it, I need to kill the old hung connections so that new ones can be established for the new day. In addition, TRAMP makes its own connection within Emacs that needs to be killed, or else it too tries to reuse a hung ssh session, which in the past used to hang all of Emacs. So, I created two simple defuns that reset all of the open ssh connections in Emacs and the ControlMaster ones.
(require 'dash) (defun reset-ssh-connections () (interactive) (let ((tramp-buffers (-filter (lambda (item) (string-match "tramp" (buffer-name item))) (buffer-list)))) (while tramp-buffers (kill-buffer (car tramp-buffers)) (setq tramp-buffers (cdr tramp-buffers)))) (delete-hung-ssh-sessions)) (defun delete-hung-ssh-sessions () (interactive) (let ((cm-socket-files (directory-files "~/.ssh/cm_socket" nil nil t))) (while cm-socket-files (let ((filename (car cm-socket-files))) (if (not (or (string= "." filename) (string= ".." filename))) (delete-file (concat "~/.ssh/cm_socket/" filename))) (setq cm-socket-files (cdr cm-socket-files)))))) (global-set-key (kbd "C-s-r") 'reset-ssh-connections)
Due to the use of the -filter function, magnar's excellent dash.el is required. The parent function is reset-ssh-connections. It filters the buffer list for all TRAMP files and deletes those, clearing Emacs' internal sessions. It then calls delete-hung-ssh-sessions which goes to the ControlPath folder above and deletes all of the matching files in there. Afterwards, there are no hung sessions and the next time I open an ssh connection to any box, it'll start a new one and then be transparent from then on. I've bound it to C-s-r - the s is the hyper key which I recently learned I can bound on OS X boxes, so that's pretty nice :)













