2011-08-09

Starting GNU Screen Automatically at System Startup

Perhaps this is so intuitive the instructions are just easily inferred from existing documentation. Perhaps this is so useless that no one before me has ever wondered how to accomplish it. In any case, I was having problems finding out how to get GNU screen to start automatically when my machine boots. People have documented online that it's quite easy to include a call to screen in their login scripts: SSH into your system and screen will automatically fire up if it's not running, or reattach to an existing screen session if you've logged in before. This is a nice feature, but I don't want to have to login first.

Why? Because I keep a persistent screen around tailored with information I care about, tailing logs and such, and I want that information to begin accumulating as soon as the machine comes up and not based on my schedule or memory to make sure I login after every time the machine restarts.

If I go on vacation and there's a power outage, I think that technology in the 21st century has evolved to the point where my machine is smart enough to automatically go through all the steps I'd ask it to do without me, were I there and if I gave it my username and password. I want screen to be an always-up system service that I happen to use by connecting to it when I can. Finding out how to set this up was surprisingly tricky.

I started by reviewing as much documentation as I could find about pty-4.0 and ptyget-0.50, two pseudo-terminal packages developed by D. J. Bernstein in the 1990s. Neither of these packages is really complete. ptyget-0.50 replaced pty-4.0, but never left alpha testing status and isn't even mentioned on the author's website beyond a link to sign up to the mailing list. The archive for this mailing list totals 40 messages last I checked, the last message being about 3 years ago.

Reading up on ptyget led me to An introduction to session management, a paper penned by Bernstein that outlines the workings of a vaporware package called "sess" for reliable and secure user session management.

Reliable and secure user session management is exactly what I want.

I opted to use GNU screen as the basis for my session manager. It's a great utility for running and maintaining multiple concurrent windows and keeping them all persistent in the event of a network disconnect. As I mentioned, I use GNU screen daily for watching logs, reading mail, and doing all sorts of network stuff, both random and specific. GNU screen has several options for allowing you to start and resume existing instances, but there wasn't any obvious way to hook GNU screen into my system's startup scripts such that it would always be there for me.

I use Bernstein's daemontools to run local and network services on my OpenBSD system, so I knew I was going to have to figure out how to stitch the supervise program and GNU screen together. I went through lots of different permutations of the service trying to start screen inside of a ptyget pseudo-terminal. This had no positive results.

Instead, I eventually trial-and-errored my way to a functional setup that, though not perfect, functions how I need it to function well enough to use.

The permanent screen service I've configured uses this as its ./run file:

#!/bin/sh
exec 2>&1
exec envdir ./env sh -c '
  exec setuidgid $USER screen -U -m -A -D -S mail -c /service/screen/screenrc
'

./env contains values for HOME PATH SHELL and USER. I haven't found a way to pull this information from ~/.profile and not treat the service shell like an interactive login. Whenever I login, I have a little mail-checking application tell me how much mail I have and what kind it is. I don't want my screen session service logs to fill up with lines saying "No new messages" or, worse, my actual mail statistics.

The name of my user account is in the $USER variable of course. I could remove the need to run screen inside of an extra /bin/sh if I hard-coded it into the script.

This simple script works because of what the flags "-m -D -S" do in screen. I found that -S was really important and I couldn't make "-m -D" work as I'd anticipated without it. /service/screen/screenrc is the full path to this specific screen's config file. Basically, I can do this:

chdir

# syntax: screen -t label order command
screen -t qmail-send 0
stuff "tail -f /var/log/qmail/current | tai64nlocal \012"

screen -t qmail-smtpd 1
stuff "tail -f /var/log/qmail/smtpd/current | tai64nlocal \012"

screen -t dnscache 2
stuff "tail -f /service/dnscache/log/main/current | tai64nlocal \012"

screen -t irssi 3
stuff "irssi \012"

screen -t scratch 4

The contents of a .screenrc file are pretty well documented. In this case, when screen is started by supervise, it will open 5 windows automatically: two for tailing qmail logs, one for tailing a dnscache log, one for launching irrsi, and one will just be totally blank when I first connect. The "\012" character is a newline. It is necessary to tell GNU screen to not just paste the given stuff text into the appropriate window, but to press the enter key afterwards.

There's more to this, of course. The service should have logging configured, and there are several improvements I'm going to make to this setup as I figure out how. This simple set of configs though is more than I've been able to find after digging into the problem and should get you on your way.

1 comment:

Anonymous said...

Why does an OpenBSD user use screen (over the built-in tmux)?