How to check if ssh-agent is already running in ba

2020-02-10 11:36发布

问题:

I have a sample sh script on my Linux environment, which basically run's the ssh-agent for the current shell, adds a key to it and runs two git commands:

#!/bin/bash
eval "$(ssh-agent -s)"
ssh-add /home/duvdevan/.ssh/id_rsa

git -C /var/www/duvdevan/ reset --hard origin/master
git -C /var/www/duvdevan/ pull origin master

Script actually works fine, but every time I run it I get a new process so I think it might become a performance issue and I might end up having useless processes out there.

An example of the output:

Agent pid 12109
Identity added: /home/duvdevan/.ssh/custom_rsa (rsa w/o comment)

Also, along with all this, is it possible to find an existing ssh-agent process and add my keys into it?

回答1:

No, really, how to check if ssh-agent is already running in bash?

Answers so far don't appear to answer the original question...

Here's what works for me:

if ps -p $SSH_AGENT_PID > /dev/null
then
   echo "ssh-agent is already running"
   # Do something knowing the pid exists, i.e. the process with $PID is running
else
eval `ssh-agent -s`
fi

This was taken from: https://stackoverflow.com/a/15774758



回答2:

Also, along with all this, is it possible to find an existing ssh-agent process and add my keys into it?

Yes. We can store the connection info in a file:

# Ensure agent is running
ssh-add -l &>/dev/null
if [ "$?" == 2 ]; then
    # Could not open a connection to your authentication agent.

    # Load stored agent connection info.
    test -r ~/.ssh-agent && \
        eval "$(<~/.ssh-agent)" >/dev/null

    ssh-add -l &>/dev/null
    if [ "$?" == 2 ]; then
        # Start agent and store agent connection info.
        (umask 066; ssh-agent > ~/.ssh-agent)
        eval "$(<~/.ssh-agent)" >/dev/null
    fi
fi

# Load identities
ssh-add -l &>/dev/null
if [ "$?" == 1 ]; then
    # The agent has no identities.
    # Time to add one.
    ssh-add -t 4h
fi

This code is from pitfalls of ssh agents which describes both the pitfalls of what you're currently doing, of this approach, and how you should use ssh-ident to do this for you.


If you only want to run ssh-agent if it's not running and do nothing otherwise:

if [ $(ps ax | grep [s]sh-agent | wc -l) -gt 0 ] ; then
    echo "ssh-agent is already running"
else
    eval $(ssh-agent -s)
    if [ "$(ssh-add -l)" == "The agent has no identities." ] ; then
        ssh-add ~/.ssh/id_rsa
    fi

    # Don't leave extra agents around: kill it on exit. You may not want this part.
    trap "ssh-agent -k" exit
fi

However, this doesn't ensure ssh-agent will be accessible (just because it's running doesn't mean we have $SSH_AGENT_PID for ssh-add to connect to).



回答3:

If you want it to be killed right after the script exits, you can just add this after the eval line:

trap "kill $SSH_AGENT_PID" exit

Or:

trap "ssh-agent -k" exit

$SSH_AGENT_PID gets set in the eval of ssh-agent -s.

You should be able to find running ssh-agents by scanning through /tmp/ssh-* and reconstruct the SSH_AGENT variables from it (SSH_AUTH_SOCK and SSH_AGENT_PID).



回答4:

ps -p $SSH_AGENT_PID > /dev/null || eval "$(ssh-agent -s)"

Single line command. Run for the first time will start ssh-agent. Run for the second time will not start the ssh-agent. Simple and Elegant Mate !!!



回答5:

The accepted answer did not work for me under Ubuntu 14.04.

The test to check if the ssh-agent is running I have to use is:

[[ ! -z ${SSH_AGENT_PID+x} ]]

And I am starting the ssh-agent with:

exec ssh-agent bash

Otherwise the SSH_AGENT_PID is not set.

The following seems to work under both Ubuntu 14.04 and 18.04.

#!/bin/bash
sshkey=id_rsa
# Check ssh-agent
if [[ ! -z ${SSH_AGENT_PID+x} ]]
then
    echo "[OK] ssh-agent is already running with pid: "${SSH_AGENT_PID}
