Unbreaking GNU Screen

GNU Screen is an extremely useful piece of software, but one that requires an annoying amount of hackery to make it useful. Herewith a description of why you want to use it, and what you have to do to make it work better.

Screen has a huge number of features that many people like. I don’t claim to know about all of them, but these are the ones I use:

  • Long-lived interactive programs. I use a BitTorrent program called rTorrent which provides a Curses-based user interface. I run it on a headless Linux box (on a Mac Mini). I can SSH in to the Mini, start Screen, and run rTorrent inside Screen.

    Then I can detach from the Screen session, and go away. Any time I like, I can log in to the Mini again, reattach the Screen session, and rTorrent has been sitting there quietly doing its thing unattended.

  • Long-lived non-interactive programs. Suppose you have a data manipulation job that you’d like to start running before you leave work, so that you can log out, and come back next day to find the results. Traditionally, you have to do something like this:

    (nohup long_job arg...  &)

    The nohup ensures that long_job doesn’t get killed when you log out. Backgrounding with & is necessary because nohup doesn’t do that for you, and the extra shell process (…) is a simple way of hiding the background task from the shell’s job-control list. Any output generated will be left in a nohup.out file by default; you’ll need to check that when you come back, and try and work out whether everything finished successfully. And because of all these hoops you have to jump through, if the job is actually a complex pipeline rather than just a simple command, it’s rather more awkward — the simplest approach is probably to just write a shell script containing the pipeline, and execute that script under nohup.

    With Screen, it’s rather simpler. Just start the job interactively under Screen, turning on verbose progress messages if you want. Detach from Screen, then log out. When you come back the next day, reattach to the Screen session, and you can trivially check whether the job completed, or generated any error messages.

  • Dealing with slow and/or unreliable network connections. If you’re using a network connection which is prone to dropped connections (like, say, a wifi connection in an area with lots of wireless interference), it can be extremely annoying to try and work on a remote system. Using screen doesn’t completely make that pain stop, but at least if the network disappears you can get back to exactly where you were beforehand.

    You get similar advantages if you’re using a slow network connection. Suppose you’ve logged into a remote server to run a large rsync transfer. You’d like rsync to emit progress messages as it goes, but if your network connection to the server is slow enough, the progress messages might become the limiting factor in how quicky the transfer completes. Running rsync under Screen eliminates that issue: rsync will write its messages to a local Screen process, which will copy them to your network connection asynchronously.

I like Screen. But it took me a long time to get to that point. I’d heard for a long time about the convenient things it can do for you, but every time I’d tried it, I got so irritated so quickly that I’d end up quitting it without trying it out. It seemed to have several features that caused constant annoyance to some degree or another:

  • It steals the Control+A keystroke from me. That’s probably not a hugely unreasonable keystroke for Screen to pick, but I’ve been an Emacs user for about 14 years, now — so long that there’s just no way I can retrain my fingers not to know that Control+A means “beginning of line”.

  • It breaks scrollback in my terminal windows. I configure my terminal emulator to use many lines of scrollback, and I’m accustomed to Shift+PageUp paging through it. By default, Screen switches to the terminal’s “alternate screen”, in which scrollback is unavailable. Screen does offer its own equivalent to terminal scrollback, but it requires so much additional effort to access it that I find it mostly useless.

  • It breaks my expectation that other applications use an alternate screen. I’m used to interactive Curses-style applications (Vim, Mutt, rTorrent, and the like) running in the alternate screen: it allows you to separate your normal line-by-line shell interaction from full-screen stuff. Screen’s default behaviour is to offer no alternate screen, so quitting (or suspending), say, a Vim process doesn’t return you to a position where you can read what was in your terminal before you ran Vim.

I’m sure that some users would consider at least one of these things features rather than bugs, but to me, they’re showstoppers. Fortunately, they’re all easily fixable in your ~/.screenrc file.

First, to restore Control+A to its standard meaning, you just have to pick an alternative keystroke. I went for Control+6 (aka U+001E, aka ^^, aka RS in ASCII), because it’s almost never used anywhere else, and it’s easy to type. In the vanishingly rare case in which I might want to type a ^^ character, doubling the Control+6 keystroke is fine:

escape ^^^^

To make scrollback work, all you need to do is tell Screen not send the termcap initialisation and deinitialisation strings, at least in things that claim to be X-based terminal emulators:

termcapinfo xterm*|rxvt*|kterm*|Eterm* ti@:te@

Finally, Screen has a simple option to make it provide an alternate screen to applications running inside it that might want one:

altscreen on

My full Screen configuration contains those settings and a couple of others.

It’s good that you can easily unbreak Screen, but that doesn’t stop me wishing it weren’t necessary. If Screen had better defaults, I might have started using it five or ten years earlier than I did.