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.
You can use also a “nohup ./run_command &”. It will run like a fake-deamon.
@Krzysiek:
sorry, but I fail to see how’s “nohup” is doing anything similar to screen.
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
@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:
to your ~/.screenrc (on remote host)
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.
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 &