What the Tmux: An Unwatched Pot Boils
It's hard to explain tmux
, and saying that it's for "window management" or "multiple terminal sessions" doesn't quite do it justice, I think.
Window management isn't the core issue that tmux
solves for you, though it can be used for that!
Common question: tmux
gives me multiple terminal sessions, sure, but don't I have nicer ways of doing that already?
Ctrl+T Ctrl+T Ctrl+T, Ctrl+W Ctrl+W Ctrl+W!
Why go through the trouble of typing tmux a -t mysession
when I can Ctrl+T?
And when I'm done, gosh, I have to type tmux kill-session -t mysession
! What a drag! I'd rather Ctrl+W!
And when I switch between sessions, I'd rather click on the desired tab! None of that tmux a -t mysession
, and especially none of those tmux list-sessions
if I forget how I spelled a session.
Turns out, tmux
is more than window management.
Boiling Water at Uncle Sam's
Say hello to the shell. You've probably touched it at least once in your life, if you've opened the Command Prompt as a Windows user, Terminal.app as a MacOS user, and you've most definitely touched it if you're a Linux user.
The cursor blinks, waiting for us to type a command.
you@yourmachine % |
Okay, say we want to do something on Uncle Sam's machine, so we ssh into Uncle Sam's machine.
you@yourmachine % ssh uncle_sam
Now we're in Uncle Sam's machine,
you@unclesams % |
and we want to boil some water at Uncle Sam's, so we run a program named boil
.
you@unclesams % ./boil
A watched pot never boils
Okay, it's boiling. Let's bike around the neighborhood and come back.
you@unclesams % ./boil
Boiling water...
We come back, and...oh no!
you@unclesams % ./boil
Boiling water...
you@yourmachine % |
We got kicked out of Uncle Sam's. When we get back into Uncle Sam's, we see that our boiling program has been killed and we have to start all over again. Quandary!
An unwatched pot never boils
There are many reasons why we got kicked out of Uncle Sam's. Maybe we took our laptop into the forest and got disconnected. Maybe we stayed connected, but Uncle Sam's has rule where they log out anyone who's been inactive for too long.
Another common question: What we run ./boil
in the background, like ./boil &
? Would that work? No, our boiling program will likewise get killed.
Basically, we can't leave our boiling water unattended.
...or can we? tmux
to the rescue!
Tmux to the Rescue
First, I'll give you the magic words:
tmux new -s boilsesh
./boil &
Done! It's boiling, and it'll still be boiling.
We can detach from our session (Ctrl+b d
) and reattach to it (tmux a -t boilsesh
) as many times as we want, and it'll still be boiling.
We can bike around the neighborhood, and even if Uncle Sam kicks us out, we can get back in, reattach to our tmux session, and it'll still be boiling.
With this, an unwatched pot boils :)
When does our pot stop boiling?
tmux
protects your boiling pot from situations where you
- close your terminal
- are boiling your pot on a remote session, and you get logged out of the remote session
- are boiling your pot on a remote session, and you log out, restart, or shut down your computer locally
tmux
will NOT protect you when you
- are boiling your pot on a local session, and you log out, shut down, or restart your computer locally
- are boiling your pot on a remote session, and Uncle Sam decides to reboot the remote server
Addendum: Why This Works
How the Shell Works
Let's go back to the shell. The shell is actually a process that
- Reads your command
- Evaluates the command
- Prints the result
- Loops back to 1
You may have seen this called REPL, or the read–eval–print loop.
Now we command it to run our boil
program.
you@yourmachine % ./boil
Recall that the shell is a process. When we hit enter on ./boil
, we create a copy of the shell process that we call the "child process" (aka "forking" a child process from the shell) and replace the running program in the child process with boil
.
When we close out of the terminal, log out, or doing any of the scandalous deeds listed under "tmux
will NOT protect you...", the shell process dies.
To announce its death, the shell process forwards a signal SIGHUP
to its children, and its children die in its honor.
Among its children is the process running our boil
program. So, it doesn't matter whether we ran boil
in the foreground as ./boil
or in the background as ./boil &
, the child process receives SIGHUP
and dies in the shell's honor.
How Tmux Works
If you're curious, you can read the source code under /usr/src/tmux
or here. Feel free to email me if you have any questions and I'll look over it when I have time.
Short explanation: When we create a tmux session, tmux
forks a child process. In other words, the shell we interact with in the tmux session is a child process of tmux
, not a child of the SSH shell. When Uncle Sam logs us out, the SSH shell does get terminated, but because our shell processes are children of the tmux
process, they don't get killed.
Long explanation: When we create a tmux session, tmux forks a child process, which is initialized as a daemon server. The daemon server use the syscall setsid
to create a new session. The daemon server opens its fds 0, 1 and 2 at /dev/null
. Then the daemon server enters an infinite loop for processing commands from the client.
The parent process of this daemon server is the tmux client. When the child process, aka the daemon server, has been initialized, its parent, the tmux client, then sends a command to the daemon server to start a new shell, set up the terminal for the user, and so on.
When we attach to an existing tmux session, tmux connects to the daemon server started previously. As for the mechanism in which tmux connects to the daemon server? Unix sockets are used.
You can actually list these sockets! Each session has a unix socket under directory /tmp/tmux-${uid}
. For example, I have uid 1001, so my unix sockets will be under /tmp/tmux-1001
.
/tmp/tmux-${uid}
, write it down! We could probably do something with it later.
Isn't it great how we can rest easy as our unwatched pots boil? Next time you offer to manage someone's pots and pans, maybe instead of saying, "I'll manage your pots and pans," go the extra mile and bring them peace for their unwatched pots.