Magical screens

Hello, I am the internet, and I am a screenoholic. Yes, I love screen. Never is an ounce of work accomplished on the command line without being encapsulated in the warm embrace of my favorite stateful terminal session manager. So much so that I quickly found myself being annoyed of always having to find my screen and never remembering what I named it, if I named it at all. And even worse were the times where I would lose my terminal to find that I was abandoned by my digital soul mate by never calling them before I stared. Oh how the innocence of youth lost so many critical vim undo buffers and ssh connections. I mean seriously, how many times can a guy type `ssh` in a day before hanging his self. 12. It turns out that number is 12. The resolution to my laziness was something of a revolution when I realized all the work I always forgot to do and never wanted to forget again could be easily accomplished automatically, every time I logged in. All hail the .bashrc. In other words, you can harness the power of .bashrc by intelligently invoking screen when you log in as well as giving a few helper functions along the way. Here is what I mean.

Never leave home without it

First, I tend to find myself using screen within a screen; assigning each a different “meta” character. The parent screen `^Pp` and the child `^Aa` (the default). I usually have the parent screen running on my localhost with each of the child screens either on a remote server I am working on or locally, depending on my situation. Knowing this, my first step was to find a canonical name for my parent screen and ensure I was inside of it every time I invoked screen. To do this, I simply overrode `/bin/screen` (may be different on your distribution, find out with `which screen`). I did this with a named function, placed in my .bashrc.

# .bashrc
# …
function screen() {
    if [ "$*" ];
    then
        /usr/bin/screen $*
    else
        if [ "`screen -ls | grep main`" ];
        then
            /usr/bin/screen -e ^Pp -x main
        else
            /usr/bin/screen -e ^Pp -S main
        fi
    fi
}

Now any time I keyed `screen`, I would end up in my parent screen. If it already existed, I reattach. If it doesn’t exist, I create it. Perfect.

The second step is to auto-invoke screen when I first log in to a shell. Always a good idea.

# .bashrc
# …
START_SCREEN=true
# …
if [ $START_SCREEN ];
then
    if [ $TERM != ’screen’ ];
    then
        echo "Not in screen, envoking … "
        screen
    else
        echo "Already in screen"
    fi
fi

This little condition will first test to see if I am already in a screen session. If I am, it will do nothing. If not, it will call my new and overloaded screen function. The combination ensures that I am not only in screen at all times but in the canonical parent screen `main` of the host system I am working on.

With a little sugar comes rotten teeth

Most of my frustrations were resolved once I implemented this. However, I still found myself constantly digging for my children screens from time to time. As is a common attribute with anyone who uses computers for too long, I found myself in the hunt for some long needed sugar functions to help me along the way.

# .bashrc
# …
alias sls=’screen -ls’
alias s="source $HOME/.bashrc"

The first two little buddies I spawned were simple key aliases. `sls` was now mapped to `screen -ls` and nothing more than a character reduction to list the open screens assigned to myself. `s` is a simple way to source the .bashrc of the system to ensure I am already in screen. Now, any time I key `s`, it is like I logged into the terminal again. A nice thing to have if you ever want to leave the screen (and are lazy and don’t feel like typing `screen -x main` again).

function ms() {
    if [ "$1" ];
    then
    next_ms="$1"
    /usr/bin/screen -c /dev/null -e ^Aa -x meta$next_ms
    else
        next_ms="`screen -c /dev/null -ls | grep meta| sed ’s/.*meta//g’| sort -n| tail -1 | perl -ne ‘/(^\d+)/; print $1′`"
    if [ "$next_ms" ];
    then
        next_ms=$(($next_ms+1))
    else
        next_ms="1"
    fi
    /usr/bin/screen -c /dev/null -e ^Aa -S meta$next_ms
    fi
}

This little guy has been the most useful thing I’ve built in all of this. The `ms` function works two ways. Called with no arguments, will build a new child screen (^Aa) named `metan`, where n is the next integer in the list of all “meta” screens. For example:

~$] ms
~$] ms
~$] sls
There are screens on:
        10794.meta1     (Attached)
        10816.meta2     (Attached)
        152.main        (Attached)
3 Sockets in /tmp/uscreens/S-internetsamhard.

A-a-a-a-awesome. No more do I have to key all them pesky characters again. That, and I again have canonical names for my child screens.

The same function, when called with an argument (single parameter of Int type(ish)) will simply try to attach to an existing screen with the name `metan` (where n is the argument passed to the function). Remembering the example from above …

~$] ms
~$] ms
~$] sls
There are screens on:
        10794.meta1     (Attached)
        10816.meta2     (Attached)
        152.main        (Attached)
3 Sockets in /tmp/uscreens/S-internetsamhard.

~$] ms 1

I will find myself behind the curtain of `meta1` child screen under the cloak of the `main` parent screen.

Now, you may not be all that familiar with screen. That is fine. Although if you use Linux, I recommend you learn it. It is arguably one of the biggest reasons I run around like a crazy software evangelist spouting praises of Linux to all developers world-wide. It’s that good. Some would say it is like pooping as it’s such a necessity to life as screen is a necessity of being an effective developer on the popular open source platform. Once you learn it, bend it to your will and make it do what you want. Use these little tricks if you think they will help and if they do – you are welcome. Carry on.

Tags: , ,

Leave a comment