git 登录时启动 ssh-agent

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/18880024/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-10 17:00:15  来源:igfitidea点击:

Start ssh-agent on login

gitsshbitbucketredhatssh-agent

提问by Pathsofdesign

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.

我有一个站点作为使用 SSH 别名从 Bitbucket.com 拉取的远程 Git 存储库。我可以在我的服务器上手动启动 ssh-agent,但每次我通过 SSH 登录时都必须这样做。

I manually start the ssh-agent:

我手动启动 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).

我很高兴去。有什么方法可以使这个过程自动化,这样我就不必每次登录时都这样做吗?服务器运行的是 RedHat 6.2 (Santiago)。

回答by Litmus

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

请仔细阅读这篇文章。您可能会发现这非常有用:

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

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

Joseph M. Reagle 通过 Daniel Starin 提供的解决方案:

将以下内容添加到您的 .bash_profile

SSH_ENV="$HOME/.ssh/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

这个版本特别好,因为它会查看您是否已经启动了 ssh-agent,如果找不到,将启动它并存储设置,以便您下次启动时可以使用它们贝壳。

回答by spheenik

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

在 Arch Linux 上,以下效果非常好(应该适用于所有基于 systemd 的发行版):

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

创建一个 systemd 用户服务,将以下内容放入~/.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, ...):

设置 shell 为套接字 ( .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):

将以下配置设置添加到本地 ssh 配置文件~/.ssh/config(自 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.

这将指示 ssh 客户端始终将密钥添加到正在运行的代理,因此无需事先 ssh 添加它。

回答by xelber

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.

老问题,但我确实遇到过类似的情况。不要认为上述答案完全达到了需要。缺少的部分是keychain; 如果尚未安装,请安装它。

sudo apt-get install keychain

Then add the following line to your ~/.bashrc

然后将以下行添加到您的 ~/.bashrc

eval $(keychain --eval id_rsa)

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

ssh-agent如果它没有运行,这将启动它,如果它正在运行,则连接到它,将ssh-agent环境变量加载到您的 shell 中,并加载您的 ssh 密钥。

Change id_rsato whichever private key in ~/.sshyou want to load.

更改id_rsa~/.ssh您要加载的任何私钥。

Reference

参考

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

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

回答by midenok

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_profilevery end(edit key list to your needs):

如果您的密钥不需要输入密码,我建议以下解决方案。将以下内容添加到您的.bash_profile最后(根据您的需要编辑密钥列表):

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.
  • 更简单的解决方案;
  • 当 bash 会话结束时,代理会话结束。

It have possible disadvantages:

它有可能的缺点:

  • interactive ssh-addcommand 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).
  • 交互式ssh-add命令只会影响一个会话,这实际上只是在非常不典型的情况下才会出现的问题;
  • 如果需要输入密码则无法使用;
  • 启动的 shell 变为非登录(这不会影响任何 AFAIK)。

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

请注意,多个ssh-agent进程并不是缺点,因为它们不会占用更多内存或 CPU 时间。

回答by Collin Anderson

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

将此添加到您的~/.bashrc,然后注销并重新登录以生效。

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-agentas long as it stays running.

这应该只在您每次重新启动后第一次登录时提示输入密码。ssh-agent只要它保持运行,它就会继续重复使用。

回答by Micah

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.

所以我曾经使用上面描述的方法,但我更喜欢代理在我最后一次 bash 会话结束时死亡。这比其他解决方案要长一些,但它是我的首选方法。基本思想是第一个 bash 会话启动 ssh-agent。然后每个额外的 bash 会话检查配置文件 ( ~/.ssh/.agent_env)。如果存在并且有会话正在运行,则获取环境并创建到套接字文件的硬链接/tmp(需要与原始套接字文件位于同一文件系统上)。当 bash 会话关闭时,每个会话都会删除自己的硬链接。最后关闭的会话会发现硬链接有2个链接(硬链接和原始链接),删除进程自己的套接字并杀死进程将导致0,在最后一个bash会话关闭后留下一个干净的环境。

# 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 }'`                             
    if [[ "$nhard" -eq 2 ]]; then                                               
        rm ~/.ssh/.agent_env                                                    
        ssh-agent -k                                                            
    fi                                                                          
    rm $SSH_AUTH_SOCK                                                           
}                                                                               
trap end_agent EXIT                                                             
set +x              

回答by Keego

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

只是为了添加另一个解决方案:P,我结合了 @spheenik 和 @collin-anderson 的解决方案。

 # 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 yesis 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
  • 确保AddKeysToAgent yes在您的 ssh 配置中,以便在使用时自动添加密钥
  • 登录时不会提示您输入任何密码(同样,第一次使用时会输入一次性密码)
  • 如果 ssh-agent 尚未启动,则静默启动

Comments welcome :)

欢迎评论:)

回答by TheFrog

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

我通过将它添加到/etc/profile- 系统范围(或用户本地.profile或 _.bash_profile_)来解决它:

# SSH-AGENT 
#!/usr/bin/env bash
SERVICE='ssh-agent'
WHOAMI=`who am i |awk '{print }'`

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.

如果当前用户没有运行,这将启动一个新的 ssh-agent,或者如果正在运行,则重新设置 ssh-agent env 参数。

回答by Daniel Gerber

Users of the fish shellcan use this scriptto do the same thing.

fish shell 的用户可以使用这个脚本来做同样的事情。

# 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

回答by CreationTribe

I use the ssh-identtool for this.

为此,我使用了ssh-ident工具。

From its man-page:

从它的手册页:

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

ssh-ident - 根据需要启动和使用 ssh-agent 并加载身份。