如何在附加到现有tmux会话时自动更新SSH代理环境变量

时间:2014-01-27 10:36:36

标签: tmux ssh-agent

当我重新连接断开连接的tmux会话时,我正试图找到一种恢复SSH代理的好方法。

原因似乎是SSH代理会话发生了变化,但tmux会话中的环境变量没有更新。

如何在附加会话本身之前自动执行此操作?因为我附加的会话并不总是有bash提示符,所以我不能在其中键入内容。它必须在创建或附加tmux会话之前运行。

我正在运行的代码示例位于https://gist.github.com/ssbarnea/8646491 - 一个使用tmux创建persistem ssh连接的小ssh包装器。这很有效,但有时ssh代理停止工作,所以我不再能够使用它连接到其他主机。

10 个答案:

答案 0 :(得分:70)

Martijn Vermaat有一个很好的gist,它可以很好地解决你的问题,虽然它适用于屏幕用户,所以我在这里调整它为tmux。

总结:

  1. 创建~/.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
    
  2. 让它在tmux中运行,将其添加到~/.tmux.conf

    # fix ssh agent when tmux is detached
    setenv -g SSH_AUTH_SOCK $HOME/.ssh/ssh_auth_sock
    
  3. 如果要启用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  )
  1. export SSH_AUTH_SOCK环境变量设置为$()命令替换的输出
  2. find开始的
  3. /tmp个文件
  4. 将结果限制为仅在路径中具有/ssh-的结果
  5. 将结果限制为仅以agent开头的人
  6. 将结果限制为仅具有其ID与当前用户匹配的用户
  7. 沉默所有(权限等)错误
  8. 如果有多个结果,则仅获取最后一个结果

如果知道只有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=&quot;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&quot;" providerName="System.Data.EntityClient" /> 配置文件中的解决方案。与修改~/.tmux.conf~/.bash_profile不同。

仅使用~/.ssh/rc

的解决方案

只需将以下代码粘贴到您的~/.tmux.conf

~/.tmux.conf

注意事项

在启动与同一台机器的多个连接时,上述解决方案以及其他解决方案很容易出现竞争状况。考虑一下:

  • 客户端1连接:SSH到machineX,启动/连接tmux(写入# ~/.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\" \ " 链接)
  • 客户端2连接:SSH到machineX,启动/连接tmux(覆盖ssh_auth_sock链接)
  • 客户端2断开连接:客户端1留下了失效的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)。