If you’re reading this blog, I probably don’t have to explain why I love GNU screen. I can keep a long-running session going on a server somewhere, and log in and resume my session without losing any state.
I also love X-forwarding. I love being able to log into a remote server and work in a shell there, but still pop up graphical windows (for instance, gitk’s) on my local machine when I need to.
Unfortunately, X-forwarding and screen don’t totally play nice
together. When I start a screen session, I fix a value of
that session, while I can change it in individual shells, having to
remember to do so whenever I open a new ssh session is
irritating. Ideally, of course, we’d have something like
for X11, so that X sessions could live in a virtual X server on your
machine, which gets forward to a real X server on demand. I hear that
NX does something like this, or even just a VNC window.
But in practice, I find I tend to care less about having my X windows
long running. If I’m popping up a
gitk to look at some commits, I
will probably just close it, and don’t care about it being there
tomorrow. Really, I just want a way for
DISPLAY to magically track
the latest X-forwared
DISPLAY, so that in any window in my screen
session, I can run
display or such, and it will magically
pop up in the appropriate X server.
So, last week, I finally wrote a script that lets you do just
that. Instead of futzing with
DISPLAY, it works by proxying between
two values of
DISPLAY. You initially open a screen with some dummy
“virtual” DISPLAY that nothing is connected to – I tend to use
env DISPLAY=:15 screen
Then, whenever you log in to the machine with X forwarding (or log in locally), you simply from:
proxy-display starts listening for connections on display
proxying traffic between there and whatever
$DISPLAY was when it was
launched. In addition, it makes the appropriate
xauth incants so
that everything just works. It also looks for any old instances of
itself listening on
:15, and kills them off, to prevent leaking
processes. Any connections to old instances of itself, however, that
had accepted connections and were now proxying data, are left alone –
so existing X windows stay open on whatever display they’re on.
So, now you can just add to your dotfiles something along the lines of
if [ "$DISPLAY" ]; then proxy-display :15 fi
And whenever you
ssh into your remote machine and resume your screen
sessions, you can run X programs and they’ll magically pop up in your
most recent X-forwarded connection.
(The script, available on github, is currently a disgusting mess of shell that uses
socat to do the actual proxying, and mucks around in
/proc/net to find old instances of itself to kill. But it works wonderfully, so I haven’t bothered to clean it up)