tmux 断线不丢会话:远程开发的会话、窗口与复制模式实操

tmux 断线不丢会话:远程开发的会话、窗口与复制模式实操

tmuxSSH远程开发LinuxUbuntu
📶 入门 🧩 tmux · Ubuntu

跑一个四十分钟的数据迁移,SSH 到 38 分钟时公司网络闪断,连接重开,迁移进度清零,命令重跑。问题出在命令的宿主上:它挂在那个 SSH 会话下面,会话断了,内核给它发 SIGHUP,进程组跟着一起走。tmux(terminal multiplexer,终端复用器)解决的就是这个宿主问题——把进程挪进一个独立于 SSH 的常驻 server。SSH 只是它的一个屏幕,屏幕碎了进程不死。这篇文章按「装好、用会话、用窗口、回滚输出、写配置」的顺序过一遍日常够用的部分。

环境说明:Ubuntu 24.04 官方仓库带的是 tmux 3.4(apt-cache policy tmux 可查),本文命令均在此版本真实可用。tmux 3.8 新增的浮动窗格本文不涉及,低版本跟着敲不会报错。

server、session、window、pane:先分清四层

tmux 的所有状态在一个后台进程里,叫 server。你敲 tmux 时自动启动它,所有会话退出时它跟着退出,不用手动管。四层结构从外到内列出来:

概念是什么类比
server持有全部状态的常驻进程机房
session一组 window 的集合,有唯一名字一台机器
window占满整个终端的一屏,可含多个 pane显示器
pane屏幕里的一块区域,跑一个终端分屏

关键规则有一条:session 不依赖任何连接。断开(detach)只是屏幕被拿走,session、window、pane 和里面跑的所有进程原地不动;重连(attach)换个屏幕接上,输出还在原地。这就是「断线不丢」的全部原理——和让命令去跑 nohup 的区别在于,tmux 里是完整的交互环境,窗口、分屏、滚动缓冲区全都保得住。

一个常见误区:pane 和 session 是两个方向的能力。一个 session 里开满分屏,断线后全部保留;多个 session 可以各跑各的任务,互不影响。管理粒度选 session,梳理界面用 window 和 pane。

装好之后先记 detach 和 attach

安装就一行:

sudo apt install tmux
tmux -V    # tmux 3.4

第一次进入会话,直接敲 tmux,底部出现一条绿色状态栏就成了。会话记得起名字:

tmux new -s work     # 新建名为 work 的会话

操作都走一个前缀键 Ctrl+b:先按 Ctrl+b,松开,再按功能键。日常最常用的两个:

  • Ctrl+b d——detach,回到外层 shell,会话在后台继续跑
  • tmux attach -t work——attach 回 work 会话,现场原样恢复

嫌两步麻烦,tmux new -A -s work 一条顶两条:会话存在就 attach,不存在就新建。把 shell 别名指到这条命令,入口就固定了。

查后台有什么在跑:

tmux ls
# work: 3 windows (created Sat Oct 31 10:12:00 2026)

顺手记三个破坏性操作:Ctrl+b & 关当前 window(全部 pane 一起没),Ctrl+b x 关当前 pane,kill-session -t work 关整个会话。确认键别乱按,迁移跑一半被自己关掉就尴尬了。

窗口和分屏:一个终端当十个用

window 层面:Ctrl+b c 新建,Ctrl+b 0 到 9 按编号跳转,Ctrl+b n/p 顺序切换,Ctrl+b w 列出全部会话和窗口,用方向键加回车选择。窗口名默认跟随当前跑的程序,Ctrl+b , 可以手动改。改成 build、logs 这类有意义的词,Ctrl+b w 列表才有可读性。

pane 层面高频操作一组就够:

键作用
Ctrl+b %左右分屏
Ctrl+b "上下分屏
Ctrl+b 方向键在 pane 之间跳
Ctrl+b q 显示数字后按数字快速跳到目标 pane
Ctrl+b z当前 pane 临时放大到全屏,再按恢复
Ctrl+b Space在几种预设布局间轮换

Ctrl+b z 是长输出场景的救星:日志刷屏时先放大看完,再按一下回原布局。

两个进阶操作值得记。改默认前缀,.tmux.conf 里三行:

