tmux:终端多路复用器

你是否考虑希望能在关闭终端窗口或 SSH 连接后,程序仍能在后台运行?是否希望在下次打开终端时仍能保留先前的状态上下文?或是希望和其他用户共享终端内容——以实现结对编程?终端多路复用器程序 tmux 能够解决你的上述困扰。

传统意义上来讲,Linux 操作系统会为连接上的每个终端(包括本地终端以及 SSH 会话等)分配对应的终端设备文件。该设备文件以 tty(电传打字机)或 pts(伪终端)设备命名。“电传打字机”则得名于早期的计算机设备使用打字机而非显示屏将程序的运行结果进行输出。我们常说的“将结果打印在屏幕上”中的“打印”一词也是得名于此。

一个老式电传打字机,背后是看起来像电路板或是 CRT 显示屏
意大利制造商 Olivetti 生产的老式电传打字机;源图片知识共享署名-相同方式分享 3.0 协议发布

本文介绍的开源软件 tmux 得名于终端多路复用器(Terminal multiplexer)。其中,多路复用指通过技术手段使用户在一个终端中能够切换或并行查看多个 Shell,甚至进行窗口化。同样地,一个终端设备也可以被多个终端同时共享。

Linux 系统会为每个用户终端分配供用户输入命令并提供执行环境的程序,被称为 Shell(外壳)程序。大多数 Linux 发行版的默认外壳程序是 bash

安装 tmux

tmux 被收录于大多数发行版的软件包管理器中。根据发行版系统的不同,可能需要执行下述命令之一以安装 tmux 程序:

sudo pacman -S tmux
sudo apt-get install tmux
sudo dnf install tmux
sudo yum install tmux

如果你的系统软件包管理器中不含 tmux 程序(很罕见!),则应考虑通过编译方式安装 tmux 软件,请见此文指引。

新建、缩小以及恢复窗口

tmux 使用术语面板(Panel)来表示其创建的一个单独的命令执行环境。而面板被包裹在窗口(Window)中。这些由 tmux 定义的概念允许用户在一个终端设备内灵活管理多个分离的执行环境。为便于描述,下文中使用“本地 Shell”指代系统为用户默认分配的终端环境;而“tmux 中的执行环境”则表明 tmux 中的某一个面板中的执行环境。

新建窗口

就像我们在 Windows 中输入 cmd 打开命令提示符程序一样。要在终端设备中创建一个新执行环境,只需在本地 Shell 中键入:

tmux

注意到屏幕像是被清空了,然后重新打开了一个终端一样吗?事实上,上述指令将 tmux 程序运行于用户终端设备中,并且提供一个新的面板,便于用户在其中执行命令与计算机交互。

如何区分现在是位于“tmux 中的执行环境”还是“本地 Shell”环境呢?注意在 tmux 中的执行环境中,终端最底部有一个绿色的指示条,依据设置不同,可能显示终端代号、窗口名称以及时间等信息。若底部此状态条,则说明位于本地 Shell 中。

在 tmux 中运行的程序不会因为终端的关闭或断开而停止。如果此时关闭该终端(窗口)或者是断开 SSH 远程链接,tmux 会话中运行的程序仍将运行。

缩小窗口

当你需要从 tmux 中的执行环境切换回本地 Shell 而希望保存工作时,需要指示 tmux 脱离(Detach)当前环境:

在 tmux 执行环境中,按 Ctrl+B,然后按 D

其中,Ctrl+B 是 tmux 程序定义的功能键:为了在 tmux 会话内向 tmux 本身发送消息,需要在大多数指令前附 Ctrl+B 组合键。

从 tmux 中的执行环境切换回本地 Shell 后,应注意到终端下方的状态栏消失了。

用户可以向 tmux 中的执行环境发送 EOF(默认为 Ctrl+D)或 exit 指令以关闭面板

恢复窗口

好了,现在我们脱离了一个 tmux 会话,并且退回到本地 Shell 环境了。我们如何重新打开以恢复这个 tmux 中的执行环境呢?首先我们需要查看 tmux 中正在管理哪些窗口:

tmux ls

在本地 Shell 中执行上述命令后,你会获得类似下述的结果:

0: 1 windows (created Mon Nov 16 22:13:01 2020)

其中,冒号前的数字 0 代表活跃窗口的名称。如果 tmux 同时管理多个窗口,则结果中应含有多行。

现在我们希望恢复名称为 0 的终端窗口,我们在本地 Shell 中执行下述命令:

tmux attach -t 0

其中,-t 参数后接的是要恢复的会话名称。上述例子还可以简写为 tmux attach,这将恢复最后脱离的会话(在本例中为会话 0)。你甚至可以使两个不同终端恢复同一个 tmux 会话,这将实现共享屏幕。

当用户通过远程方式连接到远程计算机时,tmux 特别有用。由 tmux 管理的会话不会因为用户断开终端连接而终止:所以网络问题或用户手动关闭终端链接均不会使远程计算机中运行的程序终止。

在本地 Shell 中使用 tmux 新建会话;使用 tmux ls 查看已有会话;使用 tmux attach -t <tag> 恢复会话。在 tmux 中的执行环境中使用 Ctrl+B,然后 D 以脱离。

回滚历史记录

由于技术限制,tmux 不兼容通过滚动屏幕的方式查看曾经显示在屏幕上的历史信息。我们可以通过在 tmux 的执行环境中进入复印模式(copy-mode)查看历史消息:

Ctrl+B,然后 [

注意会话右上角显示的 xxx/xxx 指示符,表示目前正在位于回滚模式中。此时通过键盘上的方向键或翻页键即可实现查看历史消息的功能。按 q 键从回滚模式中返回 tmux 中的执行环境。

tmux 默认记录每个会话至多 8192 行回滚的信息,该值可以通过配置调整。

在窗口中管理多个会话

截止到目前,我们在单个 tmux 窗口中只有一个会话。不过实际上,如果终端显示空间足够大,我们可以在单个 tmux 窗口中管理多个会话。在 tmux 中的执行环境中:

Ctrl+B,然后 % 以水平分隔当前窗口至多个会话
Ctrl+B,然后 " 以垂直分隔当前窗口至多个会话

那要怎么把光标切换到想要的会话呢?tmux 中的光标切换非常直观,只需要按 Ctrl+B,然后按方向键将光标移动至希望聚焦的会话即可。