The screen command

TL;DR

I discovered the screen command recently and it was love at first sight. Before knowing about screen, I was using nohup to leave commands running in the background after closing my SSH connection. The rich set of options that the screen command has, made nohup obsolete for me. In this post I show you my most common use case of screen.

What is screen

screen is a terminal multiplexer. Quoting the man page:

Screen is a full-screen window manager that multiplexes a physical terminal between several processes (typically interactive shells). Each virtual terminal provides the functions of a DEC VT100 terminal and, in addition, several control functions from the ISO 6429 (ECMA 48, ANSI X3.64) and ISO 2022 standards (e.g. insert/delete line and support for multiple character sets). There is a scrollback history buffer for each virtual terminal and a copy-and-paste mechanism that allows moving text regions between windows.

The man page is more than 4000 lines long. And that’s because screen is packed with options.

You can do quite a few things with screen:

  • Open an ssh connection, run a job in the background inside a screen and close the connection. You reconnect back later through ssh and open the screen you left open to see how your command is doing.
  • Open a screen with a shell in it and share it with other people connected to the same machine through ssh.
  • Use it to run several processes in the background using the same SSH connection. I see it as a replacement of the good old jobs, fg, and bg bash builtins.

In this post, I will describe the first use case, which is the most common for me.

Installation

In Linux or Windows 10 with WSL, you can use the package manager of your distribution to install it. In Debian based distributions you can use apt:

> sudo apt install screen

In macOS, the best way to install it is by using homebrew:

> brew install screen

Using screen to run long-running commands

In my current company (Platform161) we run scripts that take several hours to finish. Although we normally use Jenkins to run them, from time to time we need to execute them manually connecting to the machine using ssh.

For those that are not used to work with Linux, if you run a script just by connecting to the machine using ssh and executing it, the script will be run inside your session. If you log out or your internet connection fails, your session will be terminated and your job as well. It’s not enough to run the script in the background since it will be still running in your session.

If you have a backup script that lasts four hours, you don’t want to have it running inside attached to your session. Losing your internet connection 10 seconds before your 3-hout-long job finishes and having to run it again is something extremely infuriating.

We will run the command using screen instead. Let’s connect through ssh to our machine:

Once we logged in, we run the screen command:

and we will be welcomed with a message:

Screen version 4.00.03 (FAU) 23-Oct-06

Copyright (c) 1993-2002 Juergen Weigert, Michael Schroeder
Copyright (c) 1987 Oliver Laumann

This program is free software; you can redistribute it and/or modify it under 
the terms of the GNU General Public License as published by the Free Software 
Foundation; either version 2, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY 
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 
PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with 
this program (see the file COPYING); if not, write to the Free Software Foundation, 
Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

Send bugreports, fixes, enhancements, t-shirts, money, beer & pizza to [email protected]

[Press Space or Return to end.]

After pressing Space or return, screen will run a shell. Inside that shell, we execute our long-running command:

[email protected] > ./long_running_script.sh
The script starts to run...
progress: 1%...2%...

Let’s say the script takes about 3 hours to complete. Since we are running it inside a screen session, we can now detach from the screen by pressing CTRL+A and then d. After doing that, we go back to the shell we opened when we logged in using ssh:

[email protected] > screen
[detached from 2661.pts-0.mycomputer]
[email protected] > _

Now, our script is not attached to our session but to the screen we created. This way, We don’t depend on the internet connection for our script to run!

…and we can just logout and come back later to check the progress. Before logging out from mymachine.com let’s have a look at the list of screens that are open:

[email protected] > screen -ls

There is a screen on:
	2661.pts-0.mycomputer	(12/07/20 10:54:54)	(Detached)
1 Socket in /run/screen/S-alfonso.

[email protected] > _

As you can imagine, we can re-attach later to that screen using the identifier 2661.pts-0.mycomputer. Since this is a command that takes a long time, we will close the ssh connection and check again later.

[email protected] > exit
> _

Re-attaching to the screen

After a couple of hours, we want to check the progress of our long-running script. To do that, let’s connect again to our machine using ssh:

Let’s see if our long-running script is stil there. To do that, we get a list of the available screens:

[email protected] > screen -ls

There is a screen on:
	2661.pts-0.mycomputer	(12/07/20 10:54:54)	(Detached)
1 Socket in /run/screen/S-alfonso.

[email protected] > _

Yes,it’s still there. We re-attach to the screen 2661.pts-0.mycomputer to see how are things going:

[email protected] > screen -r 2661.pts-0.mycomputer

after running this command, the screen will open and we can check the progress

[email protected] > ./long_running_script.sh
The script starts to run...
progress: ...10%...20%...30%...40%...50%...60%..

We can log out and check again later.

Saving output to a file

We can continue to connect through ssh and check the progress of the script. Eventually, the script will finish and the screen -ls command will return that no screens have been found:

[email protected] > screen -ls
No Sockets found in /tmp/uscreens/S-alfonso

After the script finishes running, the screen is closed and the output of our command will be lost. Unfortunately, we don’t know if the command was successful or not. If I want to save the output of the screen and keep it after the script ends, we should use the -L option. We can also use the -Logfile option to select where to store the output:

[email protected] > screen -L -Logfile long_running_script_ouput.txt

With these options, once the script finishes, we can look at the output of the file long_running_script_ouput.txt to see what happened.

Credits

  • My colleague Manuel Molina for introducing me to this command that I didn’t know about. Much more convenient than nohup.