set -g prefix C-a
unbind C-b
bind C-a send-prefix

批量操作用 Ctrl+b : 进命令提示符,setw synchronize-panes on 开启同步输入——一个窗口里 4 个 pane 同时执行同一条部署命令,敲一遍就行。开完记得 off 关掉,这个模式下误操作是 4 倍伤害。

复制模式:看历史输出和复制文本

终端滚回去看之前的输出,是每个会话都有的需求,但 tmux 的滚动缓冲区不认鼠标滚轮(默认配置下),得进它自己的复制模式:Ctrl+b [。光标用方向键移动,Ctrl+b 复制模式里翻页,g 跳到缓冲区最顶,q 退出。

选中与复制:Ctrl+Space 开始选,Ctrl+w 复制并退出模式;Ctrl+b ] 把最近一次复制的内容粘贴到当前 pane。

两个让体验翻倍的配置。其一,鼠标支持:

set -g mouse on

之后滚轮直接翻历史、点击切 pane、拖边框调大小。其二,复制内容同步到本机剪贴板。tmux 的粘贴缓冲区是 server 内部的,和本地剪贴板不通。SSH 场景下的通行做法是 OSC 52 转发:

set -s set-clipboard on

终端配好就能直接粘贴。

滚动缓冲区默认 2000 行,编译日志动辄上万行,建议放大:

set -g history-limit 100000

三段能直接抄的配置

~/.tmux.conf 只在 server 启动时读一次,改完要对现有会话生效,Ctrl+b : 执行 source-file ~/.tmux.conf。一段低风险起手配置:

set -g mouse on
set -g history-limit 100000
set -g base-index 1           # window 编号从 1 开始
setw -g pane-base-index 1     # pane 编号从 1 开始
set -g renumber-windows on    # 关掉窗口后自动补编号空位
set -g escape-time 10         # Esc 响应更快,vim 用户有感
set -g status-interval 5      # 状态栏刷新间隔(秒)

配置文件不是 shell 脚本,$()、管道这些 shell 语法在里面不认,只能写 tmux 命令,一行一条。

还有一条对 vim/emacs 用户很重要。tmux 里跑的全屏程序退出后,屏幕内容直接消失,回滚历史看不到。原因和修法:

set -g alternate-screen on

打开后,进入 vim、htop 这类程序前后的输出都保留在滚动缓冲区里,退出后照常 Ctrl+b [ 回看。

常见问题

断线后进程真的还活着吗?

活着。session 与连接解耦,detach 只是屏幕被拿走。验证方法:断线重连后 tmux ls 会话还在,attach 回去看输出完整保留。

已经跑起来的长命令没放进 tmux,SSH 要断了怎么办?

事中补救只有 disown 配合 nohup 这一档手段,且只对还没产生终端输出的场景勉强有效,交互式程序救不回来。这类任务的正确姿势是开跑前先 tmux new -s job 再执行。

tmux ls 报 no server running on /tmp/tmux-0/default?

server 已经退出,会话自然全部不存在——最后一个会话关闭时 server 跟着退出。这不是故障,重新 tmux new 即可。想避免误关,重要会话养成 Ctrl+b d detach 的习惯,别用 exit。

attach 时提示 sessions should be nested with care?

在 tmux 会话里又敲了 tmux attach。设置 TMUX 环境变量区分内外即可,典型做法是在 shell 配置里给外层命令加判断,嵌套会话没有意义,跳回外层或先 detach。

复制的内容粘贴出来是乱的?

粘贴目标是 tmux 内部缓冲区,走 Ctrl+b ];想粘贴到本机,开 set-clipboard on(OSC 52)或用支持剪贴板转发的终端。两套剪贴板分清楚,问题就消失。

窗口编号断了 0、2、4?

窗口按创建顺序占第一个空位,关闭造成空洞。renumber-windows on 让编号自动连续,或者临时用 movew -r 重排一次。


tmux 的价值可以用一句话压缩:把「进程的生死」和「连接的生死」拆开。做到这一件事,SSH 闪断只是换块屏幕,四十分钟能跑完的迁移再也不用从零开始。命令行东西不多,Ctrl+b d 和 tmux new -A -s work 先用起来,剩下的窗口、分屏、复制模式按需补。