320

I have a site as a remote Git repo pulling from Bitbucket.com using an SSH alias. I can manually start the ssh-agent on my server but I have to do this every time I login via SSH.

I manually start the ssh-agent:

eval ssh-agent $SHELL

Then I add the agent:

ssh-add ~/.ssh/bitbucket_id

Then it shows up when I do:

ssh-add -l

And I'm good to go. Is there any way to automate this process so I don't have to do it every time I login? The server is running RedHat 6.2 (Santiago).

random
  • 9,324
  • 10
  • 63
  • 77
Pathsofdesign
  • 3,768
  • 5
  • 15
  • 25
  • 2
    Anything you want to do every time you login should in .profile (terminal logins) or .xinitrc (for GUI logins). – Barmar Sep 18 '13 at 18:50
  • 1
    Ah! I was using .bash_profile... What's the difference between .profile and .bash_profile? – Pathsofdesign Sep 18 '13 at 18:54
  • @Barmar - It looks like .profile is the correct file name. However it doesn't look like any of the commands after the 'eval ssh-agent $SHELL' is being ran. Any suggestions? – Pathsofdesign Sep 18 '13 at 19:06
  • 1
    Not sure why you're running the command that way in the first place. `ssh-agent ` runs `` as a subprocess of `ssh-agent`, so you're starting a new shell. I think you want `eval ssh-agent`. – Barmar Sep 18 '13 at 20:53
  • 11
    `.bash_profile` is specific to bash, `.profile` is generic to all POSIX shells. `bash` will look first for `.bash_profile`, then default to `.profile`. – Barmar Sep 18 '13 at 20:54
  • 5
    The correct way to spawn `ssh-agent` for a "standard" (POSIX-compatible) shell is `eval $(ssh-agent -s)`. Note also that you have to make sure you properly get rid of the agent when you log out, so it's also advisable to put `trap 'kill $SSH_AGENT_PID' EXIT` in your `.profile` after the line which starts the agent. – kostix Sep 19 '13 at 10:16
  • @Barmar what is wrong with running ssh-agent without eval? I don't understand your comment. – Calicoder May 30 '17 at 04:37
  • 1
    @Calicoder The `ssh-agent` command prints environment variable assignments. If you don't use `eval`, they just get printed on the screen, they don't get executed, so the variables don't get set. – Barmar May 30 '17 at 16:12
  • Stack Overflow is a site for programming and development questions. This question appears to be off-topic because it is not about programming or development. See [What topics can I ask about here](http://stackoverflow.com/help/on-topic) in the Help Center. Perhaps [Super User](http://superuser.com/) or [Unix & Linux Stack Exchange](http://unix.stackexchange.com/) would be a better place to ask. – jww Oct 02 '17 at 08:03
  • @Pathsofdesign `ssh-add` says when run without arguments, it adds the files ~/.ssh/id_rsa, ~/.ssh/id_dsa, ~/.ssh/id_ecdsa, ~/.ssh/id_ed25519 and ~/.ssh/identity. so `/usr/bin/ssh-add` won't add other private key files together. When using a custom file, I have to modify this script. Am I correct? – niaomingjian Jan 18 '18 at 02:11
  • 3
    I’m voting to close this question because it is better suited to the Unix SE site where there's a better answer: https://unix.stackexchange.com/questions/90853/how-can-i-run-ssh-add-automatically-without-password-prompt – icc97 Jan 14 '21 at 11:41

12 Answers12

421

Please go through this article. You may find this very useful:

http://mah.everybody.org/docs/ssh

Just in case the above link vanishes some day, I am capturing the main piece of the solution below:

This solution from Joseph M. Reagle by way of Daniel Starin:

Add this following to your .bash_profile

SSH_ENV="$HOME/.ssh/agent-environment"

function start_agent {
    echo "Initialising new SSH agent..."
    /usr/bin/ssh-agent | sed 's/^echo/#echo/' > "${SSH_ENV}"
    echo succeeded
    chmod 600 "${SSH_ENV}"
    . "${SSH_ENV}" > /dev/null
    /usr/bin/ssh-add;
}

# Source SSH settings, if applicable

if [ -f "${SSH_ENV}" ]; then
    . "${SSH_ENV}" > /dev/null
    #ps ${SSH_AGENT_PID} doesn't work under cywgin
    ps -ef | grep ${SSH_AGENT_PID} | grep ssh-agent$ > /dev/null || {
        start_agent;
    }
else
    start_agent;
fi

This version is especially nice since it will see if you've already started ssh-agent and, if it can't find it, will start it up and store the settings so that they'll be usable the next time you start up a shell.

Michael Renner
  • 2,848
  • 3
  • 18
  • 16
Litmus
  • 9,164
  • 5
  • 26
  • 43
  • does it need full restart and where it eats '~/.ssh/config ? – gaussblurinc Jul 15 '14 at 12:49
  • 11
    Machine restart is not necessary. You can just reload `.bash_profile` using `source ~/.bash_profile` in your current shell session. Machine restart will also work because that will load the new config anyway. – Litmus Jul 16 '14 at 08:49
  • 13
    Use ``SSH_ENV="$HOME/.ssh/env"`` (i.e. just not /environment) Why? sshd uses ~/.ssh/environment (see man page : PermitUserEnvironment). Github also recommend this in their solution - https://help.github.com/articles/working-with-ssh-key-passphrases#auto-launching-ssh-agent-on-msysgit – Andrew Murphy Sep 13 '14 at 08:22
  • I call `ssh-agent` and `ssh-add` in my `.bachrc` but the already running sshd daemon does not use the newly executed `ssh-agent`. If I log in a few times into my remote server, I'll have a few `ssh-agent`s running but none of them would work. I still would need to log in with a username/pass. After I log in, I can stop sshd and start sshd myself (i.e. `/etc/sbin/sshd -d`), which uses `ssh-agent` but it is not what I want to do. I want `ssh-agent` be loaded automatically when I boot the system even if nobody logs in. I don't have Xserver on my remote system to start ssh-agent for me. – Always Asking Jan 20 '15 at 23:02
  • 7
    This script worked for me when I put it in my ~/.bashrc file (not my ~/.profile or ~/.bash_profile). The first time I open a local console it prompts for the passphrase, everything works from that point on without further prompting. Cheers. – andrew pate Feb 19 '15 at 11:38
  • 3
    Adding the `ssh-agent` start command in .bashrc will make `scp` command not work. – Dzanvu Mar 18 '15 at 08:14
  • 1
    I removed the `> /dev/null` pieces since I wanted to be notified of errors. You might want to add `-q` to that last `grep`, though, since if you remove `> /dev/null` it will still output the grepped line. – jamadagni Nov 20 '15 at 03:18
  • @Dzanvu I presume you mean `scp` does not work even though you add `ssh-agent` to `.bashrc`. I confirm that. Not sure how to fix that though. – jamadagni Dec 06 '15 at 09:53
  • Finally, if you are using a graphical askpass program (possibly using your DE's password manager), you might have to use `ssh-add – jamadagni Dec 06 '15 at 09:55
  • You're a saint! Thank you!!. I closed all my clients and ssh-agent does not ask passphrase!! – JRichardsz Jul 04 '16 at 20:44
  • 6
    Still annoying... you have to do this every time you log in... even if you don't use ssh. Need to make this fire off every time ssh is called... and ideally, you should be able to configure which hosts cause which keys to load. – Erik Aronesty Jul 22 '16 at 15:30
  • 2
    Creating the .ssh/environment file then chmod 600 leaves it open a a brief time period. It's much more secure to use umask:```OLD_UMASK=$(umask 077); /usr/bin/ssh-agent | sed 's/^echo/#echo/' > "${SSH_ENV}"; umask ${OLD_UMASK}``` – dlundquist Feb 21 '17 at 20:36
  • This answer is a near-perfect, cross platform solution to make sure ssh-agent just works. But please, clarify in the answer that the file to use is *either* `.bash_profile` or `.bashrc`. My advice is to use whichever one exists already on your OS. For me, it was `.bash_profile` on OS X and `.bashrc` on Ubuntu 16.04. Other than that, this answer works unchanged in both cases. – tobias.mcnulty Mar 08 '17 at 17:15
  • @tobias.mcnulty, I put this in my .bashrc and ensure it is only run for my interactive shells (like `if [[ "$-" == *i* ]] ; then STUFF; fi`). Placing in .bashrc causes the ssh-agent setup commands to be executed for EVERY shell which might seem overkill, but simplifies your issues with how interactive command shells are started and how environment is passed. Examples take up more space than comment allows. When in .bash_profile, commands are ONLY run for "login shells" (bash -l) which may not be how a shell is started (e.g., vim sub-shell). – PatS Oct 16 '17 at 23:33
  • @PatS Perhaps OS X terminals are login shells, then, because `.bash_profile` works on OS X, while `.bashrc` does not... – tobias.mcnulty Oct 18 '17 at 01:21
  • @tobias.mcnulty Thanks for the info. I found http://www.joshstaiger.org/archives/2005/07/bash_profile_vs.html which states this and recommends adding `if [ -f ~/.bashrc ]; then source ~/.bashrc fi` to your .bash_profile so you can just maintain one file (.bashrc). – PatS Oct 18 '17 at 18:23
  • Like what others here are saying, adding the solution in `~/.bashrc` file works. Thank you!!! – Eje Jun 24 '19 at 22:38
  • this somehow broke my svn – Rho Phi Aug 04 '20 at 23:46
  • Just a quick note that if you want to load an SSH key other than the default, change the "/usr/bin/ssh-add;" line to "/usr/bin/ssh-add ;" – Jason Oct 03 '20 at 15:20
133

On Arch Linux, the following works really great (should work on all systemd-based distros):

Create a systemd user service, by putting the following to ~/.config/systemd/user/ssh-agent.service:

[Unit]
Description=SSH key agent

[Service]
Type=simple
Environment=SSH_AUTH_SOCK=%t/ssh-agent.socket
ExecStart=/usr/bin/ssh-agent -D -a $SSH_AUTH_SOCK

[Install]
WantedBy=default.target

Setup shell to have an environment variable for the socket (.bash_profile, .zshrc, ...):

export SSH_AUTH_SOCK="$XDG_RUNTIME_DIR/ssh-agent.socket"

Enable the service, so it'll be started automatically on login, and start it:

systemctl --user enable ssh-agent
systemctl --user start ssh-agent

Add the following configuration setting to your local ssh config file ~/.ssh/config (this works since SSH 7.2):

AddKeysToAgent  yes

This will instruct the ssh client to always add the key to a running agent, so there's no need to ssh-add it beforehand.

spheenik
  • 1,449
  • 1
  • 10
  • 12
  • 4
    I found this comment while trying to do this in Ubuntu. It seems to play much more nicely with the built in systems than hacking something into the startup scripts, at least given my knowledge of how the system should work. – xiterion Jul 25 '17 at 14:55
  • I tried this on Ubuntu 16.04 LTS. Unfortunately, every shell process wants its individual `ssh-agent` process. Perhaps I lack knowledge even after reading the docs. – Daisuke Aramaki Sep 26 '18 at 12:36
  • You can also use *Type=simple*. https://wiki.archlinux.org/index.php/SSH_keys#Start_ssh-agent_with_systemd_user – Hans-J. Schmid Jan 09 '19 at 15:46
  • 2
    so is this solution basically installing/configuring a systemd service (but only for the user)? – Trevor Boyd Smith Jan 10 '19 at 15:35
  • This will not set the `SSH_AGENT_PID` environment variable, though :( – MrMeszaros Mar 06 '19 at 10:28
  • I like this approach because it makes deployment with Salt dead simple. Just drop the files and start the service (as opposed to keeping separate `bashrc`s for different kinds of machines) – nomen Mar 23 '19 at 14:19
  • @spheenik, can you clarify whether `AddKeysToAgent yes` goes in your local ssh config or the remote? – Ben Nov 27 '19 at 14:35
  • This is such a nice clean solution, worked for me on Fedora 31. – kurczynski Feb 28 '20 at 17:32
  • for some reason this is not working for me, do I have generate a key afterwards? this doesn't work for existing keys? – Ahmed Mohamedeen Mar 26 '20 at 08:47
  • This is definitely the way to go but the automatic start on login doesn't work for me. I log into another machine via ssh, on which I set up the service to connect to git without password prompt. Is there some special magic needed for ssh-based logins on the machine where I want to run the service? – tifrel Aug 15 '20 at 21:35
  • 2
    I like this answer because it uses the infrastructure specifically designed for running daemons (systemd) and not shell-script hacks with variables. – PeterT Nov 04 '20 at 23:23
  • why is the step `export SSH_AUTH_SOCK` needed? for me it works without it. – morrow Dec 21 '20 at 18:21
  • It is needed so that commands issued in the terminal (for example `ssd-add`) can find the agent. If they can on your machine without configuration, it seems it found the agent in another way. – spheenik Dec 22 '20 at 12:51
  • I think the solution is the best one. And it just has to be adopted by distros. see https://stackoverflow.com/questions/2419566/best-way-to-use-multiple-ssh-private-keys-on-one-client if you want several keys to be tried automatically when connect to git – dev_null Dec 29 '20 at 11:04
  • For getting the `$SSH_AUTH_TOKEN` to be readable by programs started without reading `.zshrc` (such as VSCode), see this question: https://unix.stackexchange.com/q/637788/297140 – James Wright Mar 06 '21 at 17:15
107

Old question, but I did come across a similar situation. Don't think the above answer fully achieves what is needed. The missing piece is keychain; install it if it isn't already.

sudo apt-get install keychain

Then add the following line to your ~/.bashrc

eval $(keychain --eval id_rsa)

This will start the ssh-agent if it isn't running, connect to it if it is, load the ssh-agent environment variables into your shell, and load your ssh key.

Change id_rsa to whichever private key in ~/.ssh you want to load.

Some useful options for keychain:

  • -q Quiet mode
  • --noask Don't ask for the password upon start, but on demand when ssh key is actually used.

Reference

https://unix.stackexchange.com/questions/90853/how-can-i-run-ssh-add-automatically-without-password-prompt

Christopher Oezbek
  • 17,629
  • 3
  • 48
  • 71
xelber
  • 3,239
  • 2
  • 18
  • 29
  • 1
    keychain does not work for me according to the instructions given. I added to .bash_profile and ssh still asks for password every time. i tried it multiple times in same shell. no dice. going back to basic ssh-agent approach – StephenBoesch Jul 23 '14 at 20:12
  • 3
    This is the correct and simple solution. If you do not want to see the log when keychain command is executed, you can add `-q` option for quiet mode. More info about Keychain: https://www.funtoo.org/Keychain – Diki Ananta Jan 26 '18 at 00:45
  • 7
    Thx, this is by far the most elegant solution. – greenspand Aug 03 '18 at 18:01
  • 1
    @James The `$(`....`)` *is* better than using backticks! See https://stackoverflow.com/q/9449778/4805858 ... – SlySven Jun 12 '20 at 04:26
  • Works great! FWIW, I also appended `2> /dev/null` inside `$(...)` to suppress reported information from keychain. – Sorawee Porncharoenwase Sep 27 '20 at 06:33
  • 1
    The [linked reference](https://unix.stackexchange.com/questions/90853/how-can-i-run-ssh-add-automatically-without-password-prompt) gives by far the most complete answer to this question. It details all the possible approaches to this and their tradeoffs. – icc97 Jan 14 '21 at 11:38
  • This is the the most elegant and efficient solution and works without issues in a virtual linux environment on chromebook (arm build) too. Specifically it works with git and visual studio code. – squarespiral Jan 24 '21 at 09:41
  • 1
    This solution as it stands currently "eval $(keychain --eval id_rsa)" didn't work for me until I added "--agents ssh " parameter to keychain, as it is recommended in the linked solution. – il--ya Jan 24 '21 at 19:59
  • How should I modify this to add ALL my private keys at once? --eval ~/.ssh/* fails because it tries to everything, but files like *.pub or known_hosts or config aren't private keys, so it fails. – a3y3 Mar 20 '21 at 15:46
  • This works perfectly for Ubuntu 20.04.2. For all the Oh My ZSH users, instead of updating `~/.bashrc`, update `~/.zshrc` instead – 2Toad May 29 '21 at 20:35
38

The accepted solution have following drawbacks:

  • it is complicated to maintain;
  • it evaluates storage file which may lead to errors or security breach;
  • it starts agent but doesn't stop it which is close equivalent to leaving the key in ignition.

If your keys do not require to type password, I suggest following solution. Add the following to your .bash_profile very end (edit key list to your needs):

exec ssh-agent $BASH -s 10<&0 << EOF
    ssh-add ~/.ssh/your_key1.rsa \
            ~/.ssh/your_key2.rsa &> /dev/null
    exec $BASH <&10-
EOF

It have following advantages:

  • much simpler solution;
  • agent session ends when bash session ends.

It have possible disadvantages:

  • interactive ssh-add command will influence only one session, which is in fact an issue only in very untypical circumstances;
  • unusable if typing password is required;
  • started shell becomes non-login (which doesn't influence anything AFAIK).

Note that several ssh-agent processes is not a disadvantage, because they don't take more memory or CPU time.

midenok
  • 761
  • 8
  • 12
  • I've got SSH keys in a directory outside of $HOME in Windows 10, using Git Bash. Changing the path to the RSA was all I needed to do to get this working. TYVM! – kayleeFrye_onDeck Mar 18 '16 at 04:58
  • 12
    I would argue that **"If your keys do not require to type password"** is close equivalent to leaving the key in ignition. – Bruno Bronosky Oct 03 '16 at 22:51
  • At least, it is on your own host, not somewhere on the network. – midenok Oct 04 '16 at 07:23
  • 1
    "I would argue that "If your keys do not require to type password" is close equivalent to leaving the key in ignition. " – Scott Prive May 10 '17 at 14:37
  • 3
    Don't do that. Passwordless keys are a bad practice. – user48678 Sep 28 '17 at 01:58
  • There are people who live in the world of theft and treachery and there are people who live in the world of friendship. It's your choice of course: do you want to spend time on passwords, locks, certificates, fingerprints, etc. If you are afraid of course use "best practices" and remember and type long and hard meaningless strings. But there more interesting things to do. Btw, I'm not saying you don't have to lock anything. I'm just saying that Goble, Micro$oft, Fapple, etc. call paranoid lifestyle on you, but it's always your choice to select level of security according to stakes involved. – midenok Nov 17 '20 at 00:57
  • @midenok Hello after adding this on my .bash_profile and loging out i cant access my server from my terminal. i tried severel times but i can access my server right now what can i do now? it gives me this error **ec2-user@1.2.3.4.5: Permission denied (publickey,gssapi-keyex,gssapi-with-mic).** – MD Nasirul Islam May 11 '21 at 00:32
32

Add this to your ~/.bashrc, then logout and back in to take effect.

if [ ! -S ~/.ssh/ssh_auth_sock ]; then
  eval `ssh-agent`
  ln -sf "$SSH_AUTH_SOCK" ~/.ssh/ssh_auth_sock
fi
export SSH_AUTH_SOCK=~/.ssh/ssh_auth_sock
ssh-add -l > /dev/null || ssh-add

This should only prompt for a password the first time you login after each reboot. It will keep reusing the same ssh-agent as long as it stays running.

Collin Anderson
  • 12,371
  • 6
  • 55
  • 50
  • What would we use instead if we had multiple keys and they weren't named `~/.ssh/id_rsa`? It seems that the `ssh-add` part of your answer expects default file names for the keys. – Gabriel Staples Jan 24 '18 at 00:23
  • Yup. I believe you can just add the file names to to the very end of the last line if needed – Collin Anderson Jan 24 '18 at 14:51
  • But you still cant automize a script do pull git stuff for example without entering password manually? How to avoid that? – trainoasis Aug 09 '19 at 13:33
8

So I used to use the approaches described above, but I kind of prefer the agent to die when my last bash session ends. This is a bit longer than the other solutions, but its my preferred approach. The basic idea is that the first bash session starts the ssh-agent. Then each additional bash session checks for the config file (~/.ssh/.agent_env). If that is there and there is a session running then source the environment and create a hardlink to the socket file in /tmp (needs to be on the same filesystem as the original socket file). As bash sessions shut down each deletes its own hardlink. The last session to close will find that the hardlinks have 2 links (the hardlink and the original), removal of the processes own socket and killing of the process will result in 0, leaving a clean environment after the last bash session closes.

# Start ssh-agent to keep you logged in with keys, use `ssh-add` to log in
agent=`pgrep ssh-agent -u $USER` # get only your agents           
if [[ "$agent" == "" || ! -e ~/.ssh/.agent_env ]]; then
    # if no agents or environment file is missing create a new one
    # remove old agents / environment variable files
    kill $agent running
    rm ~/.ssh/.agent_env 

    # restart
    eval `ssh-agent` 
    echo 'export SSH_AUTH_SOCK'=$SSH_AUTH_SOCK >> ~/.ssh/.agent_env             
    echo 'export SSH_AGENT_PID'=$SSH_AGENT_PID >> ~/.ssh/.agent_env             
fi

# create our own hardlink to the socket (with random name)           
source ~/.ssh/.agent_env                                                    
MYSOCK=/tmp/ssh_agent.${RANDOM}.sock                                        
ln -T $SSH_AUTH_SOCK $MYSOCK                                                
export SSH_AUTH_SOCK=$MYSOCK                                                

end_agent()                                                                     
{
    # if we are the last holder of a hardlink, then kill the agent
    nhard=`ls -l $SSH_AUTH_SOCK | awk '{print $2}'`                             
    if [[ "$nhard" -eq 2 ]]; then                                               
        rm ~/.ssh/.agent_env                                                    
        ssh-agent -k                                                            
    fi                                                                          
    rm $SSH_AUTH_SOCK                                                           
}                                                                               
trap end_agent EXIT                                                             
set +x              
Micah
  • 452
  • 4
  • 8
7

Just to add yet another solution :P, I went with a combination of @spheenik and @collin-anderson 's solutions.

 # Ensure that we have an ssh config with AddKeysToAgent set to true
 if [ ! -f ~/.ssh/config ] || ! cat ~/.ssh/config | grep AddKeysToAgent | grep yes > /dev/null; then
     echo "AddKeysToAgent  yes" >> ~/.ssh/config
 fi
 # Ensure a ssh-agent is running so you only have to enter keys once
 if [ ! -S ~/.ssh/ssh_auth_sock ]; then
   eval `ssh-agent`
   ln -sf "$SSH_AUTH_SOCK" ~/.ssh/ssh_auth_sock
 fi
 export SSH_AUTH_SOCK=~/.ssh/ssh_auth_sock

Could be a little more elegant but its simple and readable. This solution:

  • ensures AddKeysToAgent yes is in your ssh config so keys will be automatically added upon use
  • doesn't prompt you to enter any passphrases at login (again, one-time passphrase entering occurs on first use)
  • silently starts an ssh-agent if it has not already started one

Comments welcome :)

Keego
  • 2,949
  • 1
  • 14
  • 6
6

Tried couple solutions from many sources but all seemed like too much trouble. Finally I found the easiest one :)

If you're not yet familiar with zsh and oh-my-zsh then install it. You will love it :)

Then edit .zshrc

vim ~/.zshrc

find plugins section and update it to use ssh-agent like so:

plugins=(ssh-agent git)

And that's all! You'll have ssh-agent up and running every time you start your shell

Sharak
  • 589
  • 4
  • 12
4

Users of the fish shell can use this script to do the same thing.

# content has to be in .config/fish/config.fish
# if it does not exist, create the file
setenv SSH_ENV $HOME/.ssh/environment

function start_agent                                                                                                                                                                    
    echo "Initializing new SSH agent ..."
    ssh-agent -c | sed 's/^echo/#echo/' > $SSH_ENV
    echo "succeeded"
    chmod 600 $SSH_ENV 
    . $SSH_ENV > /dev/null
    ssh-add
end

function test_identities                                                                                                                                                                
    ssh-add -l | grep "The agent has no identities" > /dev/null
    if [ $status -eq 0 ]
        ssh-add
        if [ $status -eq 2 ]
            start_agent
        end
    end
end

if [ -n "$SSH_AGENT_PID" ] 
    ps -ef | grep $SSH_AGENT_PID | grep ssh-agent > /dev/null
    if [ $status -eq 0 ]
        test_identities
    end  
else
    if [ -f $SSH_ENV ]
        . $SSH_ENV > /dev/null
    end  
    ps -ef | grep $SSH_AGENT_PID | grep -v grep | grep ssh-agent > /dev/null
    if [ $status -eq 0 ]
        test_identities
    else 
        start_agent
    end  
end
hoijui
  • 3,076
  • 1
  • 28
  • 34
Daniel Gerber
  • 2,572
  • 2
  • 23
  • 30
3

I solved it by adding this to the /etc/profile - system wide (or to user local .profile, or .bash_profile):

# SSH-AGENT 
#!/usr/bin/env bash
SERVICE='ssh-agent'
WHOAMI=`whoami |awk '{print $1}'`

if pgrep -u $WHOAMI $SERVICE >/dev/null
then
    echo $SERVICE running.
else
    echo $SERVICE not running.
    echo starting
    ssh-agent > ~/.ssh/agent_env
fi
. ~/.ssh/agent_env

This starts a new ssh-agent if not running for the current user, or re-sets the ssh-agent env parameter if running.

rh0dium
  • 6,317
  • 3
  • 42
  • 72
TheFrog
  • 31
  • 1
2

I like your answers a lot. It made working from cygwin / linux hosts a lot easier. I combined start and end functions to make it secure.

SSH_ENV="$HOME/.ssh/.agent_env"

function start_agent {
    echo "Initialising new SSH agent..."

    eval `/usr/bin/ssh-agent`
    echo 'export SSH_AUTH_SOCK'=$SSH_AUTH_SOCK >> ${SSH_ENV}
    echo 'export SSH_AGENT_PID'=$SSH_AGENT_PID >> ${SSH_ENV}

    echo succeeded
    chmod 600 "${SSH_ENV}"
    . "${SSH_ENV}" > /dev/null
    /usr/bin/ssh-add;
}

# Source SSH settings, if applicable
if [ -f "${SSH_ENV}" ]; then
    . "${SSH_ENV}" > /dev/null
    #ps ${SSH_AGENT_PID} doesn't work under cywgin
    ps -ef | grep ${SSH_AGENT_PID} | grep ssh-agent$ > /dev/null || {
        start_agent;
    }
else
    start_agent;
fi

# create our own hardlink to the socket (with random name)
MYSOCK=/tmp/ssh_agent.${RANDOM}.sock
ln -T $SSH_AUTH_SOCK $MYSOCK
export SSH_AUTH_SOCK=$MYSOCK

end_agent()
{
    # if we are the last holder of a hardlink, then kill the agent
    nhard=`ls -l $SSH_AUTH_SOCK | awk '{print $2}'`
    if [[ "$nhard" -eq 2 ]]; then
        rm ${SSH_ENV}
        /usr/bin/ssh-agent -k
    fi
    rm $SSH_AUTH_SOCK
}
trap end_agent EXIT
set +x
hoijui
  • 3,076
  • 1
  • 28
  • 34
Knelis
  • 21
  • 1
  • Great idea! Perhaps it would be more reliable though if you used the bash process' PID and the current user's name with `$$` and `${USER}` instead of `${RANDOM}`? Also, the `$(command)` syntax is the new way to do command substitution. – starbeamrainbowlabs Jun 29 '20 at 15:31
2

I use the ssh-ident tool for this.

From its man-page:

ssh-ident - Start and use ssh-agent and load identities as necessary.

hoijui
  • 3,076
  • 1
  • 28
  • 34
CreationTribe
  • 552
  • 1
  • 5
  • 16