登录时启动ssh-agent

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

我手动启动ssh-agent:

eval ssh-agent $SHELL

然后添加代理:

ssh-add ~/.ssh/bitbucket_id

然后当我这样做的时候,它就出现了:

ssh-add -l

我可以出发了。有什么方法可以自动化这个过程,这样我就不必每次登录都这么做了?服务器的操作系统为RedHat 6.2 (Santiago)。

372481 次浏览

请通读这篇文章。你可能会发现这很有用:

https://web.archive.org/web/20210506080335/https://mah.everybody.org/docs/ssh

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

以下是Joseph M. Reagle通过Daniel Starin提出的解决方案:

将以下内容添加到.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

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

老问题了,但我确实遇到过类似的情况。不要认为上面的答案完全满足了需要。缺少的部分是keychain;如果还没有,就安装它。

sudo apt-get install keychain

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

eval $(keychain --eval id_rsa)

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

id_rsa更改为你想要加载的~/.ssh中的任何一个私钥。

一些有用的钥匙扣选项:

  • -q安静模式
  • --noask不要在启动时询问密码,而是在实际使用ssh密钥时要求。

参考

https://unix.stackexchange.com/questions/90853/how-can-i-run-ssh-add-automatically-without-password-prompt < a href = " https://unix.stackexchange.com/questions/90853/how-can-i-run-ssh-add-automatically-without-password-prompt " > < / >

目前公认的解决方案存在以下缺陷:

  • 维护起来很复杂;
  • 对可能导致错误或安全漏洞的存储文件进行评估;
  • 它启动代理,但不停止它,这是接近相当于离开点火钥匙。

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

它有以下优点:

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

它可能有缺点:

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

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

我通过将此添加到/ etc / profile -系统范围(或用户本地. profile,或. 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

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

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

# 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

因此,我过去常常使用上面描述的方法,但我有点希望代理在最后一次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

我很喜欢你的回答。它使得在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

将此添加到您的~/.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

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

在Arch Linux上,下面的工作真的很棒(应该适用于所有基于系统的发行版):

通过将以下内容放入~/.config/systemd/user/ssh-agent.service中,创建systemd用户服务:

[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

为套接字设置一个环境变量(.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添加。

再加上另一个解决方案:P,我使用了@spheenik和@ collins -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

可以更优雅一点,但它简单易读。这个解决方案:

  • 确保AddKeysToAgent yes在你的ssh配置中,这样密钥将在使用时自动添加
  • 不会提示您在登录时输入任何密码(再次强调,在第一次使用时输入一次密码)
  • 如果ssh-agent还没有启动,则静默地启动

欢迎评论:)

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

如果你还不熟悉zshoh-my-zsh,那么就安装它。你会爱上它的:)

然后编辑.zshrc

vim ~/.zshrc

找到plugins部分并更新它以使用ssh-agent,如下所示:

plugins=(ssh-agent git)

这就是全部!每次你启动你的shell时,你都会有ssh-agent启动并运行

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

从它的男人。-page:

ssh-ident—根据需要启动和使用ssh-agent并加载标识。