Screen: running long commands on your server without fear of disconnection

Who hasn't started a big rsync or a database import over SSH, only to see the connection drop (or close their laptop out of habit) and lose everything along the way? That's exactly the problem screen solves: a tool as old as vim and Linux, installable everywhere, and a real night-saver.

The idea: screen creates a virtual terminal that lives on the server, independently of your SSH connection. You can "detach" from the session (on purpose, or because the wifi gave up), the command keeps running, and you "reattach" later, from home or anywhere else, finding everything just as you left it.

1. Installation

There's a good chance it's already there; let's check with the whereis screen command

kgaut@garage:~$ whereis screen
screen: /usr/bin/screen /usr/share/screen  ...

in that case it's installed, you can skip to step 2

if the command answers this: 

kgaut@garage:~$ whereis screen        
screen:

then you need to install it:

# Debian / Ubuntu
sudo apt install screen

# Fedora / Alma Linux / Rocky Linux
sudo dnf install screen

2. The AlmaLinux 10 trap

On a fresh AlmaLinux 10 install, dnf install screen goes perfectly well… and the first launch fails:

$ screen -S test
Directory '/run/screen' must have mode 777.

The natural reflex is to go look at that directory and set it to 777, since that's what the command is asking for. It's also the first answer you'll find pretty much everywhere. Except that the error message points to the wrong cause: /run/screen matches exactly what the package declares. The problem lies elsewhere, on the binary, and as long as you're looking at the directory, you can't see it.

The right diagnosis: rpm -V

Rather than inspecting permissions without knowing what they should be, you might as well ask RPM to compare what's on disk with what the package declares:

$ rpm -V screen
.M....G..    /usr/bin/screen

Each output line flags a file that has diverged (no output at all = everything matches). Here M stands for mode and G for group: /usr/bin/screen has neither the expected permissions nor the expected group. The verdict is immediate, and above all it requires no prior knowledge: you don't need to know what you should have seen, RPM knows it for you.

To see the gap, you can ask the package for the state it declares, then compare it with what's on disk:

$ rpm -qlv screen | grep bin/screen
-rwxr-sr-x    1 root    screen    480680 ... /usr/bin/screen     <- what the package expects

$ ls -l /usr/bin/screen
-rwxr-xr-x. 1 root root 480680  5 janv. 2026 /usr/bin/screen     <- what is actually there

The s instead of the x in the group permissions is the setgid bit. That's what's missing, along with the screen group.

The explanation

The package creates a screen system group and installs the binary as root:screen with the setgid bit. That's what allows screen to write to a shared socket directory, hence the /usr/lib/tmpfiles.d/screen.conf file shipped with the package, which contains d /run/screen 0775 root screen. Without its setgid bit, screen loses that right and switches to its other operating mode: the one where, having no particular privilege, it requires a world-writable 0777 directory in order to create its subdirectory there. Hence the message.

As for why the bit disappears during installation, Red Hat bug #2385964, still open, attributes it to an ordering problem in the package: the screen group would be created after the file permissions are set, so RPM silently fails to assign a group that doesn't exist yet. I'm reporting this mechanism as it's described there, without having verified it myself. What is certain (and enough to fix it) is that the binary is not in the state the package declares.

The fix

First, make sure no screen session is running. Careful: as long as the bug is there, screen -ls fails with the same error and won't tell you anything. So ps is the one to ask:

ps -ef | grep [s]creen

Then a single command is enough. The screen group now exists on the system: reinstalling the package sets the permissions correctly.

sudo dnf reinstall screen

You can also fix it by hand:

sudo chown root:screen /usr/bin/screen
sudo chmod 2755 /usr/bin/screen

…but prefer reinstall, and not just because it's shorter: it restores everything the package declares, including what you haven't noticed. If the late group creation made the assignment fail on one file, nothing guarantees it didn't fail elsewhere too. Here rpm -V only reported a single line, so the damage was limited, but you only find that out afterwards.

Nothing else is needed: no reconnection, no reboot, no systemd-tmpfiles --create. And above all, no need to add yourself to the screen group: the setgid binary carries the right, not the user. It's a natural mistake when you see a dedicated group show up, but it's useless.

Checking that it's fixed

$ ls -l /usr/bin/screen
-rwxr-sr-x. 1 root screen 480680  5 janv. 2026 /usr/bin/screen   # the "s" is back

$ rpm -V screen
                                                                 # no more output
$ screen -S test                                                 # starts, and screen -ls lists it

All three together, not just the last one: a screen that starts could do so for another reason. The socket is created in /run/screen/S-yourlogin, with mode 0700 and owned by you.

So what about chmod 777?

It's the first answer you find online, and it's wrong on two counts. First, /run is a tmpfs: the change is lost at the next reboot. Second, it amounts to doing exactly what the error message asks, that is, deliberately switching screen to its unprivileged mode, with a socket directory writable by every account on the machine, when the real problem is a missing bit on a binary that can be fixed with one command.

