Here are notes on how to use the program called screen which is a terminal multiplexer. The GNU Screen home page can be hard to find thanks to the indistinct name.

Customize Settings

My first suggestion before even running screen would be to customize the settings for screen. For example, using "Ctrl-a" for screen’s escape key is, in my opinion, crazy. Ctrl-a is used for too many other things (beginning of a line in bash and most other ncurses environments). I like to use Ctrl-g which rarely conflicts with anything.

To do this, add:

escape ^gg

to your ~/.screenrc file.

The second setting I would recommend is to keep an active status line running. These are called "captions" in screen terminology. There are several reasons to have one:

  1. It alerts you to when screen is running. It can be hard to tell if you’re in a screen session or not otherwise. The status line makes it clear.

  2. There is a clock on the status line. You may have a clock on your wrist but the point of a clock here is that over an ssh connection, the screen will be refreshed about once per second at a minimum. This is useful for not letting connections drop.

  3. The status line allows you to see exactly what windows you have open.

To get a decent status line use something like my favorite:

caption always " %w --- %c:%s"

My .screenrc looks like this:

caption always " %w --- %c:%s"
escape ^gg                    # only seriously conflicts with mutt
vbell on                      # default: off
vbell_msg "   -- vbell_msg!! --   "   # default: "Wuff,Wuff!!"
startup_message off           # default: on
defscrollback 1000            # default: 100
autodetach on
pow_detach_msg "Screen session of \$LOGNAME \$:cr:\$:nl:ended."

Starting Screen

To use screen you just type screen to start initially. If you’re using a "caption" or status bar, you should see that. If not you can type echo $STY and it should show you something. If you’re not in a screen session, then it won’t.

Restarting After A Power Outage

When your server running a complex screen session dies, restoring all the terminals to the way you like them can be tedious. Here is script that shows the basic technique.

#!/bin/bash
# Chris X Edwards - 2021-10-07 - screen_reboot.sh
# This script is to recover my complex screen sessions after a power
# outage. It is a good place to record the setup details of my screen
# terminals and what they should be doing.

# === Start Main Session ===
S=Xed_main_session
if screen -S $S -list; then
    echo "WARNING! There is an existing screen session called: $S"
    echo "Press [C]-c to abort this, or Enter to DELETE that session and replace it with a new one."
    read
fi

# Delete any sessions with the main session name just in case.
screen -S $S -list |\
grep $S |\
awk '{print $1}' |\
while read SS; do \
    echo $SS
    screen -S $SS -X quit
done
# Start new main session in background.
# `-d -m` starts detached allowing this script to continue tweaking.
screen -S ${S} -d -m

# === Basic Setup Of Each Window ===
# 1. Create a new screen terminal. (First is present automatically.)
# 2. Set title of this screen terminal.
# 3. Send a command to window. Repeat as needed.

# Helpful for simulating "enter" presses after commands.
NL=$(echo -ne '\015')

# (Present by default.) # Mail client.
screen -S ${S} -p 1 -X title "mu"
screen -S ${S} -p 1 -X stuff "mu${NL}"

screen -S ${S} -X screen 2 # Help notes
screen -S ${S} -p 2 -X title "h"
screen -S ${S} -p 2 -X stuff "cd /home/xed/X/web/live/help/${NL}"
screen -S ${S} -p 2 -X stuff "clear${NL}"

# etc...

# Reattach this screen and start using.
screen -r ${S} -p 1

Screen Actions

