How do you get screen to automatically connect to the current ssh-agent when re-attaching to an existing screen?
If you start a screen session while ssh-agent is running (from ssh -A agent forwarding), accessing ssh-agent works fine. However, if you detach from that session, log out, log in again (with ssh-agent forwarding), and re-attach to your screen session, ssh-agent access doesn't work.
How can this be fixed?
-
In your SSH rc script (~/.ssh/rc) you will set up a symbolic link from a canonical location to the "current" SSH_AUTH_SOCK. Here's how I do it in bash (content of ~/.ssh/rc):
#!/bin/bash if test "$SSH_AUTH_SOCK" ; then ln -sf $SSH_AUTH_SOCK ~/.ssh/ssh_auth_sock fi
(and make sure to chmod 750 ~/.ssh/rc
). The "test" is just to prevent an error from displaying if you aren't running ssh-agent (ie you ssh without -A
). The second half of that command sets up a symlink in a canonical location that updates itself to the "real" SSH_AUTH_SOCK
at login time. This is independent of using a shell in ssh or calling a command directly, works also with ssh -t <host> screen -RRD
.
Note: the existence of ~/.ssh/rc
changes the behaviour of sshd. Notably, it will not call xauth. See man sshd for more information, and how to fix this.
Also, you should not use "-v" with ln as soon as it will break rsync-over-ssh with following diagnostics:
$ rsync -n addr.maps.dev.yandex.net: .
protocol version mismatch -- is your shell clean?
(see the rsync man page for an explanation)
rsync error: protocol incompatibility (code 2) at compat.c(173) [Receiver=3.0.7]
-
In your .screenrc, you just need to override the SSH_AUTH_SOCK to the canonical location:
setenv SSH_AUTH_SOCK $HOME/.ssh/ssh_auth_sock
Note that you use setenv no matter what shell you use; I think that setenv is screen syntax, not the shell.
Solution originally adapted from this post, which doesn't work, but has the right idea.
I think this works as a simplification of @sandip-bhattacharya's answer. Put this in your ~/.bashrc
file, and run the export command in any currently running screen sessions.
if [ -S "$SSH_AUTH_SOCK" ] && [ ! -h "$SSH_AUTH_SOCK" ]; then
ln -sf "$SSH_AUTH_SOCK" ~/.ssh/ssh_auth_sock
fi
export SSH_AUTH_SOCK=~/.ssh/ssh_auth_sock
That reads "if $SSH_AUTH_SOCK
is a socket (-S
) and not a symbolic link (! -h
), create a new symbolic link at the known path. In all cases, redefine SSH_AUTH_SOCK
to point to the known path.
The ! -h
avoids creating a circular reference if you run this multiple times.
Also, if you use byobu
, it does this automatically, without needing to edit any config files.
The only bug I've found in this (byobu
has it too) is if you open a second ssh -A
or ForwardAgent
connection it will overwrite the first socket, and if you close the second connection before the first, you will lose your only good socket.
"ssh -t some.machine screen -R" won't run bash and therefore won't run the .bash_profile script where the symlink is created.
You could try: ssh -t some.machine bash -c "screen -R"
(assuming you are using bash as your shell of course)
Edit: That "answer" is actually a comment on the first answer given above :)
Here's the method I use:
SOCK=$(sudo cat /proc/$(pgrep -f "screen -(r|DR)")/environ | tr "\0" "\n" | grep SSH_AUTH_SOCK) ; eval $SOCK ; export SSH_AUTH_SOCK
DISP=$(sudo cat /proc/$(pgrep -f "screen -(r|DR)")/environ | tr "\0" "\n" | grep DISPLAY) ; eval $DISP ; export DISP
I usually set up an alias or a shell function with theses commands:
function ssh-screen-auth() {
SOCK=$(sudo cat /proc/$(pgrep -f "screen -(r|DR)")/environ | tr "\0" "\n" | grep SSH_AUTH_SOCK)
eval $SOCK
export SSH_AUTH_SOCK
DISP=$(sudo cat /proc/$(pgrep -f "screen -(r|DR)")/environ | tr "\0" "\n" | grep DISPLAY)
eval $DISP
export DISPLAY
}
You may have to adapt the regular expression 'screen -(r|DR)' to the exact commands you use to reattach your screen.
- The first line reads the SSH_AUTH_SOCK environment variable in the process space of the "screen -r" command you just typed and updates the value in your current shell.
- The second line is necessary if you use "ssh -X" to forward X11 connections: it updates the DISPLAY variable in the same way.
A caveat with my method: things may go wrong if there is another "screen" command running on the computer.