Tips N’ Tricks – using GNU Screen as shell

I'm quite often doing stuff on remote machines, and quite frequently I start some long-running job, when I remember that I didn't ran it via screen – so it will break, if my network connection will die.

Is there any sane way to start screen automatically? YES.

In manual to screen, you can find that you can simply put screen as your shell in /etc/passwd. Which is true, but it has problems. Namely:

  • You no longer can scp anything to the machine using this account
  • You no longer can su – name to this account

Why? It looks like this:

=$ scp test.file test@localhost:
Must be connected to a terminal.

And via su:

=# su - test
Cannot open your terminal '/dev/pts/9' - please check.

Which kinda sucks.

So I started digging for better option.

Finally I added these lines to the end of my ~/.bash_profile (not bashrc!):

if [[ ( -z "$STY" ) && ( ! -z "$SSH_CONNECTION" ) ]]
then
      exec screen -R -D -S shell
fi

Which kinda-works, but the “kinda" is actually problematic:

  • it will not work with multiplexed ssh connections
  • if I will run ssh to the same account from single place, it will close earlier connection
  • when starting first shell (i.e. not re-attaching) it shows annoying notification, which cannot be disabled (i.e. I can disable all notifications, but then I will also hide all other. And it makes shell startup delayed.

After some more tinkering I finally found nearly perfect solution:

if [[ ( -z "$STY" ) && ( ! -z "$SSH_CONNECTION" ) ]]
then   
        screen -S shell -x 2> /dev/null || screen -S shell
        logout
fi

Which is actually pretty cool – “su –" works (doesn't start screen), scp works, I can use multiplexing, and previous sessions are not detached on new connect (they all share the same screen session).

The only problem with this approach is that it leaves behind one obsolete bash process:

test@h3po4:~$ ps uxf
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
test     21927  0.0  0.0  85424  2016 ?        S    13:48   0:00 sshd: test@pts/7 
test     21928  0.0  0.0  19288  1932 pts/7    Ss+  13:48   0:00  \_ -bash
test     21932  0.0  0.0  25168  1276 pts/7    S+   13:48   0:00      \_ screen -S shell
test     21933  0.0  0.0  25728  1756 ?        Ss   13:48   0:00          \_ SCREEN -S shell
test     21934  0.0  0.0  19412  2192 pts/10   Ss   13:48   0:00              \_ -bash
test     22034  0.0  0.0  15252  1160 pts/10   R+   13:50   0:00                  \_ ps uxf

i.e. bash with PID 21928 is obsolete, and could simply not exist, but it's not possible to get rid of it. Or is it?

Let's add some more logic:

if [[ ( -z "$STY" ) && ( ! -z "$SSH_CONNECTION" ) ]]
then
        COUNT="$( LC_ALL=C LANG=C screen -S shell -ls | grep -cE '[^[:space:]]' )"
        if [[ "$COUNT" -lt 3 ]]
        then    
                exec screen -S shell
        fi      
        exec screen -S shell -xRR
fi

With this, after logging to the account I get only these processes:

test@h3po4:~$ ps uxf
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
test     23080  0.0  0.0  85424  1920 ?        S    14:00   0:00 sshd: test@pts/10
test     23081  1.0  0.0  25168  1272 pts/10   Ss+  14:00   0:00  \_ screen -S shell
test     23088  0.0  0.0  25596  1696 ?        Ss   14:00   0:00      \_ SCREEN -S shell
test     23089  0.0  0.0  19416  2164 pts/12   Ss   14:00   0:00          \_ -bash
test     23092  0.0  0.0  15252  1160 pts/12   R+   14:00   0:00              \_ ps uxf

All other stuff works well. There is only one possible issue – what will happen in case of dead screen sessions – well, I didn't put any code for handling it in the bash_profile, as – if something like this would happen – I can always “ssh -t user@server bash" – thus bypassing .bash_profile, and fix the problem manually.

6 thoughts on “Tips N’ Tricks – using GNU Screen as shell”

  1. You can use also a “nohup ./run_command &”. It will run like a fake-deamon.

  2. @Krzysiek:
    sorry, but I fail to see how’s “nohup” is doing anything similar to screen.

  3. it is very nice, but with your code, i can not open to ssh connection to one server, on both connections i have this same data, when i enter something in one window it’s “reenter” in second: http://qkpic.com/2e115

  4. @acid:
    screen is running, and it’s running the same screen on both ssh connections. just open more windows in screen (ctrl-a c), and use different windows for different connections.

    you might want to add:

    backtick 1 99999 99999 id -u -n
    caption always "%{Gb}%1`@%H > %{wb}%?%-Lw%?%{Rb}[%n%f %t]%{wb}%?%+Lw%?%=%{Cb}%l %{Mb}%c:%s "

    to your ~/.screenrc (on remote host)

  5. I can recommend byobu, a front end for screen. Its possible to configure byoby to start on login. Your sessions are preserved across ssh sessions.

  6. here is what I use on Ubuntu:

    in $HOME/bin/rscreen:

    #!/bin/bash

    if [ -z “$1” ]; then
    echo “Usage: $(basename $0) [user@]host”
    exit 0
    fi

    USER=${1%@*}
    [ “$USER” == “$1″ ] && USER=root
    HOST=${1#*@}

    LABEL=${2:-$HOST}

    CMD=”screen -A -d -R -U /bin/bash -l”
    if [ “$HOST” != “local” ]; then
    CMD=”ssh -t -X $USER@$HOST $CMD”
    fi
    gnome-terminal –maximize -t $LABEL -x $CMD &

Comments are closed.