Can I start a GUI application from inside GNU Screen?

You can't. Well... At least, you have to set DISPLAY before invoking it.

When I disconnect and reconnect, will it still be there?

No, of course not!

Right, but... wrong. This post describes how to answer "Yes" to the two questions above.

Introduction

If you run long tasks or work with multiple shells on a remote Linux/Unix server, GNU Screen is your friend. It is a virtual terminal multiplexer that will continue running all your shells and all the processes started by them even if you disconnect, and of course allow reconnecting later. Unfortunately, this tool has one drawback: All subprocesses will inherit the environment at the time Screen was first started, even after disconnecting and reconnecting. This means that you cannot automatically launch applications with a GUI in a reconnected Screen session, even if you enable X forwarding with ssh -X: The DISPLAY environment will probably be wrong. Of course you can note the value of DISPLAY right after ssh -X, and start your GUI applications using DISPLAY=:### my-gui-app -- but that's very inconvenient. In addition, even if Screen survives a disconnect, the GUI application won't -- the target display must run at least as long as the application runs, or the application will terminate. Another option is to log in separately using ssh -X for each GUI application and start it outside Screen -- this is inconvenient if a GUI application needs to be started from a specific directory (say, a version control front-end or a visual diff tool).

That's where xpra comes to play -- "Screen for X". It provides and maintains an Xvfb-based virtual framebuffer on the server to which applications can connect, this framebuffer is intended to run indefinitely. Xpra clients can then connect to the xpra server instance and display the contents of the virtual framebuffer on the local display, forward input events, ... -- in other words, let the user interact with the application as if it runs on the local machine. Once disconnected, another connection can be made to the same xpra session -- this is transparent to GUI applications using xpra as display, these applications simply continue running. The value of DISPLAY (and its lifetime) remains unchanged for the entire duration of the xpra session.

This post describes the installation of xpra and GNU Screen on a Debian/Ubuntu Linux server and client, with the following features:

  • Login on the server via SSH by default reattaches to a running Screen. If no Screen is running, a new instance is started and xpra is set up in that instance.

  • Applications with a GUI can be started from within Screen, and keep running even if the client disconnects. Several GUI applications can be run in parallel. They are shown on the client's display by issuing a special command once.

  • Multi-user support.

It is assumed that usernames match on both local and remote systems. If this is not the case, some tweaking might be necessary -- YMMV. Some knowledge of Screen is assumed, too.

Tested with xpra 0.9.6 (server, Debian Squeeze) and xpra 0.9.8 (client, Ubuntu 13.04). In principle, the configuration should also work on other Linux flavors.

Installation

Server and client

  • Add the winswitch repository according to the instructions. (This used to be a bad idea, but should now work fine.)

  • Install xpra: sudo apt-get install xpra.

Server only

  • Install GNU Screen: sudo apt-get install screen

Configuration

Server: Auto-start Screen

The script below needs to be added to or sourced from your ~/.profile. It is a modified version of this script. The main changes are:

  • If no running Screen is found, the DISPLAY environment variable is set to the first free display with number larger than 5555. (This is to avoid confusion with system display numbers.) Free display numbers are discovered by looking into /tmp/.X11-unix/ for files named X*. The DISPLAY environment variable will be inherited by the screen instance which is started next, and thus also by all processes started inside this Screen. (There is a race condition here: Two simultaneous logins from the same user will set DISPLAY to identical values, and one instance of xpra will fail to attach to that display.)

  • If the DISPLAY environment variable is already set, the auto-start feature is disabled. This happens, for instance, if you use ssh -X to login to the remote machine.

  • The window title is set to $HOSTNAME.

Test this by sshing into your remote machine with and without the -X switch. In the latter case, Screen should be started automatically (if no instance was running previously), in the former case you'll be getting a simple prompt. If you cannot distinguish the former from the latter, you can customize the appearance of Screen (e.g., add a permanently visible status line) by editing your ~/.screenrc file. There are plenty of examples on the web. (You'll need to edit that file anyway, see below.) Close the auto-started Screen, this will also close your SSH connection.

Server: Patch xpra configuration

The following is necessary if your home on the server runs on a file system that does not support sockets. Add this one setting to your ~/.xpra/xpra.conf configuration file (not /etc/xpra/xpra.conf, thanks antoine!). Replace the string username by your own user name on the local machine.

Once variable expansion is implemented, you can indeed also edit /etc/xpra/xpra.conf and define a generic per-user socket-dir.

Server: Patch Screen configuration

The following lines need to be added to your ~/.screenrc on the server. (Create the file if it does not exist.) It will start an instance of xpra that uses the preconfigured DISPLAY in Screen window 9. (Even if xpra were able to choose the DISPLAY itself, we could not let it do so because screen, the parent process, needs to know the value of DISPLAY.)

Test this by sshing into the remote machine again. Now, window 9 should contain logging information from xpra.

Client: Connecting to the server

The final piece is the command that needs to be run on the client to connect to a remote xpra session:

This will attach to your (only) xpra session running on the server, and works even with a changed socket dir thanks to the changed xpra configuration. This command must keep running as long as you want to use GUI applications on the remote machine.

Test this by starting a GUI application from inside the remote Screen.

Client: Connector script

We can wrap this with a script that will also set the window title and accept the host name or address as parameter:

Add or link this script to some location in your PATH.

Maintenance

Watch out for lonely Xvfb processes using pstree $USER, sometimes killing xpra doesn't kill the associated virtual framebuffer.

Further steps

It's only a bit of configuration, but I understand that coupling xpra with an auto-started Screen might not suit everyone's needs. Packaging this into a small application that works similarly to keychain (a script that determines the current state, starts xpra as daemon if necessary and creates sourceable files which are then sourced from .bashrc) would be a logical next step.

Finding files in subdirectories

How to locate your files no matter what the subdirectory is Continue reading

From zero to tested in five minutes

Published on April 14, 2015

Using .gitattributes to avoid merge conflicts

Published on February 25, 2014