Now you can use the screen session. You can:

  • New - Make more windows with <screen_escape_key>+c

  • Next - Switch to the next window with <screen_escape_key>+n or <screen_escape_key>+<space>

  • Previous -Switch to the previous window with <screen_escape_key>+p

  • Jump - Switch to a specific screen window with <screen_escape_key>+<number> where number is the number of the screen window.

  • Recent - Switch back and forth between two (of the most recent) screen windows with <screen_escape_key>+<screen_escape_key>. This is very handy.

  • Name - Name windows if you have a caption/status line with <screen_escape_key>+[S]-A. That’s a captital A. After typing that key sequence, you can edit the id of the window for the current session. Usually it just says bash (or your shell). I like to rename it to something short that reminds me what’s going on in that window.

  • Kill - Kill stuck windows. Sometimes bad things happen and you have to kill a window. Use <screen_escape_key>+[S]-K. It will politely ask for confirmation.

  • Shutdown - To close all windows and stop screen <screen_escape_key>+\ .

  • Reset - You can use /usr/bin/reset to recover from dumping a screen full of binary (causing who-knows-what terminal settings madness) or just use <screen_escape_key>+[S]-Z

  • Select - Have too many screens open? Try <screen_escape_key>+" to get a menu of them.

  • Monitor - Want to know when some activity has happened on one of the screens? Use <screen_escape_key>+[S]-M. Then the name in the status bar will invert when there is new activity. Not only can you monitor for activity, but you can monitor for a lack of activity. Perhaps you are waiting for a compile to finish, you can do <screen_escape_key>+[S]-_ and when 15 seconds have gone by with nothing changing, you’ll get the inverted name indicator. Consider shortening the time needed to register inactivity with the silencewait 5 command (shown here setting to 5 seconds).

  • Log - With <screen_escape_key>+[S]-H, screen activity is written to screenlog.n. Use a second time to toggle log writing off.

  • Help - <screen_escape_key>+[S]-?. Note that what this shows is missing some things that are found in the man page which might be a better reference.

Checking For Screen Status

Sometimes you have scripts that should be run in a screen session (e.g. minecraft or octoprint servers). How do you know if you’re properly in a screen session?

if [ "${TERM::6}" == screen ]; then echo "Screen session OK"; else echo "NOT in a screen"; exit 1 ;fi

Put this in your script and it will patiently stop to allow you to start the screen session.

Splitting

I used to use screen splitting but since screen only supported horizontal splitting and I usually wanted vertical, I just stopped worrying about it. But these days (later than 2016-12-10, version 4.05.00), screen seems to do just fine splitting vertically so maybe worth doing. Since I forgot the splitting bindings, I’ll put them here.

  • <screen_escape_key>+[S]-S - splits horizontally.

  • <screen_escape_key>+| - (pipe) splits horizontally.

  • <screen_escape_key>+<tab> - focuses different split regions.

  • <screen_escape_key>+[S]-X - Removes a split region, but not the "screen" which continues to do what it was doing, in the background if necessary.

  • <screen_escape_key>+x - Locks screen session, but also collapses all regions into a single one on unlocking. (Use normal user passwd.)

Detaching

When you are finished working with your screen windows but you wish for them to continue working without you, you need to "detach" them. One way to do this is to kill the client side of the ssh connection or kill the terminal it is running in. This works because screen is designed to carry on even if inadvertently interrupted. But there is a more polite way to detach. Use <screen_escape_key>+d. Now screen should be running but not interactively in your terminal session. You can log out or close your terminal.

When you want to reconnect to the running screen session, use this command:

$ screen -rd

Now you should be back where you were when you detached. Note that you can also reattach in a new physical location even if you didn’t detach. For example, if you are at your office and working on a screen session and you go to a computer at home after logging in with ssh, you can run screen -rd and the session that was running on your office computer will detach and start running on your home computer. This is extremely handy!

Multiple Attachments

Sometimes I have a complicated situation where I’m reading a long thing on one screen window but I need a different screen window open on a different computer (or different non-contiguous monitor). Screen can re-attach multiple simultaneous times.

:->[host1][~]$ screen -rd
....
:->[host2][~]$ screen -rx

The -x option allows screen sessions that are already attached to be attached again. They then become pretty much exact mirrors and can be operated independently. When both connections share the same screen window like this, both have equal control. This could be useful for having two people edit the exact same thing at the exact same time. This could be useful for teaching or pair programming.

Quitting Screen

