What is "terminal multiplexing" and why should I, J. Random Hacker, care?

Have you ever had your network connection die in the middle of a long-running job or edit session, causing you to lose work? Have you ever thought "OK, I have 50 xterms open right now for five different projects, how do I group these to make some sense out of this mess?" Have you ever wished you could walk away from your workstation in one place and seamlessly resume all of that project state elsewhere (e.g., for those late night "Aha!" moments, long after you've gone home from work)? If the answer to any of those questions is "yes," terminal multiplexing might make your life much easier.

A terminal multiplexer is, in essence, a program that transparently "stands between" your active terminal connection and N-number of spawned terminal sessions. See the figure below for a "before" and "after" of how a given user is interacting with a server (assuming SSH for remote connection):

click to embiggen

Imagine in the diagram above that the network (represented by the vertical dotted line) suddenly went away. Maybe the wifi died in the coffee shop, maybe a backhoe found your network cable, maybe your laptop ran out of power and shut down on you, whatever. The user in the "before" scenario just lost their active connection to each of their shell sessions, something to which many programs do not respond well, and likely lost at least some amount of work in addition to the bother of having to restore the state of their project work ("Hmm, I was editing foo.c, and bar.pl, and I had a psql session going to bazdb. . ."). Feel free at this juncture to doodle a little cloud of steam coming out of the poor fellow's ears.

The user in the second scenario is in a much better situation however. Since the terminal multiplexer is running on the server end of the connection and managing all of the spawned sub-sessions, no state has been lost. All of his programs (editors, database shells, whatever) are still happily running with no idea than an interruption has occurred. So, once the network is restored, all the second user has to do is re-login to the server and resume his terminal multiplexer session. (An important note here: naturally if something happens to the server itself, the terminal multiplexer can't help you.)

The user in the first scenario, even under normal conditions, must maintain N-number of terminal windows open. For one or two concurrent sessions, this is not a big deal. However, this quickly becomes disorganized as the need for concurrent sessions increases (imagine a web developer working with an editor, a watched log file and a database shell related to each of four projects; at a minimum this would be 12 terminal windows). The second user need only have one window for all of their sessions (e.g., they could choose to have one terminal multiplexed 12 ways, or four terminals multiplexed three ways, to continue the previous example). This "bundling" of persistent project state into one window radically cuts down on the number of terminal sessions to keep track of during a busy work day.

Combining the prior two paragraphs yields perhaps the nicest day-to-day use for terminal multiplexers: portable project state. Since all you need to do to resume your project work exactly where you left of is log into the server and resume your terminal multiplexer session, you are not tied to any particular client machine or location. The user in the second scenario could walk away from their workstation at work, have an epiphany over dinner at home, and (via something like a VPN, ssh, or similar) log back into the central server to continue their work. The first user, if they wanted to work remotely, would have to try to recreate all of their project state by logging in and starting programs anew in separate sessions (hoping that no bad behavior would be observed, e.g., editors fighting over modifying the same open files).

There are many other potential uses of terminal multiplexing, this article attempts only to scratch the surface with the above scenarios. For example, it is possible to configure many such programs to allow more than one user to view the same session, allowing for things like remote pair programming and observed practical technical interviews. These uses are left as exercises for the reader as they lie beyond the scope of this introductory article.

GNU Screen: Open Source Terminal Multiplexing

GNU screen is an open source program that provides terminal multiplexing facilities. It is available for many Unix and Unix-like platforms. The GNU screen homepage includes a comprehensive user manual along with download links for the source itself (though it is available pre-packaged for many operating systems; check with your vendor's package repositories and/or Google for " gnu screen package"). This article attempts to give a tutorial on GNU screen usage in light of the overview presented in the first section (in other words, how to achieve all of those good things with screen). In the process of evangelizing about the virtues of using screen, I have, in the past, managed to condense this information onto Post-It notes and once even into a 140 character tweet. I'll try to elaborate a bit more, but at its core, the day-to-day operation of screen is not complicated.

GNU screen is invoked from the command line by entering "screen" at your shell prompt. By default, screen will show a bit of information about itself, and when you press any key, presents you with a shell session (e.g. bash). From this point forward, interaction with the running screen is done by means of meta-character input (in other words a specific key sequence alerting screen that what is to follow is a screen command, and not regular input to be passed through to the sub-process you are interacting with). The default command meta-character is ctrl-a (that is, pressing the control and A simultaneously). A table of common GNU screen commands is shown here (with "ctrl-a" abbreviated as "c-a", and "c-a x" means press control and a simultaneously, release, then press x); there are many other features but this is enough to start:

GNU screen CommandAction
c-a c"C"reate a new sub-process window (defaults to new shell session)
c-a nSwitch to "n"ext window in the circular list of windows 0 .. (N-1)
c-a pSwitch to "p"revious window in the circular list of windows
c-a (a number)Switch to window number (a number)
c-a A (shift-a)Retitles this window (default is running process name e.g. bash)
c-a " (shift ')Present list of windows w/ titles, allowing selection via arrow/enter
c-a d"D"etach from the running screen session (see below)
c-a ?Display a list of commands and other help

Detaching and resuming form the remainder of the core functionality of GNU screen. Once you have detached from GNU screen (or if your network dies, or your client machine does), it remains running on the server. You can see a list of your running screen sessions by entering "screen -ls" (this prints out all running screens and their names, if any, and exits, rather than starting a screen session). To resume a GNU screen session that is already running, enter "screen -dr" (detach running session and reattach). There are other methods of increasing sophistication that can be used with these options, consult the man page for more information. Typically I use -dR always as that will detach and resume, or create if one is not present, so that I only have to enter "screen -dR" (actually, I tend to use "screen -dRAU" as that enables Unicode support and Adapts all sub-process windows to be the same size as the terminal window I am currently using; as this is a bit much to type every time I set up a shell alias like, 'alias sr="screen -dRAU"' ["s"creen "r"esume] to reduce typing). With detaching and reattaching, you could stop working on something, fly to a different continent, log back in and be right where you left off.

One wrinkle that sometimes arises during use of GNU screen is terminal settings, and the TERM environment variable in particular. The TERM environment variable is essentially how running programs (e.g., editors, database shells, less/more) know what kind of terminal you are using so that they can emit the appropriate output format. GNU screen by default causes the TERM environment variable to be set to "screen", which on some operating systems and in some environments is not a recognized value. Commonly this manifests as glitchy display from things like full screen editors, less/more type paging programs warning that "X is not a recognized terminal type" or similar. This can be enough of a complicated question in terms of what the right value should be and how it is set that if you run into this, it probably pays to turn to your local systems administrator for help. For example, on Solaris systems, I sometimes have to do things like "export TERM=dtterm" in bash to get sensible behavior from things running under GNU screen. This issue tends to be less commonly encountered on the core free Unix operating systems like Linux and the BSDs, in my experience.

tmux: An Open Source Competitor to GNU Screen

Open source is nothing if not full of options, and terminal multiplexing is no exception. A relatively recent addition to the field options, tmux is a BSD-licensed terminal multiplexing program. In terms of feature sets it is broadly comparable to the older GNU screen, with the first visible difference being that the command meta-character is control-b rather than control-a. The tmux homepage has extensive documentation and references for further usage. In terms of benefits, power users may find that tmux is easier to configure than GNU screen and it makes it easier to make named groups of windows/programs that should start when it does (e.g., allowing you to define a set of programs to automatically start up for a given project name, for instance a shell in the right root directory of the source code, a database shell pointing to the right database). There are other differences, but they all lie in the realm of uses more advanced than what would be within scope for this article. The downside, of course, to a newer program is that it is less commonly installed and may not be present in all operating systems' precompiled package repositories.

Conclusion

Terminal multiplexing may sound arcane at first blush, but the theory and practical use of it are fairly straightforward as illustrated above, and I believe will make life considerably nicer and more productive for developers working in command-line oriented environments. This article only scratches the surface of the power available through GNU screen and tmux; a great deal of flexibility and configurability is available for the motivated power user.