August 30th, 2010 by depesz | Tags: , , , , | 6 comments »
Did it help? If yes - maybe you can help me?

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.

  1. 6 comments

  2. # Krzysiek
    Aug 31, 2010

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

  3. Aug 31, 2010

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

  4. # acid
    Aug 31, 2010

    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

  5. Aug 31, 2010

    @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)

  6. # sunew
    Sep 10, 2010

    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.

  7. # cellux
    Oct 27, 2011

    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 &

Leave a comment