Tmux FTW
Monday, December 23, 2024
So I have a bunch of Raspbery Pi's because reasons, and I want to ssh into them periodically to do things. Quite a common scenario, that all sysadmins solve somehow. But one of the things that has always bitten me - as a Windows user - is that when an ssh session gets disconnected, it ends - period. There's no 'reconnecting' to it. I'm used to Remote Desktop (again, Windows user) which works differently: if you disconnect and reconnect a session, it keeps running in the background and no work is lost.
Enter tmux, of course, the go-to solution for this on Linux. tmux is hard to describe, because it can do so much. On the one hand it's a terminal on steroids - it supports sessions, windows, and panes (window splitting) - scriptable, no less. But more importantly: it creates virtual terminals that keep running when you disconnect.
So, suppose I have three pis, unimaginatively called pi-1, pi2 and pi3. I ssh into them using
ssh pi-1
(Also support that as a sysadmin, I have of course set up everything that prevents me from having to enter usernames and passwords here.)
Once connected, I can simply enter
tmux
to start a new tmux session. It looks like a regular terminal, except with some status information at the top and bottom. Using hotkeys (or even mouse menus!) you can open new windows (sort of tabs) and switch between them. tmux will automatically close when you close the last window/tab, but also when you press Ctrl+A, then d (for "detach the current client").
For me, the real magic happens when you then log out of the ssh session, and log back in: tmux is still alive, all your windows are still there and all your processes are running. All you have to do is run tmux again, this time with the attach command:
tmux attach
And this is where it gets slightly complicated. tmux' default behavior is to start a new session, with its own windows, when you start it without arguments. So you always simply run tmux attach, right? Wrong: if there is no previous session to attach to, tmux will report
no sessions
So we need a way to start a new session when there is none, or to attach to a session if there is. Fortunately, there is a magic formula that does it all:
tmux new-session -A -s main
This tells tmux to attach to a session called main, or to create that session if it doesn't exist. Perfect for our needs - a single command to run that always does what we expect. It's just a pity that we have to remember that command and type it every time we connect to a remote Pi. But wait, we can tell ssh to execute a command on a remote machine! Why don't we just
ssh pi-1 "tmux new-session -A -s main"
Nice try, but no cigar:
open terminal failed: not a terminal
The problem here is that ssh will not start an interactive terminal to execute the tmux command. Luckily, we can force ssh to open a terminal anyway, using the -t switch. So here we are:
ssh -t pi-1 "tmux new-session -A -s main"
Boom! A one-liner that will connect to the pi and show me exactly where I left off. Of course, I made another small script to allow
ssht pi-1
because a) I'm lazy and b) I can't remember things I don't use often.
As I said: tmux FTW.