重新连接到已超时的 shell 实例化 tmux 会话的预期方式是什么?

重新连接到已超时的 shell 实例化 tmux 会话的预期方式是什么?

使用 tmux 会话时作为 shell 实例化的一部分被调用,每次用户通过 SSH 连接到系统时都会创建一个新会话。当分离时(如会话超时),会话仍然存在;但是,重新连接时,仍会创建一个新会话,而不是附加到先前的会话。重新连接或管理以前的会话的预期方式是什么?

背景

在里面RHEL 8 斯蒂格,有一个发现这要求“会话控制在 shell 初始化时自动启动”。在 STIG 中完成此操作的方法是在登录时启动 tmux。此外,还有其他一些控制会导致tmux 会话在活动后锁定,并且对于ssh 在不活动后断开连接。在我的 STIGed 系统上,除了主开发系统之外,我还进行了因果测试,结果出现了很多空闲超时,因此出现了很多独立的会话。

超时会话示例

[user@system ~]$ tmux list-sessions
0: 1 windows (created Tue Jun 15 14:09:29 2021) [202x47]
1: 1 windows (created Tue Jun 15 14:32:53 2021) [202x47]
10: 1 windows (created Wed Jun 16 10:34:15 2021) [202x47]
11: 1 windows (created Wed Jun 16 10:50:04 2021) [202x47] (attached)
3: 1 windows (created Tue Jun 15 15:11:01 2021) [202x47]
4: 1 windows (created Tue Jun 15 16:47:34 2021) [202x47]
5: 1 windows (created Tue Jun 15 16:50:10 2021) [80x24]
6: 1 windows (created Tue Jun 15 18:22:36 2021) [202x47]
7: 1 windows (created Wed Jun 16 09:41:14 2021) [202x47]
8: 1 windows (created Wed Jun 16 09:52:56 2021) [202x47]
9: 1 windows (created Wed Jun 16 10:14:31 2021) [202x47]

我是如何处理这件事的

如果我尝试重新连接其中一个,我会收到警告:

[user@system ~]$ tmux attach-session -t 0
sessions should be nested with care, unset $TMUX to force

如果我取消设置该值并再次附加会话,现在我有嵌套会话,这使事情变得非常复杂。理论上,我可以在这个嵌套会话中完成我正在做的事情,但似乎应该有更好的方法。如果在完成之前我再次分离,然后必须重新连接到之前的会话,现在我会议深度?

笔记: 我正在使用该系统来测试并熟悉已实现 RHEL 8 STIG 的环境。希望在生产系统上,用户能够更加关注环境,并且减少会话空闲超时的可能性。我可以为我的用例禁用超时,但我试图遵守 STIG 的规定。

答案1

猜测发生这种情况是因为tmux您的登录 shell 。每次通过 SSH 连接时,tmux都会开始一个新的过程。默认情况下tmux创建一个新会话。

连接时可以tmux a按需运行:

# from the outside
ssh -t user@server 'tmux a || tmux'

笔记:

  • 我使用了,因此如果失败(例如,当没有旧会话可附加时),tmux a || tmux这将创建一个新会话。tmux a
  • -ttmux将在远程端分配 tty 。你需要一个终端。
  • 该命令之所以有效,是因为tmux支持-c(如sh -c)。 SSH 服务器使用此选项来传递命令字符串。man 1 tmux说“此选项是为了与用作登录 shellsh(1)时兼容”。tmux确实如此。

您可以ssh user@server 'tmux ls'先运行(不需要这样做ssh -t),然后附加到特定会话 ( ssh -t … 'tmux a -t …')。


我不喜欢用它tmux作为我的登录 shell。我就是这样做的:

  1. 我的正式登录 shell 是/bin/bash.如果您想更改服务器上的登录 shell,请在连接时使用,例如chsh -s /bin/bash。您可以指定/etc/shells(运行cat /etc/shells以检查文件)中列出的任何 shell。

  2. 然后在最后我的.bashrc我有这个:

    # run tmux if outside of tmux
    if [ -z "$TMUX"]; then
       tmux a || tmux
    fi
    

    .bashrc适用于 Bash。如果您选择除此之外的 shell,bash则需要更改另一个文件。)

当我ssh到机器(或以任何方式启动登录 shell)时,/bin/bash会运行,因为它是我的登录 shell。它检测到它不在tmux并运行tmux aor tmux。如果tmux尝试运行bash那么它将运行其他 /bin/bash。该 shell 将检测到它在内部tmux,并且不会尝试运行另一个tmux.

这非常有效。请注意,.bashrc我不尝试exec tmux a也不这样做exec tmux,所以当我在里面时tmux,外壳仍然在运行。这意味着我可以终止或分离当前的 tmux 会话而无需注销。这样做会将我置于外壳中,如果我愿意,我可以手动tmux a进入另一个会话、启动新会话或无需工作。tmux这是我经过深思熟虑的设计选择。

bash我用作外壳和内壳的事实也是我的选择。一般来说,这些可以是不同的外壳。您选择带有 的外层chsh。您可以通过指定来选择默认内壳default-shell在你的.tmux.conf

default-shell path

指定默认 shell。当该default-command选项设置为空时,它将用作新窗口的登录 shell ,并且必须是可执行文件的完整路径。启动时尝试从第一个合适的环境变量(shell 由, 或 )返回tmux的值设置默认值。当用作登录 shell时应配置此选项。SHELLgetpwuid(3)/bin/shtmux

在我的设置中,我什至不使用default-shelltmux在窗口/窗格中使用我的登录 shell。但如果tmux它本身是我的登录 shell,那么我需要指定default-shell(这可能就是它目前为您工作的方式)。

答案2

导航到其他会话的键盘快捷键是ctrlb+(ctrlb+ )

与之等效的命令不是attach-session,但我发现手册在讲述时具有误导性(以粗体显示的误导性强调):

attach-session [-dErx] [-c working-directory] [-t target-session]
(别名:附件)

如果从外部 tmux 运行,则在当前终端中创建一个新客户端并将其附加到目标会话。 如果从内部使用,请切换当前客户端。

等效的实际上是switch-client可以切换客户端的会话(即:当已经连接时)。

switch-client [-Elnpr] [-c target-client] [-t target-session] [-T key-table]
(别名:switchc)

将客户端 target-client 的当前会话切换到 target-session。

如果未指定客户,则为当前客户。

因此,手动登录后,您可以首先将当前会话 ID 存储在某处:

tmux display-message -p '#S' > /tmp/sessiontokill

不需要,变量#{client_last_session}将在下一次切换后立即采用该值。

切换到目标会话:

tmux switch-client -t 0 

并杀死现在无用和未使用的先前会话,这样它就不会随着时间的推移而累积:

tmux kill-session -t "$(tmux display-message -p '#{client_last_session}')"

如果仍然有一个或多个客户端使用同一会话(例如:由于某些网络故障),则可以通过执行以下操作将它们全部删除:

  • 查找使用此会话的客户端列表
  • 从列表中删除当前客户端
  • 分离 (+ -HUP) 所有其他客户端

for i in $(tmux list-clients -F '#{client_name}' -t "$(tmux display-message -p '#S')" | grep -Fvx "$(tmux display-message -p '#{client_name}')"); do
        tmux detach-client -P -t "$i"
done

我希望一旦这些命令包含在某些脚本中或者别名/函数中,这可以有所帮助。

相关内容