To stop using screen completely, log out of all windows and screen will quit. It’s good to do this before turning off machines. Once a machine is turned off, no screen sessions can be reattached.

If your computer hosting the screen session loses power, you’ll have to clean up the screen session. Use screen -wipe to get ride of any dead sessions.

Named Sessions

It is also possible to have multiple screen sessions. I use this so that different projects have their own session saving me from cycling through windows from an irrelevant project. To get different sessions, you need to name them. Just use a -S <name> option when starting screen or reattaching a named session. The name can be pretty much whatever you want.

Note
Looks like Centos7 is overly helpful with this. When you change a session’s name, it gets overwritten immediately upon execution of the next program. I found this to be extremely aggravating. To give an example of the problem, if you set a name like log and then run cat log the name instantly changes to something like user@host:dir. This may be Red Hat’s new overly helpful help conflicting with my longstanding screen configuration. The cure is to find this in /etc/bashrc and comment it out:
/etc/bashrc
# are we an interactive shell?
if [ "$PS1" ]; then
  if [ -z "$PROMPT_COMMAND" ]; then
    case $TERM in
# xed- please stop "helping" me. This messes up status bar name captions.
#   screen*)
#     if [ -e /etc/sysconfig/bash-prompt-screen ]; then
#         PROMPT_COMMAND=/etc/sysconfig/bash-prompt-screen
#     else
#         PROMPT_COMMAND='printf "\033k%s@%s:%s\033\\" "${USER}" "${HOSTNAME%%.*}" "${PWD/#$HOME/~}"'
#     fi
#     ;;

Or, just after the esac add this to undo the damage.

unset PROMPT_COMMAND

Cut and Paste

One nice fancy feature of screen is the ability to "copy" text out of one window and "paste" it into another. To do this start the "copy" mode with <screen_escape_key>+<escape>. Now you can move around with the vi keys (most work, like hjklwb, etc) and probably the arrow keys work too. Go to the beginning of the text you want to copy and press enter. Now move around to the end of the text you want to copy and press enter again. The text is now stored.

Now switch to a different window and do a paste with <screen_escape_key>+] - yes, that’s a right bracket. Your text should come in as if you had just typed it. This feature seems quite overly complicated, but once you get used to it, it is actually quite useful and not really too difficult to use at all. In many cases I find it is quite efficient.

Recursion Of Screen Sessions

It is also possible to have screen sessions within screen sessions. This tends to happen when you’re using screen on a computer from which you log into another computer where you have a screen session. This works just like you’d think it would and is just as complicated as it sounds. It’s best to not do this if you can avoid it, but if you like this sort of thing, you basically need to "escape" the <screen_escape_key> so that it gets to the "inner" session. To do this use <screen_escape_key>+g which sends a screen escape sequence to the "inner" session. Then use one of the commands described above. Like I said, this gets complex and isn’t especially fun to use. But it can be done if needed.

Andrey’s Setup

This is Andrey’s method to get meaningful titles in screen sessions. I’m not sure I like the naming; it seems to put a PWD label on the status bar. I tend to like to see all my options. But I could see this style working for people who don’t do most things from their home directory (which I mostly do). There are some other nice ideas. The colors are very nice. Having the host always shown is less foolish than it may seem if you’re always using screen on remote machines. But I have it in PS1 so it’s redundant. But it’s not a bad concept since PS1 pollutes redundant stuff all over the screen.

