Take the 2-minute tour ×
Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

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?

share|improve this question

migrated from stackoverflow.com Aug 24 '10 at 16:46

This question came from our site for professional and enthusiast programmers.

10 Answers 10

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 755 ~/.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 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]

2) 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.

share|improve this answer
    
This assumes that you first login, then start screen. Right? –  innaM Mar 24 '09 at 9:13
    
How can it be any other way? How would you start screen without being logged in? –  apinstein Mar 24 '09 at 14:04
    
You're right. The question was phrased in a stupid way. But you do need to login, start up a shell and from there start screen? I often do something like "ssh -t some.machine screen -R". –  innaM Mar 24 '09 at 15:06
1  
Ah ok. Well, I just tried this and it doesn't work (ie ssh-agent is not connected). I guess ssh doesn't set up the appropriate sockets when used in this fashion. Maybe some more argument-foo could clean that up? –  apinstein Mar 25 '09 at 13:46
    
SSH does set up the sockets, it just never starts up the shell. But this tip is so useful that I think I might just change my habits. –  innaM Mar 26 '09 at 21:57

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.

share|improve this answer

"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 :)

share|improve this answer
    
"First answer given above" doesn't mean anything as the answers change order as they are voted on etc. Please include the share link from the answer you are referring to, as that won't change. –  rjmunro Nov 26 '12 at 12:44

I think you need autossh. I've been using it for years now, and combined with screen it makes all my terminal sessions completely portable and transparent. I simply close lappy, move to new location, open lappy and all my screens and nested screens connect automatically. I don't even think about it anymore.

http://www.linux.com/archive/feature/134133

is the basics... I ruby'd up a lil script to automate the process in my .screenrc for a given host. ( also does my ssh forwarding, so in all these different places i can tunnel my connection through my servers )

in the autossh distro there should be a program called rscreen ( and.. there is! )

#!/bin/sh                                                                       
#
# sample script to use autossh to open up a remote screen
# session, or reconnect to an existing one. 
#
# $Id: rscreen,v 1.4 2002/05/07 17:54:13 harding Exp $
#
if [ "X$1" = "X" ]; then
    echo "usage: `basename $0` <host>"
    exit 1
fi

if [ "X$SSH_AUTH_SOCK" = "X" ]; then
    eval `ssh-agent -s`
    ssh-add $HOME/.ssh/id_rsa
fi

#AUTOSSH_POLL=600
#AUTOSSH_PORT=20000
#AUTOSSH_GATETIME=30
#AUTOSSH_LOGFILE=$HOST.log
#AUTOSSH_DEBUG=yes 
#AUTOSSH_PATH=/usr/local/bin/ssh
export AUTOSSH_POLL AUTOSSH_LOGFILE AUTOSSH_DEBUG AUTOSSH_PATH AUTOSSH_GATETIME 

autossh -M 20004 -t $1 "screen -e^Zz -D -R"

This should help with ssh/screen problems

Finally, in order to keep my ssh-agent running , I use keychain, since I am kind of a shell head... I think OSX has something available to keep your agent around ...

share|improve this answer

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.

share|improve this answer
    
-1 for the unnecessary use of sudo. –  0xC0000022L Jan 30 '13 at 14:26

I commonly keep long term (6+ months) sessions running at my workplace on different servers. So repeatedly reattaching and having a viable ssh forwarding agent has been problematic. This is what I set up on my systems:

if [ -z "${STY}" -a -t 0 -a X${USER} = Xmyusername ]; then
    reattach () {
        if [ -n "${SSH_AUTH_SOCK}" ]; then
            ln -snf "${SSH_AUTH_SOCK}" "${HOME}/.ssh/agent-screen"
            SSH_AUTH_SOCK="${HOME}/.ssh/agent-screen" export SSH_AUTH_SOCK
        fi
        exec screen -A -D -RR ${1:+"$@"} ;
    }

    screen -wipe
    echo 'starting screen... (type Cntl-C to abort)'
    sleep 5 && reattach
fi

If I just log in to the remote server without starting/reattaching screen, then there will be two "sockets", one in use by screen and another by the new shell. There shouldn't be two "startup" sessions, but a second session could still be started using reattach -S new; in this situation, the agent would be shared with the ~/.ssh/agent-screen value. To get a working forwarding agent back, then I would detach, log back in. The X${USER} = Xmyusername ensures that the code won't be called through sudo on the same server.

