screen is a useful command for running jobs in the background, if you need to disconnect from your terminal session for whatever reason. It’s particularly useful with ssh, where a screen session can persist even if the ssh connection is dropped. But it’s tedious having to log onto a machine and then reconnect to a screen session in a separate step. I wrote a simple bash function that I put in my .bashrc to make this easier

function sshr()
{
    if [ -z $2 ]
    then
        session="default"
    else
        session=$2
    fi

    if [ $session = "ls" ]    
    then
        ssh $1 -t "screen -ls"
    else
        ssh $1 -t "screen -D -R -S "$session
    fi
}

This function performs a few tricks

  • sshr remote will ssh into remote, and then automatically connect to the screen session named default if it exists, and otherwise create a new screen session named default
  • sshr remote sessionname will do the same, but with a session called sessionname
  • sshr remote ls will list the names of all the screen sessions available on remote

The other half of this solution is the .screenrc on the server, for which I have

defscrollback 5000
termcapinfo xterm* ti@:te@
startup_message off
msgwait 0
shell -$SHELL
caption always "%{= mw}Screen session on %H - %S"

This addresses a couple of things

  • The defscrollback and termcapinfo lines make it so that scrolling back in the terminal on Mac OS behaves the same as in a normal terminal session (e.g. mouse wheel scrolls back in the window, rather than scrolling through previous commands)
  • The startup_message and msgwait commands eliminate the ‘New Session’ message that accompanies screen
  • shell -$SHELL treats the session as a login session which means that .bash_profile is sourced on Mac OS just like in a normal terminal
  • caption always means you get a status bar showing you that you’re in a screen session, with the name of the host and the name of the session in it

So all together this ends up being quite a simple solution to managing persistent sessions on a remote machine. You can detach the session as usual with Ctrl+A+D and this will also automatically close the ssh session.

There’s one last convenience though - I’m used to typing exit to end a session, but if I’m in a screen, what I really want to do is detach. This can be achieved by overwriting the exit() command by putting a function in your .bashrc

exit() {
    if [[ -z $STY ]]; then
        builtin exit
    else
        screen -d
    fi
}

If you’re in a screen session, then $STY will not be empty, but otherwise it will be. This exit function will thus detach if screen is running, and otherwise will exit normally. To terminate the screen session, use Ctrl+D.