登录时启动ssh-agent

时间:2013-09-18 18:48:43

标签: git ssh bitbucket redhat ssh-agent

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

我手动启动ssh-agent:

eval ssh-agent $SHELL

然后我添加代理:

ssh-add ~/.ssh/bitbucket_id

然后它出现在我做的时候:

ssh-add -l

我很高兴。有没有办法自动化这个过程,所以我不必每次登录都这样做?服务器正在运行RedHat 6.2(Santiago)。

12 个答案:

答案 0 :(得分:302)

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

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

以防上述链接有一天消失,我正在捕捉下面解决方案的主要部分:

  

来自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,如果找不到它,会启动它并存储设置,以便下次你可以使用它们启动一个shell。

答案 1 :(得分:74)

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

通过将以下内容添加到~/.config/systemd/user/ssh-agent.service

来创建systemd用户服务
[Unit]
Description=SSH key agent

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

[Install]
WantedBy=default.target

设置shell以获得套接字的环境变量(.bash_profile, .zshrc, ...):

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

启用该服务,以便在登录时自动启动,然后启动它:

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

将以下配置设置添加到ssh配置文件~/.ssh/config(这可以从SSH 7.2开始):

AddKeysToAgent  yes

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

答案 2 :(得分:46)

老问题,但我确实遇到过类似的情况。不要以为上述答案完全实现了所需要的。遗失的部分是keychain;如果它还没有安装它。

sudo apt-get install keychain

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

eval $(keychain --eval id_rsa)

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

id_rsa更改为您要加载的~/.ssh中的私钥。

<强>参考

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

答案 3 :(得分:36)

公认的解决方案有以下缺点:

  • 维护起来很复杂;
  • 评估可能导致错误或安全漏洞的存储文件;
  • 它启动代理但不会停止它,这相当于将钥匙保持在点火状态。

如果您的密钥不需要输入密码,我建议您使用以下解决方案。将以下内容添加到您的.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

它有以下优点:

  • 更简单的解决方案;
  • 代理会话在bash会话结束时结束。

它有可能的缺点:

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

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

答案 4 :(得分:21)

将此添加到您的~/.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 | grep "The agent has no identities" && ssh-add

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

答案 5 :(得分:7)

所以我过去习惯使用上面描述的方法,但是当我上次的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 $2}'`                             
    if [[ "$nhard" -eq 2 ]]; then                                               
        rm ~/.ssh/.agent_env                                                    
        ssh-agent -k                                                            
    fi                                                                          
    rm $SSH_AUTH_SOCK                                                           
}                                                                               
trap end_agent EXIT                                                             
set +x              

答案 6 :(得分:4)

添加另一个解决方案: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

可能更优雅,但简单易读。这个解决方案:

  • 确保您的ssh配置中有AddKeysToAgent yes,因此在使用时会自动添加密钥
  • 在登录时不会提示您输入任何密码短语(同样,首次使用时会输入一次密码短语)
  • 如果还没有启动ssh-agent
  • ,则默默启动它

欢迎评论:)

答案 7 :(得分:2)

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

# SSH-AGENT 
#!/usr/bin/env bash
SERVICE='ssh-agent'
WHOAMI=`who am i |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

如果没有为用户运行,则启动新的ssh-agent;如果正在运行,则重新设置ssh-agent env参数。

答案 8 :(得分:2)

抱歉这么晚:

fish shell的用户可以使用此script执行相同的操作。

# 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

答案 9 :(得分:1)

喜欢你的答案很多。它使cygwin / linux主机的工作变得更加容易。我将开始和结束功能结合起来使其安全。

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

再次感谢

答案 10 :(得分:0)

尝试了许多来源的夫妇解决方案,但似乎都太麻烦了。终于我找到了最简单的一个:)

如果您还不熟悉 zsh oh-my-zsh ,请安装它。你会爱上它的:)

然后编辑.zshrc

vim ~/.zshrc

找到plugins部分,并将其更新为使用ssh-agent,如下所示:

plugins=(ssh-agent git)

仅此而已!每次启动Shell时,ssh-agent就会启动并运行

答案 11 :(得分:0)

我为此使用ssh-ident工具。

在其 man 页中:

  

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