share|improve this answer

I am using a variation of what @apinstein is using for my .bashrc.

case "$TERM" in
    screen)
           export SSH_AUTH_SOCK=~/.ssh/ssh_auth_sock
        ;;
         *)
           if [[ -n "$SSH_AUTH_SOCK" ]]; then
               ln -sf $SSH_AUTH_SOCK ~/.ssh/ssh_auth_sock
           fi
        ;;
esac

This works for all the apps running in my screen session. This would work for all new shells in your screen session. For existing shells you need to run export SSH_AUTH_SOCK=~/.ssh/ssh_auth_sock on the host shell to make it work.

P.S. Sorry for adding this as an independent answer, whereas it just built upon @apinstein's answer. Had to do this as comments in stackoverflow do not support code blocks.

share|improve this answer
    
Why not always symlink and always export? –  Collin Anderson May 15 '12 at 3:15
    
@CollinAnderson Two different behaviours. one within a screen shell, and one within the regular login shell. the environment variable in a login shell is set by ssh and therefore the symlink there. if we do this within a screen session, then we will cause a symlink loop. –  Sandip Bhattacharya Jun 14 '12 at 6:26
    
Ahh, right. You would need to only link if $SSH_AUTH_SOCK is not already a link. See my post superuser.com/a/424588/134212 –  Collin Anderson Jun 18 '12 at 14:31

I tried this simple one liner as suggested on Let's make screen and ssh-agent friends and it works for me.

First Time login to Target.Needs to be done only once.

ssh -o StrictHostKeyChecking=no -C <userid>@<server>

Launch Screen for the First time..Needs to be done only once.

eval `ssh-agent`; /usr/bin/screen -D -R -h 10000
ssh-add

If detached or disconnected, use this command to login subsequently to connect to the exiting screen.

ssh -o StrictHostKeyChecking=no -C -t <userid>@<server> ssh-agent /usr/bin/screen -D -R -h 10000
share|improve this answer

These are all really good answers I do it slightly differently. After I start a new ssh session and reattach screen, I reset the SSH_AUTH_SOCK environment variable based on the contents of the root bash environment. I only require ssh-agent access occasionaly when I am using svn so I just reset the SSH_AUTH_SOCK as required in these shells.

This uses the proc file system so is linux specific. I have only tested this on a headless linux box that is only accessed by me, it might take some tweaking to get it to work on other environments.

To reset SSH_AUTH_SOCK (this could be made an alias).

$ . ~/bin/screen_auth.sh

screen_auth.sh looks like this

# Find the pid of putty's bash shell
tty=`who | awk '/[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/ { print substr($2, 5) }'`
pid=`ps -t $tty | grep bash | awk '{print $1}'`
# Find the SSH_AUTH_SOCK variable in its enviornment
auth_sock=`xargs --null --max-args=1 echo < /proc/$pid/environ | grep SSH_AUTH_SOCK`
eval "export $auth_sock"
share|improve this answer

All solutions above suffer from racing conditions (either in multiple SCREEN sessions or in multiple SSH connections). The only universal solution I can think of is to first push SSH_AUTH_SOCK to SCREEN server process on screen -r and then pull it inside BASH session before each interactive non-builtin command. Unfortunately SCREEN and BASH was designed without awareness of such kind of problems, so it is rather hard to implement properly (though it is never late to post feature requests to both projects). My attempt was made to overcome this issue for BASH sessions which can be found here:

To install:

  1. put both scripts into $HOME/bin, add executable bit;
  2. make sure that $HOME/bin goes before /usr/bin in PATH:

    PATH=$HOME/bin:$PATH

  3. add this to your .bashrc:

    source $HOME/bin/screen-helper setup

Now you can try to create SCREEN session inside SSH session, detach, disconnect, connect and reattach and hopefully ssh-add -l should correctly show your keys.

share|improve this answer
    
Note, that permanent ssh-agent daemon (as suggested here superuser.com/a/412052/376867) do not suffer from racing condition, but suffer from stale keyring. And what is more important, it's not very secure to leave all your keys on remote host along with screen session (or even longer until reboot in case of mentioned post). –  midenok Nov 21 at 15:09

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.