每当我使用 ssh-agent 进行无密码登录时,它就无法跨不同的登录和屏幕会话工作,即使它们是并发的。
我怀疑它使用了一些无法跨不同会话工作的 shell 变量。有什么方法可以配置它或让它使用可以出现在所有会话中的某种变量吗?
答案1
我用来keychain
管理我的ssh-agent
环境变量,它负责确保一次只有一个代理运行。从我.bashrc
在适当的机器上:
# is this an interactive shell?
if [[ $- == *i* ]]; then
# set up ssh key server
if [[ -x /usr/bin/keychain ]]; then
eval $(keychain --eval --ignore-missing the <keys I want>)
fi
fi
它将环境变量存储在 中~/.keychain
,如果未找到则运行代理,并将新的或现有的变量返回到 中eval
。我几年前就设置了它,但没有碰过它。如果您已ssh-askpass
安装,即使运行钥匙串的 shell 不可见(例如 X11 初始化脚本),它也能够在 X11 环境中提示输入密码。
还有其他方法可以使用它,但这对我来说适用于多个 Linux 工作站,包括当我没有登录 X11 时从远程登录工作站。
答案2
是的,ssh 使用 SSH_AUTH_SOCK 变量来访问代理。
如果您在不同的会话中启动不同的代理,它们将不会共享密钥。
运行ssh-agent
查看该实例设置的变量。
阅读man ssh-agent
以了解可能的选择。 (特别是 -a 对您的情况应该有帮助。)
共享一名代理的最佳方式很大程度上取决于您的情况。您必须确保只有一个代理正在运行,并且所有会话都设置了使用它的环境。
如果您使用某些桌面环境,这通常会启动 ssh 代理并设置环境以使其可用于桌面会话内启动的所有进程。 - 如果您想为所有会话共享新代理,screen
您可以将屏幕启动为ssh-agent screen
。 - 如果您想在盒子内进行 ssh 并访问您的代理,这也是可能的,但您要靠自己了。
答案3
您可以为每个人的登录过程编写一个脚本
- 检查是否至少有一个 ssh-agent 实例正在运行(对于该用户)
- 选择要使用的实例(最旧的)
- 检查此进程的套接字信息是否可用(并且正确)
- 如果成功,则在自己的环境中获取此信息
- 也许会杀死其他实例(至少是它自己的实例,如果有的话)
ps -o pid,etime,args --no-headers --sort=start_time \
-p $(pgrep --uid $USER ssh-agent) |
awk '{print $1; exit;}'
为您提供最旧的 ssh-agent 实例的 PID。这样会更容易,pgrep --uid $USER --oldest ssh-agent
但这样你也可以轻松获得其他实例的 PID。
您可以$SSH_AUTH_SOCK
在文件中写入~/.ssh/env/$PID
(如果$SSH_AGENT_PID
当前进程等于 $PID):
echo "export SSH_AUTH_SOCK=$SSH_AUTH_SOCK" > ~/.ssh/env/$PID
其他会话可以检查文件是否存在并且仍然有效并导入它:
bash -c 'test -e ~/.ssh/env/$PID || exit 1;
. ~/.ssh/env/$PID; test -e $SSH_AUTH_SOCK' && . ~/.ssh/env/$PID
答案4
使用优秀的ssh-ident
它支持多个身份以提高安全性。
它是,的直接包装ssh
:scp
ln -s /usr/bin/ssh-ident ~/bin/ssh
ln -s /usr/bin/ssh-ident ~/bin/scp
有一个大量的自己提出的答案,但为什么要重新发明轮子呢?