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?


  1. 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]
  1. 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.