GNU Screen is a remote terminal multiplexer, described welll elsewhere.
I use it to eliminate the too-many-Terminal-windows problem on my laptop. I also use it to help me achieve some level of continuity on remote hosts, by leaving half-completed sysadmin tasks as-is until hours or days later even if I get interrupted or if the task is really long-running and I need to roam around with my laptop.
Today I decided to invest some time in making my command-line development environment launch with a single script. Here are the details.
Since Screen can preserve context and state only until the host it’s running on is rebooted, I use a text todo list to make sure the big tasks don’t get forgotten or done out of order. On remote hosts I keep this todo list open in a screen by itself, and make other screens for individual steps like “apt-get update” etc. Usually I can go away and come back a couple of days later and pick up where I left off, but if there’s a reboot (which happens occasionally with a VPS I don’t control fully) the todo list is still there as a backup means of remembering where I was.
Locally, though, my todo list is a text file managed in a GUI editor, which lately is TextMate. So all that has to happen throug Screen is the command-line stuff itself.
I used to set things up manually when starting a development session (which could last hours or days, depending on Software Update, travel, etc.). That took a couple of minutes because I had to launch Locomotive, use it to open a Terminal window with the right shell environment, then run screen -e^oo
and manually open a bunch of screens, then manually change their titles, then manually run a few tools and stuff.
Now I have all that automated. There’s a shell script that sets the environment up (it’s just the same script that Locomotive makes, but copied out of /tmp into a stable place, since the contents are stable and don’t need to change for each new session). That calls screen -c jamie_screenrc
whose contents are below (sanitized a bit):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
escape ^oo screen -t 'Rails project root' 0 # I like to have SVN running at the root of the whole project # (including specs, notes, etc. with source code changesets) chdir "../../.." screen -t svn 1 chdir "Site/trunk/myproject" # screen/stuff are separated so that when you exit the stuff-ed program, # you drop back to the bash shell for that screen instead of immediately # exiting that screen. This is useful for "^c, up-arrow, enter" restarting of commands screen -t psql 2 stuff "/opt/local/lib/postgresql82/bin/psql -U myprojectdev\\012" screen -t autotest 3 stuff "autotest\\012" screen -t mongrel 4 stuff "./script/server\\012" screen -t script/console 5 stuff "./script/console\\012" select 0 |
It’s “jamie_screenrc” and not ~/.screenrc so I can develop with the same setup on another host just by checking out the code (including this screenrc file) and running screen there. I don’t want this to be my default screen setup every time I run it anyway.
This is “mildly convenient” to quote Professor Frink. But it’s a big deal to me because now the barrier to starting and stopping work is very, very low; if I have a spare couple of minutes and I’m not set up to develop, I can get going in seconds. Likewise I don’t have to put off other things since I know I can stop and do anything else and get right back into flow very quickly.
The next step will probably be to create a RubyOSA script (or maybe just a shell script, if it’s sufficient) to get Firefox and TextMate and OmniGraffle up and running too with the right documents open just where and how I want them. Then I’d be able to run a single script (or click a single icon, in the Dock perhaps) and wait a minute or less and be completely ready to start coding.
Thanks for sharing this.
I’ve put together a Screen Textmate Bundle to make it easy to configure and connect to per project screen sessions like you mention here
Some times it’s nice to split windows:
you can make it by:
screen -t “Screen 1”
stuff “some command^M”
split
focus
screen -t “Screen 2”
stuff “Some command^M”
split
focus
screen -t “Screen 3”
stuff “Some command^M”
split
focus
screen -t “Screen 4”
stuff “Some command^M”