17.5 screen: Persistent Terminal Sessions
Alright, let’s talk about screen. It’s the venerable old guard of terminal multiplexers, the application that kept our forebears’ long-running processes alive through dial-up dropouts and ssh session timeouts. It’s powerful, it’s ubiquitous (it’s probably already installed on that remote server you’re SSH’d into), and its default configuration is a user interface crime scene. We’re going to conquer it, because sometimes you don’t have a choice, and honestly, knowing screen is like knowing how to drive a manual transmission—it gives you a deeper understanding of the machine.
First, the core concept. You start a screen session. This isn’t just a new window; it’s a whole new environment, a container for one or more virtual terminals, that is completely detached from your current shell. You can run a process inside it, detach from the entire session, go home, log in from your laptop, and reattach right where you left off. The process never knows you left. It’s like pausing reality.
Starting, Detaching, and Reattaching
Fire it up. Just type screen. You’ll be greeted by a splash screen that you’ll immediately hammer spacebar to skip. Congratulations, you’re in a new session. Now run something long.
$ ./my-super-important-batch-job.sh
Now, the magic. To detach, you use the command sequence. All screen commands are triggered by first hitting the “command key,” which by default is Ctrl-a (as in, hold Control and press ‘a’). Let that go, then press d for detach.
Ctrl-a d
You’re dumped back to your original shell, and your batch job is humming along, blissfully unaware, in the background. To see what sessions exist on this machine, use:
$ screen -list
There is a screen on:
28427.pts-1.hostname (Detached)
The number is the PID of the screen session itself, and the rest is the attached TTY and hostname. To reconnect to that lonely session:
$ screen -r
If you only have one detached session, -r (reattach) is enough. If you have multiple, you specify the PID or name: screen -r 28427.
Naming Your Sessions
Running screen with no name is like buying a warehouse and putting everything in one giant pile in the middle. You will regret it. Always name your sessions. Do it from the start.
$ screen -S "database_backup"
Now when you list them, you see 28427.database_backup instead of that gibberish. It’s a lifesaver. To reattach, you can use the name: screen -r database_backup.
The Multi-Window Workflow
Here’s where screen starts to earn its keep. One session can hold multiple windows. You’re in window 0. To create a new one (window 1), it’s Ctrl-a c (for create). Now you have two completely separate shells inside the same persistent session.
How do you manage them?
Ctrl-a n- Go to the next window.Ctrl-a p- Go to the previous window.Ctrl-a "- List all windows in a visually awful but functional menu.Ctrl-a 0- Jump directly to window 0 (or any other number).Ctrl-a k- Kill the current window (you’ll be asked for confirmation).
This is perfect for organizing a related set of tasks. Window 0: monitoring logs (tail -f). Window 1: a database shell. Window 2: an editor. It’s all contained and dies together when you’re done.
The Infuriating Copy Mode
screen has a copy mode for scrolling back and copying text. It’s a testament to a bygone era of computing. To enter it, hit Ctrl-a [. You are now in what feels like a minimalist text adventure. You navigate with the arrow keys (or, if you’re a masochist, the vi-style h,j,k,l). To start selecting text, press spacebar. Move to the end of the text you want and hit spacebar again to copy it. To paste it, exit copy mode (hit Esc) and use Ctrl-a ].
Yes, it’s clunky. Yes, it’s awful. We put up with it because the alternative 20 years ago was nothing. You will learn to appreciate tmux’s more sensible copy mode later. For now, just know it exists.
Configuration: Making Screen Less Terrible
The default .screenrc is practically nonexistent, which is why the interface feels so barren. Create a ~/.screenrc file and add some sanity. Here’s a starter pack:
# ~/.screenrc
# Enable a slightly useful status bar
hardstatus alwayslastline
hardstatus string '%{= kG}[%{G}%H%? %?%{g}][%= %{= kw}%-w%{=bw}%n*%t%?(%u)%?%{-}%+w%? %?%{= kG}][%{g}%l%{y}][%{g} %c:%s %{y}]%{g}'
# Set a more readable scrollback buffer
defscrollback 5000
# Make the command key (C-a) actually respond in a timely manner
bindkey -k k1 select 0 # F1 = window 0
bindkey -k k2 select 1 # F2 = window 1
# ...and so on
This gives you a status bar at the bottom showing the host, window list, and time. The bindkey lines are a hack to make the function keys switch windows, which is often more reliable than trying to remember the other commands.
The Gotchas and The Glory
The biggest pitfall is the sheer opacity of its default state. You must name your sessions. You must. The second biggest is command collision. If you use Ctrl-a to jump to the beginning of the line in your shell (a common habit), you’re now also talking to screen. You’ll get used to hitting Ctrl-a a to send a literal Ctrl-a to the underlying shell.
But here’s the glory: its sheer simplicity and universality. screen is everywhere. When you’re on some ancient, minimal Linux box in a data closet, tmux might not be installed, but screen almost certainly is. It’s your digital Swiss Army knife for persistence. It’s not the most elegant tool, but it’s the one that’s always there, and it gets the job done without fuss. Master it, curse its archaic ways, and use it to make your workflows bombproof.