Guidelines

This site is for tech Q&A. Please keep your posts focused on the subject at hand.

Ask one question at a time. Don't conflate multiple problems into a single question.

Make sure to include all relevant information in your posts. Try to avoid linking to external sites.

Links to documentation are fine, but in addition you should also quote the relevant parts in your posts.

0 votes
22 views
22 views

In a background task on host A I want to run rsync between two remote hosts (B and C), so I load the SSH private key into an SSH agent instance on host A

eval "$(ssh-agent)"
ssh-add ~/.ssh/id_ed25519

and then ssh into host B with agent forwarding enabled:

ssh -A -l root B 'rsync -av C:/src/file /dst/'

known_hosts and authorized_keys entries are already created, and the command works fine.

However, since this is supposed to run non-interactively I want to avoid needlessly spawning agent processes. But the ssh client doesn't recognize an agent that was spawned by a different process. How can I (re-)attach to an agent when it's already running?

in Scripting by (330) 2 9

Your answer

Preview

Privacy: Your email address will only be used for sending these notifications.
Anti-spam verification:
By submitting this post you agree to our Terms & Conditions.
To avoid this verification in future, please log in or register.

1 Answer

0 votes
 

The ssh client connects to the agent via a unix-domain socket /tmp/ssh-XXXXX/agent.###, where XXXXX is a random string and ### is the PID of the parent process that created both the socket and the actual agent process. The path to this socket is stored in the environment variable SSH_AUTH_SOCK, which ssh-agent echoes on launch (that's why you eval the output of the command).

To re-attach to an already running agent you need to find its socket in /tmp:

find /tmp/ssh-* -user $(whoami) -name 'agent*'

If more than one agent is running for that user you probably want the most recently launched instance:

find /tmp/ssh-* -user $(whoami) -name 'agent*' -printf '%T@ %p\n' | sort -rn | awk '{print $1; exit}'

Assign the path to the variable SSH_AUTH_SOCK and your ssh client should be able to use the keys in the agent.

SSH_AUTH_SOCK="$(find /tmp/ssh-* ...)"

If some of the sockets may be dysfunctional (e.g. because the agent process was killed with SIGKILL and thus did not properly remove the socket) you could try connecting to the first working agent like this:

while read -r sock; do
  SSH_AUTH_SOCK="$sock"
  ssh-add -l >/dev/null 2>&1
  if [ $? -le 1 ]; then
    break
  fi
  unset SSH_AUTH_SOCK
done < <(find /tmp/ssh-* -user $(whoami) -name 'agent*' -printf '%T@ %p\n' | sort -rn | awk '{print $1}')

The process substitution (< <(...)) is needed here so that the loop is not executed in a subshell, because then changes to SSH_AUTH_SOCK would be discarded when the loop terminates. ssh-add -l (list keys) is used to check the connection to the agent. Return values of 0 and 1 mean that the agent is responding and does or doesn't hold keys respectively. Return values higher than 1 mean there's an issue with connecting to the agent, in which case the variable $SSH_AUTH_SOCK is removed again.

by (330) 2 9
...