为什么重新附加时必须在 tmux 中重新设置环境变量?

为什么重新附加时必须在 tmux 中重新设置环境变量?

我主要在 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 已经默认覆盖了。

信用

我的回复是摘录这篇博文作者:Mark 'xb95' Smith,他解释了同样的问题屏幕

答案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运行中:

  1. 登录。
  2. 启动 的一个实例ssh-agent
  3. tmux以/开头screen为此 的环境变量ssh-agent

这无法使用 SSH 转发到客户端,但没有要求这样做。

相关内容