[H-GEN] Poor man's Mosh
Russell Stuart
russell-humbug at stuart.id.au
Thu Jul 26 07:48:03 EDT 2012
I finally got around to setting up a personal VPS. (The price and me
being a tight arsed bastard may have had something to do with this. You
can get a VPS with 2 Tb internet, 20 Gb disk, 384Mb RAM for around AUD
$22/yr now.)
While setting it up I got unexpectedly disconnected a couple of times,
and I wasn't running screen. Yeah, laziness I know, but it pissed me
off. Computers are supposed to take care of this sort of thing for you.
I thought about it, and decided it would be nice on logging in I was
automatically dropped into a screen session, and if I was disconnected
the screen session was automatically resumed. But there were other
conditions. I had to be able to use ssh-agent and gpg-agent within the
session, and they had to be persistent as well.
I googled it of course, but there weren't any nice solutions I liked.
All the ones I saw used background agents that saved environment
variables to files. They often failed when the agents session exited
unexpectedly. Some people solved this with symlink tricks, but that
looked fragile to me.
The solution I came up with follows. All modifications are to .profile
(or .bash_profile if you use that instead). At the top of .profile add
these lines, which restart the existing screen session if there is one:
[ -z "${PS1}" ] || {
screen -list | grep --silent 'There is a screen on:' &&
exec screen -D -r || :
}
The "-z ${PS1}" test just ensures the shell is in interactive one.
Next, at the end of .profile add these lines:
[ -z "${PS1}" ] || {
agents=
[ ! -x /usr/bin/ssh-agent ] ||
agents="/usr/bin/ssh-agent"
[ ! -x /usr/bin/gpg-agent ] ||
agents="${agents:+${agents} }/usr/bin/gpg-agent --daemon"
(setsid ${agents} screen -D -m "${SHELL}" -i&) 2>/dev/null
unset agents
while ! screen -list | grep --silent 'There is a screen on:'
do sleep 0.1
done
exec screen -r
}
The "setsid ${agents} screen -D -m" is I guess the magic sauce. The "-D
-m" arguments create a "daemon" part of the screen process, ie SCREEN
process you see if you do a "ps". Running it that way means the agents
persist until the screen session exits. As it is a daemon process you
have to put it in the background, because it is useless until a
foreground screen session connects to it. Because it is put in the
background we have to wait until it starts, which explains the while
loop. Finally the screen -r attaches to the background process we
started.
Finally, we have one more step. .bashrc isn't read by a login shell so
most .profile's read it manually. It is read by a non-login shell. The
end result is if it is done before "screen -D -m" is run then the shells
spawned by it will see it run twice. That can stuff things up, and did
in my case. The solution is to move the lines that read .bashrc to the
end of the .profile. So in my .profile this line, which was near top,
is now the last line:
[ -z "${BASH_VERSION}" -o ! -s "${HOME}/.bashrc" ] ||
. "${HOME}/.bashrc"
Mosh does more than restore sessions of course, and this does none of
those other things. But it does do what I wanted, and it does preserve
all of ssh's functionality, and as far as I can tell that is novel.
More information about the General
mailing list