连接服务器做计算时,我经常需要同时处理几件事:一个终端跑程序,一个终端看日志,再开一个终端检查 CPU、内存和磁盘占用。只靠不断新建 SSH 连接当然也能完成,但窗口一多,很容易找不到刚才的命令,本地内存占用也会跟着增加;网络一断,前台任务还有可能退出。

这正是 tmux 适合解决的问题。

Summary

tmux 可以把一个终端拆成多个分栏和窗口,并把整套工作环境保留在服务器上。我的本地电脑只需要开一个 Windows Terminal,既减少了多开终端的内存压力,也能在办公室和宿舍的电脑之间继续同一个工作区。不过,tmux 里的任务不会因为本地终端关闭而停止,远端资源异常时需要回到服务器处理。

一个终端,也可以是一套工作台

tmux 是一个终端复用器。刚接触时,可以把它理解成运行在服务器上的终端工作台。

它有三层结构:

层级可以怎样理解适合放什么
Session一套完整的工作区一个项目或一次实验
Window工作区里的标签页运行、日志、监控、文件操作
Pane一个窗口里的分栏同时观察多个命令

这三个概念看起来有点绕,举例来说为 WRF 模拟建立名为 wrf 的 session,其中开三个 window:run 用来提交任务,log 用来跟踪日志,monitor 用来看资源;在 log 窗口里再分成两个 pane,分别查看标准输出和报错信息。

我目前的使用情景类似下面这样

少开几个本地窗口,内存也轻松一些

我使用的是 Windows 11。Windows Terminal 的界面、字体渲染和整体体验都比较现代,但如果同时开好几个独立窗口,本地电脑的内存占用也会增加。对内存本来就紧张的电脑来说,为了同时看几个 SSH 终端付出这部分开销,我觉得不太划算。Warp 等现代终端在类似使用方式下也会遇到这个问题。

可能有人会问:嫌内存不够,为什么不用 Xshell?

Xshell 的内存占用确实很少,这一点很有优势。不过我自己用下来,还是觉得它的界面风格比较老旧,偶尔还会遇到字体显示问题。终端毕竟是每天都要看的工作界面,我更喜欢 Windows Terminal 这种现代化终端的观感。

所以我目前的组合是:Windows Terminal + tmux

本地只保留一个 Windows Terminal 窗口,服务器上的分栏、多窗口和 session 都交给 tmux 管理。增加 pane 和 window 时,并不需要在本地继续新开一批终端软件窗口。这样既保留了现代终端的显示体验,也明显减轻了多开窗口带来的本地内存压力。

分栏:同时看到命令、日志和资源

分栏是 tmux 最直观的优势。

在一个窗口里,可以把左侧留给正在运行的脚本,右侧执行 tail -f 查看日志;也可以在下方再开一个小区域运行 topbtopwatch。这些内容同时显示,不用在多个本地终端之间来回切换。

默认快捷键以 Ctrl+b 开头:

操作快捷键
左右分栏Ctrl+b,再按 %
上下分栏Ctrl+b,再按 "
在分栏之间移动Ctrl+b,再按方向键
临时放大当前分栏Ctrl+b,再按 z
关闭当前分栏在分栏中输入 exit

这里的按法需要特别说明:先按一次 Ctrl+b 并松开,再按后面的键。它并不是把三个键同时按住。

多窗口:把不同任务分开

一个 window 可以有多个 pane,但我不太建议把所有内容都塞进同一屏。分栏太多以后,每一块都很小,日志和长命令反而更难看。

更舒服的做法是按任务拆成多个 window:

  • run:启动程序或提交作业;
  • log:查看输出和错误日志;
  • monitor:检查 CPU、内存和 IO;
  • shell:处理文件和临时执行命令。

常用快捷键也不多:

操作快捷键
新建窗口Ctrl+b,再按 c
切换到下一个窗口Ctrl+b,再按 n
切换到上一个窗口Ctrl+b,再按 p
按编号切换窗口Ctrl+b,再按 09
重命名当前窗口Ctrl+b,再按 ,

分栏解决“同时看”,窗口解决“分类放”。两者配合起来,终端里的工作路径会清楚很多。

本地断连,工作区还在服务器上

tmux 更重要的能力是 detach 和 attach。

先在服务器上建立一个 session:

tmux new -s work

任务启动后,按 Ctrl+b,再按 d,就可以主动离开当前 session。之后即使 SSH 断开、本地电脑休眠或终端软件关闭,tmux session 以及其中的程序仍会留在服务器上。

重新连接服务器后,可以先查看已有 session:

tmux ls

再回到刚才的工作区:

tmux attach -t work

如果希望 session 存在时直接进入、不存在时自动创建,可以使用:

tmux new -A -s work

这对长时间运行的预处理、模式模拟、数据下载和模型训练很实用。临时断网不会让已经跑了几个小时的任务从头再来,换一台电脑也能继续查看同一套终端状态。

从办公室换到宿舍,工作区还在原地

我觉得 tmux 很亮眼的一个场景,是在不同电脑之间继续工作。

例如白天在办公室电脑上连接服务器,打开一个 tmux session。里面已经安排好了 WRF 运行窗口、日志窗口、资源监控窗口,也切到了对应目录。下班后回到宿舍,如果临时需要处理一点工作,不用先远程控制办公室电脑。

直接在宿舍电脑上打开 Windows Terminal,SSH 连接同一台服务器,再执行:

tmux attach -t work

