使用 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
-t
tmux
将在远程端分配 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。我就是这样做的:
我的正式登录 shell 是
/bin/bash
.如果您想更改服务器上的登录 shell,请在连接时使用,例如chsh -s /bin/bash
。您可以指定/etc/shells
(运行cat /etc/shells
以检查文件)中列出的任何 shell。然后在最后我的
.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 a
or 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时应配置此选项。SHELL
getpwuid(3)
/bin/sh
tmux
在我的设置中,我什至不使用default-shell
并tmux
在窗口/窗格中使用我的登录 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
我希望一旦这些命令包含在某些脚本中或者别名/函数中,这可以有所帮助。