3

我正在运行 Ubuntu 并使用gnome-terminal并希望以tmux这样一种方式运行,即它可以使用所有gnome-session环境,就像打开一个新的终端窗口一样。例如使用无密码的 ssh。

问题似乎是流程层次结构......

在新窗口中gnome-terminal

$ pstree -ps $$
init(1)───lightdm(1825)───lightdm(18486)───gnome-session(18552)───gnome-terminal(18626)

一旦我进入一个 tmux会话(即使在上面的终端窗口中:

$ pstree -ps $$
init(1)───tmux(15798)───bash(21770)

tmux似乎是 init 的直接子代,而不是在会话的进程层次结构中。有没有办法让它作为一个孩子被创造出来gnome-session

编辑:下面的好答案(接受的答案)!但是,我想我会包含一个我在收到将 tmux 的所有子 bash 进程更新到最新环境的答案后编写的函数:

#!/bin/bash

tmup () 
{ 
    echo -n "Updating to latest tmux environment...";
    export IFS=",";
    for line in $(tmux showenv -t $(tmux display -p "#S") | tr "\n" ",");
    do
        if [[ $line == -* ]]; then
            unset $(echo $line | cut -c2-);
        else
            export $line;
        fi;
    done;
    unset IFS;
    echo "Done"
}
4

1 回答 1

4

tmux服务器调用daemon(3)将自己与启动它的进程(即初始tmux客户端)分离。这不是可选的,因此在daemon(3)完成双分叉和中间退出之后,服务器将始终重新设置为 PID 1(例如init ) 。

一般来说,tmux服务器不再直接“连接”到gnome-session虽然是(幸存的)进程的父级,但这并不重要。

ssh的情况下,无需重新输入密码即可使用密钥的能力依赖于对ssh-agent进程的访问。ssh实例查找 SSH_AUTH_SOCK 环境变量以了解在哪里联系可以为其提供密钥的ssh 代理gnome-session可能会安排启动ssh-agent并使用适当的 SSH_AUTH_SOCK 值填充其环境。当您启动各种进程时,此环境会从父级继承到子级。这样,tmux服务器也会继承 SSH_AUTH_SOCK 值(从最初的tmux客户端,它从一个 shell 中获取它,它从gnome-terminal,它是从gnome-session获得的)。

但是,当您附加到从不同环境启动的tmux会话时,就会出现问题。考虑以下场景,这暗示了tmux服务器的 PID 低于gnome-session的 PID :

  1. 登录到 GUI 会话。
    gnome-session启动一个ssh-agentSSH_AUTH_SOCK=foo在其环境中进行配置;该值将由其所有未来的子代继承。
  2. 您启动一个tmux服务器(通过 shell 和gnome-terminal)。tmux服务器继承
    ;它将被传递给它的子进程(例如,在tmux会话中运行的 shell)。SSH_AUTH_SOCK=foo
  3. 您从tmux会话断开连接并注销您的 GUI 会话。tmux服务器及其子节点仍然具有,但
    该值可能不再有效(当gnome-session结束时,它可能会杀死它启动的ssh-agent )。SSH_AUTH_SOCK=foo
  4. 稍后,您重新登录到 GUI 会话。
    这次gnome-session设置SSH_AUTH_SOCK=bar并将其传递给它的孩子。
  5. 您重新连接到您的tmux会话。
    此时,您拥有SSH_AUTH_SOCK=bar“外部” tmuxSSH_AUTH_SOCK=foo“内部”会话。这可能是您遇到问题的地方。

实际上,由于tmux服务器已经超过了原始 GUI 会话,因此它最初继承的任何特定于该会话的环境变量都可能无效(除非它们碰巧在您下次登录 GUI 会话时使用完全相同的值)。

幸运的是,tmux具有处理这种情况的功能。session 选项指定了一个环境变量列表,当客户端创建或附加到会话时,这些update-environment环境变量会被复制到“会话环境”中(或从中删除)。SSH_AUTH_SOCK 是此选项默认值的一部分,因此在您重新附加时会更新。但是,tmux只能更新它的“会话环境”(它将被该会话的任何子代继承)。

不幸的是,tmux无法更新属于该会话的任何现有进程(事实上,这是不可能的,缺少可以修补已运行进程内部的调试工具)。因此,在上述情况之后在 Windows/窗格中运行的任何现有 shell 都可能使用无效的 SSH_AUTH_SOCK。ssh不会抱怨无效值,它只会提示您输入适当的密钥密码。

您可能会尝试做的是从会话环境中提取 SSH_AUTH_SOCK 的值,并使用如下命令将其合并到旧会话中预先存在的 shell 中:

 SSH_AUTH_SOCK=$(tmux show-environment | awk '/^SSH_AUTH_SOCK=/ { sub(/.*=/,""); print }')

If you are having issues related to other environment variables, then you may need to add them to update-environment (e.g. set-option -ga update-environment ' FROBNIZ' in your ~/.tmux.conf) and do something similar to copy the values into any existing shells after you reattach from a different context.

于 2013-01-30T08:07:37.457 回答