else
    echo "Starting new ssh-agent..."
    `exec ssh-agent bash`
    echo "Started agent with pid: "${SSH_AGENT_PID}
fi
# Check ssh-key
if [[ $(ssh-add -L | grep ${sshkey} | wc -l) -gt 0 ]]
then
    echo "[OK] SSH key already added to ssh-agent"
else
    echo "Need to add SSH key to ssh-agent..."
    # This should prompt for your passphrase
    ssh-add ~/.ssh/${sshkey}
fi


回答6:

Using $SSH_AGENT_PID can only test the ssh-agent but miss identities when it is not yet added

$ eval `ssh-agent`
Agent pid 9906
$ echo $SSH_AGENT_PID
9906
$ ssh-add -l
The agent has no identities.

So it would be save to check it with ssh-add -l with an expect script like example below:

$ eval `ssh-agent -k`
Agent pid 9906 killed
$ ssh-add -l
Could not open a connection to your authentication agent.
$ ssh-add -l &>/dev/null
$ [[ "$?" == 2 ]] && eval `ssh-agent`
Agent pid 9547
$ ssh-add -l &>/dev/null
$ [[ "$?" == 1 ]] && expect $HOME/.ssh/agent
spawn ssh-add /home/user/.ssh/id_rsa
Enter passphrase for /home/user/.ssh/id_rsa: 
Identity added: /home/user/.ssh/id_rsa (/home/user/.ssh/id_rsa)
$ ssh-add -l
4096 SHA256:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX /home/user/.ssh/id_rsa (RSA)

So when both ssh-agent and ssh-add -l are put to run on a bash script:

#!/bin/bash
ssh-add -l &>/dev/null
[[ "$?" == 2 ]] && eval `ssh-agent`
ssh-add -l &>/dev/null
[[ "$?" == 1 ]] && expect $HOME/.ssh/agent

then it would always check and assuring that the connection is running:

$ ssh-add -l
4096 SHA256:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX /home/user/.ssh/id_rsa (RSA)

You can also emulate the repeating of commands on above script with do while



回答7:

You can modify line #1 to:

PID_SSH_AGENT=`eval ssh-agent -s | grep -Po "(?<=pid\ ).*(?=\;)"`

And then at the end of the script you can do:

kill -9 $PID_SSH_AGENT


回答8:

Thanks to all the answers here. I've used this thread a few times over the years to tweak my approach. Wanted to share my current ssh-agent.sh checker/launcher script that works for me on Linux and OSX.

The following block is my $HOME/.bash.d/ssh-agent.sh

function check_ssh_agent() {
  if [ -f $HOME/.ssh-agent ]; then
    source $HOME/.ssh-agent > /dev/null
  else
    # no agent file
    return 1
  fi

  if [[ ${OSTYPE//[0-9.]/} == 'darwin' ]]; then
    ps -p $SSH_AGENT_PID > /dev/null  
    # gotcha: does not verify the PID is actually an ssh-agent
    # just that the PID is running
    return $?
  fi

  if [ -d /proc/$SSH_AGENT_PID/ ]; then
    # verify PID dir is actually an agent
    grep ssh-agent /proc/$SSH_AGENT_PID/cmdline  > /dev/null  2> /dev/null; 
    if [ $? -eq 0 ]; then
      # yep - that is an agent
      return 0
    else
      # nope - that is something else reusing the PID
      return 1
    fi
  else
    # agent PID dir does not exist - dead agent
    return 1
  fi 
}

function launch_ssh_agent() {
  ssh-agent > $HOME/.ssh-agent
  source $HOME/.ssh-agent
  # load up all the pub keys
  for I in $HOME/.ssh/*.pub ; do
    echo adding ${I/.pub/}
    ssh-add ${I/.pub/}
  done
}

check_ssh_agent
if [ $? -eq 1 ];then
  launch_ssh_agent
fi

I launch the above from my .bashrc using:

if [ -d $HOME/.bash.d ]; then
  for I in $HOME/.bash.d/*.sh; do
    source $I  
  done
fi

Hope this helps others get up and going quickly.

Created a public gist if you want to hack/improve this with me: https://gist.github.com/dayne/a97a258b487ed4d5e9777b61917f0a72