How do you get screen to automatically connect to the current ssh-agent when re-attaching to an existing screen?

50

38

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?

apinstein

Posted 2009-03-23T18:56:05.167

Reputation:

Answers

41

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.

apinstein

Posted 2009-03-23T18:56:05.167

Reputation: 1 101

This assumes that you first login, then start screen. Right? – innaM – 2009-03-24T09:13:45.120

1How can it be any other way? How would you start screen without being logged in? – None – 2009-03-24T14:04:30.927

1You'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 – 2009-03-24T15:06:57.657

1Ah 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? – None – 2009-03-25T13:46:47.360

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 – 2009-03-26T21:57:01.433

Concerning the ln -v cs rsync issue, adding a check for interactivity, e.g. $PS1 != "", may help. Your answer will of course only work as long as one doesn't establish multiple connections with ssh-agent instances that are different on purpose... – Tobias Kienzler – 2012-10-22T09:01:09.800

25

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.

Collin Anderson

Posted 2009-03-23T18:56:05.167

Reputation: 169

2This works for tmux as well. – Dag Høidahl – 2016-09-09T07:16:52.610

Works great, but breaks when using remotely mounted home folders. In that case, use ~/.ssh/ssh_auth_sock_"$(hostname)" for your symlink. It will keep separate auth sockets for each host. – Kibber – 2018-07-06T15:06:16.287

4

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

blop

Posted 2009-03-23T18:56:05.167

Reputation:

"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 – 2012-11-26T12:44:29.383

3

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

chiggsy

Posted 2009-03-23T18:56:05.167

Reputation: 472

2

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.

Farzy

Posted 2009-03-23T18:56:05.167

Reputation: 29

-1 for the unnecessary use of sudo. – 0xC0000022L – 2013-01-30T14:26:48.787

1

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.

Arcege

Posted 2009-03-23T18:56:05.167

Reputation: 1 883

1

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.

Sandip Bhattacharya

Posted 2009-03-23T18:56:05.167

Reputation: 271

Why not always symlink and always export? – Collin Anderson – 2012-05-15T03:15:11.177

@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 – 2012-06-14T06:26:19.853

Ahh, right. You would need to only link if $SSH_AUTH_SOCK is not already a link. See my post http://superuser.com/a/424588/134212

– Collin Anderson – 2012-06-18T14:31:28.030

0

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"

iain

Posted 2009-03-23T18:56:05.167

Reputation: 191

0

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

Sharjeel

Posted 2009-03-23T18:56:05.167

Reputation: 213

0

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.

midenok

Posted 2009-03-23T18:56:05.167

Reputation: 190

Note, that permanent ssh-agent daemon (as suggested here http://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 – 2014-11-21T15:09:19.573

0

I skimmed through other answers and couldn't find mine. Here's what I use. Create a file ~/.screenrc-wrapper with the following contents:

escape ^xx
bindkey ^Ad detach

And add this to your ~/.bashrc (or ~/.zshrc if you use that):

  if echo $TERM | grep -v 'screen' && ! screen -x -SU wrapper; then
      if echo $TERM | grep -v 'screen' && ! screen -x -SU main; then
      screen -c ~/.screenrc-wrapper -SU wrapper ssh-agent screen -SU main
      fi
  fi

This way you'd use two screen sessions - one is "wrapper" and one is the inner one. This will keep the latter alive even when you log out and it will keep having ssh-agent on. Another nice feature is that it will remember your window setup - if you use split windows, it might be very handy.

You can find this feature in context in my dotfiles.

d33tah

Posted 2009-03-23T18:56:05.167

Reputation: 1 014