screenrc:
escape ``
bindkey `^I other
bindkey `\' windowlist -b
hardstatus alwayslastline
# this works in modern screen
# hardstatus string '%{=b kg}%H%{w}%?%E%{R.}*%:.%?%n%=%h%=%{Y}%l
%{C}%d.%m.%y %0c'
hardstatus string '%{=b kg}%H%{w}.%n%=%h%=%{Y}%l %{C}%d.%m.%y %0c'
# for shift right and left arrows
bindkey ^[[1;2D prev
bindkey ^[[1;2C next
# for ctrl right and left arrows
bindkey ^[[1;5D prev
bindkey ^[[1;5C next
# for alt right and left arrows
bindkey ^[[1;3D prev
bindkey ^[[1;3C next
zombie d@
vbell off
defscrollback 100000
bashrc:
TITLEHOST=`hostname`

short_pwd () {
  local HPWD="$PWD"
  case $HPWD in
    $HOME) HPWD="~";;
    $HOME/*) HPWD="~${HPWD#$HOME}";;
  esac
  echo -n "${HPWD}"
}

case $TERM in
  *term)
     set_window_title () {
        # hardstatus
        printf '\033]0;%s@%s:%s\007\e\\' ${USER} ${TITLEHOST} "`short_pwd`"
     }
     PROMPT_COMMAND='set_window_title';;
  screen)
     set_window_title () {
        SPWD="`short_pwd`"
        # title
        printf '\ek%s@%s:%s\e\\' ${USER} ${TITLEHOST} "${SPWD}"
        # hardstatus
        printf '\033]0;%s@%s:%s\007\e\\' ${USER} ${TITLEHOST} "${SPWD}"
     }
     PROMPT_COMMAND='set_window_title';;
esac

Problems With Screen

Sometimes upgrading while having an active screen session open will cut off the previous sessions. This problem is described nicely with solution here:

Basically you have to downgrade and then rescue your sessions, then upgrade again. Very annoying.

tmux

If for some reason, you don’t love screen, maybe you’ll find what you need with tmux. At the very least, this competing program has a much, much better name. There are some other subtle improvements over screen (when I tried it I was focused on vertical screen splitting) but overall, it’s a very similar kind of tool. Definitely worth checking out if you’re interested in this kind of thing. Many very smart people I know made the switch from screen to tmux.

To restore a detached tmux session: tmux attach.

Most things should be similar to screen. Where different, consult the "KEY BINDINGS" section of man tmux.

Here is a nice description of how to use tmux for people used to screen. Here’s a decent ~/.tmux.conf based on that.

# Chris' Tmux Configuration
# =========================
# Taken mostly from: https://mutelight.org/practical-tmux

# Hopefully this changes the hot key from the default of Ctrl-b to Ctrl-g.
set-option -g prefix C-g

# Make double hitting the hot key do what it does in screen.
bind-key C-g last-window

# Allows for sending commands to nested sessions like screen.
bind-key g send-prefix

# Numbering starts at 1 like the keyboard.
set -g base-index 1

# Eliminate any annoying polling for escape sequences.
set -s escape-time 0

# Hopefully this will help borking after modifying window sizes in a program.
setw -g aggressive-resize on

# Highlight active window.
set-window-option -g window-status-current-bg red

# Set clock mode.
#clock-mode
set -g clock-mode-style 24

# Make space go to the next window. Default is to do "next-layout".
bind-key * next-layout
bind-key Space next-window

# Suppress default of autonaming windows to running processes.
# Use "," to assign your own permanent names.
set-option -g allow-rename off

# Set status bar
set -g status-interval 1
set -g status-bg black
set -g status-fg white
set -g status-left "#(id -un)->"
set -g status-right "%d%b %H:%M:%S%Z #(date -u +%%H%%MU)"

# split panes using | and -
#bind | split-window -h
#bind - split-window -v
#unbind '"'
#unbind %

# Reload config file. Handy for experimenting with it.
bind r source-file ~/.tmux.conf

Other Interesting Software

Mosh

This appears to be an interface for the SSH client focused on interactive use. Its main feature appears to be high latency connections where it will show you what you’ve typed and not necessarily wait for the screen echo that sometimes causes poor SSH connections to produce a "typing blind" effect. Mosh’s Wikipedia entry and official web site.

Byobu

This is a program that provides extra features to programs like screen or tmux. It provides better notifications. Byobu’s Wikipedia entry and official web site.

Xpra

Need screen-like features for graphical things? Xpra is advertised as a "screen for X".