I’m Paul Herron, a full-stack developer and technical manager.
I focus mainly on back-end development with tools like Symfony
and devops with tools like Docker

Getting into tmux

by Paul Herron on 12 January 2014

Now I’ve finally got into tmux it’s painfully obvious I spent far too long ignoring the benefits of using a terminal multiplexer. Perhaps like many others I thought I’d be just fine muddling along with a few tabs open in my Terminal.app, periodically getting confused about what was going on in each one, ending up with way too many tabs open, or doing the regular dance of realising that my SSH connections hung after I changed Internet connections, and that the easiest way of reconnecting is to just close the zombie tabs, open some new ones and reconnect. Besides which, those tmux keyboard shortcuts looked a little arcane, and my head was still spinning from arcane shortcuts after learning Vim.

It always seemed like tmux would have to come later, and now later’s arrived I can say that picking it up really didn’t take long, and the benefits are so marked I’m a little unhappy I didn’t do this much earlier!

One tab per machine

People seem to use tmux in a variety of ways, including some crazy stuff with nested tmux sessions that looks interesting but is probably a little over the top for my needs. I’ve found that a nice workflow is to simply use one Terminal tab per machine, each of which is a tmux session on that machine. My local machine gets the first tab, the SHOWstudio dev server will get the second, the production server the third, etc. Perhaps I might also have a tab open for a virtual machine, such as a Vagrant instance running on my Mac.

tmux setup

Within each tab’s tmux session, I can then open as many windows and panes as I need. At any given time I might be cdd into a few different plugins, maybe running mysql or rsync in some other windows. Unlike before there really isn’t such thing as “too many tabs” – the number of tabs is limited by the number of machines I’m working with, and within each of those tabs I can run lots of windows simultaneously without it feeling too much, thanks to tmux’s nice layout, sensible window-switching shortcuts and window searching function.

Bullet-proof SSH sessions

One of the big reasons to pick up a terminal multiplexer like tmux was that it promised the ability to resume an SSH session. Let’s say you SSH into a remote machine in the regular way, start running a command and then your connection dies. Chances are you’ll be deposited back onto your local machine’s command prompt with a message like “Write failed: broken pipe”, and you’ll have to type something like ssh user@server to get connected again. At which point you’ll probably see that you’ve lost the state of what you were working on: the output of your previous command will no longer be shown, you’ll have to cd back to where you were, and the command you were running has probably stopped.

If you’d had the foresight to run it under the nohup command, at least the command you were running wouldn’t have stopped. But you’d still lose your previous commands and your working directory.

If you’d had the foresight to run tmux on the other hand, everything would be exactly as you left it. You’d just SSH back into the server, type tmux a to reconnect to your session, and see everything exactly as it was before.

This is only half the story though, because if your connection dies you’re still going to have to run the SSH command again to get back into the server. Not the end of the world, but it would be nice if your terminal could detect when the connection has died and do this for you automatically. That’s possible by installing autossh and using it instead of the ssh command. autossh will simply take your arguments and pass them through to ssh.

autossh user@server	

You can combine this with tmux to create the ultimate bullet-proof SSH session that never loses its state, and automatically reconnects itself whenever the connection dies:

autossh -t user@server 'tmux attach || tmux new'

I’ve got the above command set up as a function in my .zshrc file so that the above is available under a t command. Declare your host config in your ~/.ssh/config file and you can connect with a minimum of typing. For example:

# Connect to the computer in the flat, which is declared as `f` in ~/.ssh/config
t f

Shared configuration

The final element of making this setup painless is the ability to share my tmux configuration across all of the machines I control. I try and keep the configuration as simple as possible and it’s only a few lines; this way I wouldn’t feel too out of kilter when using a machine where I can’t adjust the tmux configuration to my liking. Even so, there are a couple of settings like set-title on that really make a difference, from which I really benefit having on all my machines. These are easily spread around using a Git repository.

Getting the configuration onto a new machine is then just a matter of cloning the repository and then symlinking the .tmux.conf file into place:

git clone git@paulherron.com:tmux ~/.tmux && ln -s ~/.tmux/.tmux.conf ~/.tmux.conf

Back to homepage Back to blog listing