![为什么重新附加时必须在 tmux 中重新设置环境变量?](https://linux22.com/image/31895/%E4%B8%BA%E4%BB%80%E4%B9%88%E9%87%8D%E6%96%B0%E9%99%84%E5%8A%A0%E6%97%B6%E5%BF%85%E9%A1%BB%E5%9C%A8%20tmux%20%E4%B8%AD%E9%87%8D%E6%96%B0%E8%AE%BE%E7%BD%AE%E7%8E%AF%E5%A2%83%E5%8F%98%E9%87%8F%EF%BC%9F.png)
我主要在 mac 上工作,并通过 ssh/tmux 连接到 Linux 机器来完成我的工作。我在 Linux 机器上运行 ssh-agent。我有
set -g update-environment "SSH_AUTH_SOCK SSH_ASKPASS WINDOWID SSH_CONNECTION XAUTHORITY"
在我的.tmux.conf
。然而,每当我重新连接到此会话时,我都必须运行
tmux setenv SSH_AUTH_SOCK $SSH_AUTH_SOCK
为了$SSH_AUTH_SOCK
正确设置新的 tmux 窗口。我宁愿不必这样做。有任何想法吗?
更新
我想我没有很好地解释这一点。这是我在远程计算机上打开 shell 的 shell 函数:
sshh () {
tmux -u neww -n ${host} "ssh -Xt ${host} $*"
}
当 tmux 运行这个 ssh 命令时,$SSH_AUTH_SOCK
是不是设置,即使它是设置在我的本地环境中。如果我使用上面的命令将其放入 tmux 的环境中setenv
,一切都会正常工作。我的问题是,为什么我必须运行 setenv 命令?
更新2
更多信息:
当我附加到现有会话时,$SSH_AUTH_SOCK
未在 tmux 环境(或全局环境)中设置。
% tmux showenv | grep -i auth_sock
-SSH_AUTH_SOCK
如果我手动设置,一切正常:
% tmux setenv SSH_AUTH_SOCK $SSH_AUTH_SOCK
如果我分离并重新连接,$SSH_AUTH_SOCK
则会回到未设置状态。
答案1
自从我收到赏金后,为了完整性起见,我将重新发布我的关键评论 - 并避免将具有相同问题的访问者置于错误的轨道上:
Tmux 将删除环境变量
Tmux 的手册页指出 update-environment 将删除变量“源环境中不存在[...],就好像将 -r 赋予了 set-environment 命令一样”。
显然这就是导致问题的原因。看克里斯的回应如下。但是,我仍然无法想象该变量如何在“源环境”中不存在,但在新创建的 tmux 窗口中有效......
上一个答案:
SSH 转发的工作原理
在远程计算机上,建立 SSH 连接后查看 shell 环境:
user@remote:~$ env | grep SSH
SSH_CLIENT=68.38.123.35 45926 22
SSH_TTY=/dev/pts/0
SSH_CONNECTION=68.38.123.35 48926 10.1.35.23 22
SSH_AUTH_SOCK=/tmp/ssh-hRNwjA1342/agent.1342
这里最重要的是 SSH_AUTH_SOCK,它当前设置为 /tmp 中的某个文件。如果你检查这个文件,你会发现它是一个 Unix 域套接字——并且连接到你连接的 ssh 的特定实例。重要的是,每次连接时都会发生变化。
一旦您注销,该特定套接字文件就会消失。现在,如果您重新连接 tmux 会话,您就会看到问题。它拥有 tmux 最初启动时的环境——可能是几周前。那个特定的套接字早已死了。
解决方案
因为我们知道问题与了解当前活动的 SSH 身份验证套接字在哪里有关,所以让我们将其放在可预测的位置!
在远程计算机上的 .bashrc 或 .zshrc 文件中,添加以下内容:
# Predictable SSH authentication socket location.
SOCK="/tmp/ssh-agent-$USER-screen"
if test $SSH_AUTH_SOCK && [ $SSH_AUTH_SOCK != $SOCK ]
then
rm -f /tmp/ssh-agent-$USER-screen
ln -sf $SSH_AUTH_SOCK $SOCK
export SSH_AUTH_SOCK=$SOCK
fi
我认为您甚至不必在 tmux.conf 中添加“更新环境命令”。根据手册页, SSH_AUTH_SOCK 已经默认覆盖了。
信用
答案2
我明白了这一点。简短的回答,我需要SSH_AUTH_SOCK
从 中删除update-environment
。因为它在该列表中,所以每次我重新连接时,它的价值都会被消除。感谢@djf 提供线索。 tmux(1) 手册页中的重要部分update-environment
:
源环境中不存在的任何变量都将被设置为从会话环境中删除(就像为 set-environment 命令指定了 -r 一样)。
答案3
我没有使用 tmux 来处理我的 ssh 代理,而是使用 bash 来处理它:
### SSH Agent ### {{{
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 -ef | grep ${SSH_AGENT_PID} | grep ssh-agent$ > /dev/null || {
start_agent;
}
else
start_agent;
fi
### End SSH Agent ### }}}
我的〜/中有这个bashrc,而且效果很好。
答案4
djf的解释给我带来了另一种可能的解决方案:
运行前tmux
/screen
运行中:
- 登录。
- 启动 的一个实例
ssh-agent
。 tmux
以/开头screen
为此 的环境变量ssh-agent
。
这无法使用 SSH 转发到客户端,但没有要求这样做。