当我重新连接断开连接的tmux会话时,我正试图找到一种恢复SSH代理的好方法。
原因似乎是SSH代理会话发生了变化,但tmux会话中的环境变量没有更新。
如何在附加会话本身之前自动执行此操作?因为我附加的会话并不总是有bash提示符,所以我不能在其中键入内容。它必须在创建或附加tmux会话之前运行。
我正在运行的代码示例位于https://gist.github.com/ssbarnea/8646491 - 一个使用tmux创建persistem ssh连接的小ssh包装器。这很有效,但有时ssh代理停止工作,所以我不再能够使用它连接到其他主机。
答案 0 :(得分:70)
Martijn Vermaat有一个很好的gist,它可以很好地解决你的问题,虽然它适用于屏幕用户,所以我在这里调整它为tmux。
总结:
创建~/.ssh/rc
(如果它尚不存在),并添加以下内容:
#!/bin/bash
# Fix SSH auth socket location so agent forwarding works with tmux
if test "$SSH_AUTH_SOCK" ; then
ln -sf $SSH_AUTH_SOCK ~/.ssh/ssh_auth_sock
fi
让它在tmux中运行,将其添加到~/.tmux.conf
:
# fix ssh agent when tmux is detached
setenv -g SSH_AUTH_SOCK $HOME/.ssh/ssh_auth_sock
如果要启用X11转发,则需要额外的工作,请参阅gist。
答案 1 :(得分:26)
默认情况下,虽然tmux
updates SSH
个变量,但不需要
SSH_AUTH_SOCKET
变量我喜欢Chris Down的解决方案,我更改了添加功能
fixssh() {
eval $(tmux show-env \
|sed -n 's/^\(SSH_[^=]*\)=\(.*\)/export \1="\2"/p')
}
进入~/.bashrc
。在附加会话后或fixssh
/ ssh
/ scp
之前致电rsync
。
tmux
的较新版本支持-s
的{{1}}选项,因此只有
show-env
是可能的。
答案 2 :(得分:5)
这是我的解决方案,其中包括两种方法,并且在重新连接到tmux会话时不需要额外输入
{{1}}
答案 3 :(得分:3)
我使用先前答案的变体:
eval "export $(tmux show-environment -g SSH_AUTH_SOCK)"
假设您做了ssh代理程序是从外部环境开始的。其他环境变量(例如DISPLAY
)也是如此。
答案 4 :(得分:2)
这里有很多好的答案。但是在某些情况下,tmux show-environment
没有看到SSH_AUTH_SOCK
。在这种情况下,您可以使用find
对其进行明确定位。
export SSH_AUTH_SOCK=$(find /tmp -path '*/ssh-*' -name 'agent*' -uid $(id -u) 2>/dev/null | tail -n1)
那是漫长而复杂的,所以我将其分解...
01 export SSH_AUTH_SOCK=$(
02 find /tmp \
03 -path '*/ssh-*'
04 -name 'agent*'
05 -uid $(id -u)
06 2>/dev/null
07 | tail -n1
08 )
export
SSH_AUTH_SOCK
环境变量设置为$()
命令替换的输出find
开始的/tmp
个文件/ssh-
的结果agent
开头的人如果知道只有1个结果并且不关心stderr垃圾,则可以省略6和7。
答案 5 :(得分:1)
我宁愿避免配置TMUX(等),而将所有内容完全保留在~/.ssh/
中。在远程系统上:
创建~/.ssh/rc
:
#!/bin/bash
# Fix SSH auth socket location so agent forwarding works within tmux
if test "$SSH_AUTH_SOCK" ; then
ln -sf $SSH_AUTH_SOCK ~/.ssh/ssh_auth_sock
fi
在~/.ssh/config
中添加关注者,使其不再依赖$SSH_AUTH_SOCK
,后者在分离的终端中过时了:
Host *
IdentityAgent ~/.ssh/ssh_auth_sock
ssh-add
不使用~/.ssh/config
,因此无法与ssh-agent
通信。即使ssh-add -l
工作正常,诸如ssh user@host
之类的命令也会产生错误,更新SSH远程访问的git远程也是如此。答案 6 :(得分:1)
我可能已经找到了一个完全封装在<add name="UserManagementEntities"
connectionString="metadata=res://*/UserManagementModel.csdl|res://*/UserManagementModel.ssdl|res://*/UserManagementModel.msl;provider=System.Data.SqlClient;provider connection string="data source=xxx.xx.xx.xx;failover partner=yyyy.yy.yy.yy;initial catalog=testev;persist security info=True;user id=*********;password=********;MultipleActiveResultSets=True;App=EntityFramework""
providerName="System.Data.EntityClient" />
配置文件中的解决方案。与修改~/.tmux.conf
和~/.bash_profile
不同。
仅使用~/.ssh/rc
只需将以下代码粘贴到您的~/.tmux.conf
~/.tmux.conf
注意事项
在启动与同一台机器的多个连接时,上述解决方案以及其他解决方案很容易出现竞争状况。考虑一下:
# ~/.tmux.conf
# SSH agent forwarding
#
# Ensure that SSH-Agent forwarding will work when re-attaching to the tmux
# session from a different SSH connection (after a dropped connection).
# This code will run upon tmux create, tmux attach, or config reload.
#
# If there is an SSH_AUTH_SOCK originally defined:
# 1) Remove all SSH related env var names from update-environment.
# Without this, setenv cannot override variables such as SSH_AUTH_SOCK.
# Verify update-environment with: tmux show-option -g update-environment
# 2) Force-set SSH_AUTH_SOCK to be a known location
# /tmp/ssh_auth_sock_tmux
# 3) Force-create a link of the first found ssh-agent socket at the known location
if-shell '[ -n $SSH_AUTH_SOCK ]' " \
set-option -sg update-environment \"DISPLAY WINDOWID XAUTHORITY\"; \
setenv -g SSH_AUTH_SOCK /tmp/ssh_auth_sock_tmux; \
run-shell \"ln -sf $(find /tmp/ssh-* -type s -readable | head -n 1) /tmp/ssh_auth_sock_tmux\" \
"
链接)ssh_auth_sock
链接)ssh_auth_sock
链接,从而中断了ssh_auth_sock
但是,此解决方案更具弹性,因为它仅在tmux启动/附加时覆盖ssh-agent
链接,而不是在bash shell ssh_auth_sock
或ssh连接~/.bash_profile
初始化时覆盖< / p>
要覆盖最后的竞争条件,可以添加一个键绑定,以使用~/.ssh/rc
键序列重新加载tmux配置。
(Ctrl-b r)
在活动的tmux会话中,当# ~/.tmux.conf
# reload config file
bind r source-file ~/.tmux.conf
链接失效时执行此序列将刷新ssh-agent连接。
答案 7 :(得分:0)
在遇到许多建议之后,我终于找到了一个解决方案,该解决方案使TMUX在附加后可以更新陈旧的ssh代理。基本上,本地和远程计算机上的zshrc文件都需要修改。
将以下代码插入到基于this reference的本地zshrc中。
export SSH_AUTH_SOCK=~/.ssh/ssh-agent.$(hostname).sock
ssh-add -l 2>/dev/null >/dev/null
# The error of executing ssh-add command denotes a valid agent does not
# exist.
if [ $? -ge 1 ]; then
# remove the socket if it exists
if [ -S "${SSH_AUTH_SOCK}" ]; then
rm "${SSH_AUTH_SOCK}"
fi
ssh-agent -a "${SSH_AUTH_SOCK}" >/dev/null
# one week life time
ssh-add -t 1W path-to-private-rsa-file
fi
将以下代码插入将连接tmux会话的远程zshrc中。
alias fixssh='eval $(tmux showenv -s SSH_AUTH_SOCK)'
然后ssh进入远程计算机。 -A选项是必需的。
ssh -A username@hostname
附加TMUX会话。检查TMUX环境变量
# run this command in the shell
tmux showenv -s
# or run this command after prefix CTRL+A or CTRL+B
:show-environment
在先前存在的窗格中运行fixssh
以更新ssh代理。如果创建了一个新窗格,它将自动获取新的ssh-agent。
答案 8 :(得分:0)
这是另一个简单的 Bash 解决方案,在生成每个提示之前使用 PROMPT_COMMAND
更新 SSH_*
内的 tmux
变量。此解决方案的缺点是它在生成新提示之前不会在现有 shell 中生效,因为 PROMPT_COMMAND
仅在之前创建新提示运行。
只需将此添加到您的 ~/.bashrc
:
update_tmux_env () {
# Only run for shells inside a tmux session.
if [[ -n "$TMUX" ]]; then
eval $(tmux show-env -s | grep '^SSH_')
fi
}
export PROMPT_COMMAND=update_tmux_env
答案 9 :(得分:0)
以防其他鱼壳用户在使用鱼时想知道如何处理这个问题(以及我未来的自己!)。在我的 fish_prompt
中,我添加了对以下函数的调用:
function _update_tmux_ssh
if set -q TMUX
eval (tmux show-environment SSH_AUTH_SOCK | sed 's/\=/ /' | sed 's/^/set /')
end
end
我想更高级的 *nix 用户会知道如何用更好的东西替换 sed
,但这有效(tmux 3.0,fish 3.1)。