One last option, which is legitimate if you're not an administrator of the machine: tell screen to store its sockets in your home rather than in /run, by adding this to your .bashrc:

mkdir -p ~/.screen && chmod 700 ~/.screen
export SCREENDIR="$HOME/.screen"

Careful: the variable must be exported in all your shells; a screen -ls run without it won't see any of your sessions anymore.

Will it come back?

No. The screen group now exists on the system, so future package updates will apply the permissions correctly. There's nothing to keep an eye on.

Observed on AlmaLinux 10.2 with screen-5.0.1-6.el10_2.x86_64. The mechanism described suggests that Rocky Linux 10 and RHEL 10 are affected in the same way, but I haven't verified it on those distributions.

3. The basics: create, detach, come back

Create a named session with -S (get into the habit right away, don't do what I did... it saves you from juggling numeric identifiers):

screen -S backup

You're now in a regular shell, but one that lives in the "backup" session. Run your command, then detach with the shortcut Ctrl+a then d (d for detach). You're back in your normal shell, with the [detached] message, and the command keeps running in the background.

All of screen's shortcuts work this way: Ctrl+a is the prefix, followed by a key.

To list running sessions:

$ screen -ls
There is a screen on:
	12345.backup	(Detached)
1 Socket in /run/screen/S-kgaut.

(note that it's -ls and not ls; that one caught me out a lot at first.)

And to reattach:

screen -r backup

If there's only one session, a plain screen -r is enough. When the command is done and you no longer need the session, an exit (or Ctrl+d) inside the session closes it cleanly.

Classic case: your connection dropped and the session is still marked (Attached) even though you're no longer on it. The -d flag forces a detach before reattaching:

screen -rd backup

4. Real-world examples on a web server

Importing a large database dump

The typical case where a disconnection hurts: an import that takes 40 minutes and, interrupted halfway, leaves the database in a shaky state.

screen -S import-db
zcat dump-prod.sql.gz | mysql -u monuser -p mabase
# Ctrl+a d, and off to grab a coffee

Same logic for a somewhat long application migration (a drush updb on a big Drupal site, a Solr reindex, a gitlab-backup restore...): anything that takes more than a few minutes deserves a screen.

Renewing a certificate or updating the system

True story: last Thursday I lost two hours because I started a kernel update on my GitLab server without using screen, and my connection dropped at the worst possible moment... (OK, I had started the update from my phone, which isn't necessarily the smartest move...)

You won't catch me doing that again 

screen -S maj
sudo dnf upgrade

5. Real-world examples on a home server

Moving your media library

Copying a few hundred GB from a NAS or an old server takes hours. Inside a screen, you can close the laptop and go to bed:

screen -S rsync-mediatheque
rsync -avh --progress ancien-serveur:/media/mediatheque/ /media/mediatheque/

The next day, screen -r rsync-mediatheque and you check the result, including everything --progress printed during the night.

Testing a service before turning it into a proper container

Before writing the final compose.yml for a service, I sometimes run it "by hand" to watch its logs live and play with its configuration. A screen is perfect for that: the service stays reachable even if I disconnect, without having to bring out systemd for a simple test.

6. Several windows in one session

I rarely use this; out of laziness about learning the shortcuts, I'm more used to running two screen sessions. But it's screen's second string to its bow: a session can contain several "windows", each with its own shell. Typically: the long command in one window, the logs in another.

  • Ctrl+a c: create a new window
  • Ctrl+a n / Ctrl+a p: next / previous window
  • Ctrl+a 0 to 9: go to window #X
  • Ctrl+a ": list of windows, navigable with the arrow keys

Example: one window with the database import, a second one with a tail -f on the site's logs, and you switch between them with Ctrl+a n.

7. Scrolling back through history

In a screen, the mouse wheel doesn't scroll back through the terminal history. You need to enter "copy mode" with Ctrl+a [: you then navigate with the arrow keys or PgUp/PgDn, and exit with Esc. It's confusing at first, but it quickly becomes second nature.

8. Sharing a session

Another thing I should use more: two people logged into the same server can attach to the same session with screen -x backup. Each one sees what the other types, in real time. Very handy for debugging together on a server, or for showing someone a procedure without screen sharing.

Command cheat sheet

screen -S nom        # create a named session
Ctrl+a d             # detach
screen -ls           # list sessions
screen -r nom        # reattach
screen -rd nom       # reattach, forcing a detach
Ctrl+a c             # new window
Ctrl+a n / p         # next / previous window
Ctrl+a "             # list of windows
Ctrl+a [             # scroll back through history (Esc to exit)
screen -x nom        # shared session
screen -dmS nom cmd  # detached session running a command

Wrapping up

There's a more modern alternative, tmux, which is more powerful (splitting the screen into panes, more flexible configuration) and which many people prefer today. But screen has the advantage of being installed, or installable, absolutely everywhere, including on old or minimal machines. Same logic as vim: it was there 20 years ago, and it will still be there in 20 years.

Written by Kevin Gautreau — freelance PHP/Drupal developer & trainer in Auvergne, France. get in touch

Comments (0)