重新连接时,为什么必须在tmux中重新设置环境变量?


37

我主要在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没有设置,即使在我的本地环境设置。如果使用setenv上面的命令将其放在tmux的环境中,则一切正常。我的问题是,为什么我必须完全运行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则返回到未设置状态。


这根本不是关于SSH的,是吗?您在新Shell中拥有哪些环境变量,输出是env什么?
Hauke Laging

您在Mac上使用什么外壳?重击?
slm

@HaukeLaging这实际上是关于tmux的。
克里斯·W

@slm我正在使用zsh。
克里斯W.

现有的窗户呢?他们还在工作吗?
Hauke Laging

Answers:


35

自从我收到赏金后,出于完整性考虑,我将重新发布我的主要评论-并避免将访问者遇到相同的问题放在错误的轨道上:

Tmux将删除环境变量

Tmux的手册页指出,update-environment将删除“在源环境中不存在的变量,就像给set-environment命令赋予了-r一样。

显然,这是导致问题的原因。请参阅下面的克里斯回应。但是,我仍然无法想象变量如何在“源环境”中不存在,而在新创建的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中添加“ update-environment命令”。根据手册页,默认情况下已包含SSH_AUTH_SOCK。

信用

我的回答是Mark'xb95'Smith 的这篇博客文章的摘录,他解释了屏幕的相同问题。


感谢您的周到答复。我的问题不是关于$SSH_AUTH_SOCK在新shell中设置我的问题,而是关于$SSH_AUTH_SOCK在获取.bashrc / .zshrc之前在新的tmux窗口中进行设置。
克里斯·W

@ChrisW。我假设该脚本应放在远程计算机上登录shell的rc文件中。如果您登录,将生成一个新的shell,更改并导出 SSH_AUTH_SOCK 。然后,当您启动tmux时,它将从父环境继承SSH_AUTH_SOCK。由于SSH_AUTH_SOCK的值现在是固定的,因此tmux应该继续处理后续的登录...也许我误解了这个问题
2013年

我想我的困惑是关于tmux在新窗口(例如tmux neww ssh somehost)的上下文中运行ssh的环境。
克里斯W.

这种方法的一个问题是与计算机的第二个SSH连接将覆盖的值SSH_AUTH_SOCK。仅当通过最新的SSH连接打开tmux会话时,此方法才有效。
phylae 2015年

12

我想通了。简短的回答,我需要删除SSH_AUTH_SOCKupdate-environment。由于它在该列表中,因此每次重新连接时,其价值都被吹灭了。感谢@djf提供了线索。tmux(1)手册页中的重要update-environment内容:

源环境中不存在的所有变量都将设置为从会话环境中删除(就像-r被赋予set-environment命令一样)。


1
@ChrisW。您能再说清楚一点吗?我确实认为我有同样的问题:有时,当我重新连接tmux会话时,代理会停止工作。SSH连接是新的,在我使用ssh时它将启动一个新代理,这在某种意义上是有意义的。为了使其起作用,我必须更改什么?我希望它可以运行,因为我不必重新配置要插入的每台计算机。-现在我有一个ssh包装器,可以远程启动tmux或恢复现有的连接,也许我可以在恢复tmux之前做一些事情。
索林2014年

@ChrisW。简短的答案有时是不错的选择,但请您给出较长的答案?我正在努力使其正常工作,这篇文章中没有任何内容对我有用。
redbmk

@sorin @redbmk抱歉。这是我必须更改的唯一行,.tmux.conf才能使它起作用: set -g update-environment "SSH_ASKPASS WINDOWID SSH_CONNECTION XAUTHORITY" 您是否看到ssh一般的环境变量问题?
克里斯·W

2

我没有使用tmux处理我的ssh-agent,而是让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中有此功能,并且效果很好。


$SSH_AUTH_SOCK在外壳程序中正确设置了,但是当我执行类似的操作时tmux neww ssh somehost除非运行,否则系统会提示我输入密码来解锁私钥tmux setenv SSH_AUTH_SOCK $SSH_AUTH_SOCK
克里斯W.

1

我在StackOverflow https://stackoverflow.com/a/49395839/241025上回答了类似的问题。由于此页面在我的Google搜索中排在第一位,因此我想在此发布摘要。

要使每个tmux会话具有一组自定义环境变量,您必须将值添加到tmux的每个会话环境变量中。这是一个如何做的例子。

tmux new-session -s one
tmux setenv FOO foo-one
export FOO='foo-one'

需要显式导出FOO的最后一步,以便当前窗格可以拾取环境变量。您为此tmux会话创建的任何后续窗格或窗口都将继承FOO,但不会在其他会话中显示。


0

djf的解释为我带来了另一个可能的解决方案:

tmux/ screen运行之前:

  1. 登录。
  2. 启动的实例ssh-agent
  3. tmux/ 开始screen于此的环境变量ssh-agent

这不能使用SSH转发到客户端,但是没有要求。


1
ssh-agent没有绑定到TTY,为什么要在logout(?)上将其杀死-为什么要使用nohup
poige

@poige正确。
Hauke Laging
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.