Getting into tmux
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.
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 cd
d 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