之前的 window、pane、当前目录、命令输出和正在运行的程序都还在。除了两台电脑屏幕尺寸不同可能让分栏大小有所调整,看到的基本就是办公室里的同一个工作区,可以从刚才停下的位置继续。

Tip

技术上确实可以无缝接着干。不过,生活上不推荐在宿舍工作哦。

Note

tmux 保留的是服务器上的终端会话。服务器重启、tmux server 被结束、进程被管理员终止或触发 OOM 后,任务仍然会消失。它不提供计算检查点,也不能替代程序自己的断点续算机制。

快捷键与界面,都是上手成本

tmux 的上手门槛主要来自快捷键。

很多终端软件已经有自己的标签页、分栏、复制和滚动快捷键,tmux 又在里面加了一层。默认操作还要先按前缀键 Ctrl+b,初次使用时很容易忘记,也经常分不清当前控制的是本地终端、SSH 会话,还是 tmux 里的 pane。

复制文本和回看历史输出也会让新手困惑。鼠标滚轮在本地终端和 tmux 之间的行为可能不同,进入复制模式后又有一套按键。配置文件可以把快捷键改得更顺手,但一开始就照搬复杂配置,反而容易增加排查成本。

我更建议先只记住这些操作:

tmux new -s work       新建 session
Ctrl+b  %              左右分栏
Ctrl+b  "              上下分栏
Ctrl+b  方向键         切换分栏
Ctrl+b  c              新建窗口
Ctrl+b  n / p          切换窗口
Ctrl+b  d              离开但保留 session
tmux attach -t work    重新进入 session

用顺以后,再考虑在 ~/.tmux.conf 中开启鼠标:

set -g mouse on

然后重新进入 tmux,或者在当前 session 中执行:

tmux source-file ~/.tmux.conf

tmux 的学习曲线确实比普通终端陡。它的价值也很明确:一旦形成固定用法,远程工作区会稳定很多。这里没有必要一次学完全部快捷键,先把 session、window 和 pane 用起来就够了。

嫌界面朴素,可以试试 Oh my tmux

tmux 的默认界面很克制,底部只有一条简单的状态栏。实用归实用,确实谈不上精致。如果觉得它不好看,可以试试 Oh my tmux

很多人会把 Oh my tmux 称作 tmux 插件,准确一点说,它是一套已经整理好的 tmux 配置。它提供了更完整的状态栏、Powerline 风格主题、鼠标模式、pane 导航和一系列常用设置。对于不想从空白的 .tmux.conf 开始配置的人,它能省下不少时间。

不过,它也不只是换个配色。Oh my tmux 会加入自己的快捷键和行为设置,部分操作与原生 tmux 不同。安装前最好备份现有配置,后续的个性化修改也应该写到它提供的本地配置文件中。如果只想改颜色,却不想改变已经形成的快捷键习惯,需要先看清楚它的配置说明。

不想折腾配置,可以看看 Zellij

Zellij 是另一个终端复用器,它是 tmux 的替代方案,不是 tmux 插件。它同样支持 session、tab 和 pane,默认界面更加现代,底部还会显示当前可以使用的快捷键。刚装好就能获得比较完整的视觉与交互体验,这也是它“开箱即用”的地方。

如果觉得 tmux 默认界面太朴素,又嫌配置 Oh my tmux 麻烦,Zellij 是一个很自然的选择。它也支持布局和插件,后面想继续定制仍然有空间。

它的限制也要提前说清楚:Zellij 需要在服务器上额外安装,共享服务器部分环境也可能不允许用户自行放置可执行文件。tmux 在很多 Linux 服务器上更常见,资料和现成配置也更多。我的选择仍然是 Windows Terminal + tmux;如果从零开始,又更在意默认界面和按键提示,可以同时试一下 Zellij,再决定哪个更顺手。

断连后,远端任务仍在继续

tmux 保证本地断连后任务继续运行,这项优势也有一个需要提前知道的边界。

如果 WRF 前/后处理或其他程序出现异常,把服务器磁盘 IO 跑满,或者持续占用过多 CPU、内存,关闭本地的 Windows Terminal 不会让它停止。这个动作只会断开当前 tmux client,服务器上的 session 和程序仍在运行。

Warning

使用 tmux 以后,不要再把“关闭本地终端”当成停止远端任务的方法。发现资源异常时,需要重新进入 session 用 Ctrl+c 停止程序,或者通过服务器的进程管理、Slurm/PBS 调度命令取消作业。如果 IO 已经拥塞到无法登录,只能从其他登录节点处理或联系管理员。

这个问题不影响 tmux 的实用性,只是使用习惯需要跟着改变。启动长任务后多看一眼日志和资源占用,长时间计算优先交给调度系统,会比依赖本地终端是否开着更可靠。

总结

tmux 最吸引我的地方,是它把分栏、多窗口和远程会话保留放到了一起。一个 session 可以对应一个 WRF 项目,window 用来区分运行、日志和监控,pane 用来同时查看关键状态。本地只开一个 Windows Terminal 就能管理整套工作区,不必为了多任务再堆一排终端窗口。

办公室电脑断开后,回到宿舍直接连接服务器,再 attach 到同一个 session,之前的窗口、分栏和命令输出都还在。这种跨设备延续工作区的能力,是普通本地多窗口很难提供的。

它也有清楚的使用成本。默认快捷键不算直观,复制、滚动和窗口切换都需要适应。觉得界面朴素,可以用 Oh my tmux! 改善;不想折腾配置,可以试试开箱即用的 Zellij。无论选哪一个,都要记住:本地终端关闭以后,远端任务仍然可能继续运行。

相关阅读