00tmux 是什么
一句话:tmux 是一个「永远不掉线的虚拟终端管家」。
你的电脑 → SSH → 远程服务器。平时你敲的每个命令都挂在这次 SSH 连接上,连接一断,进程全死。tmux 把你的命令交给它自己去跑,SSH 只是「看屏幕的一个窗口」。
对比一下没有 tmux 的情况:SSH 断开 → 内核向前台进程组发 SIGHUP → 命令全部收到信号退出。
四层结构(记住三个词就够了)
pane:htop
session 会话 → window 窗口 → pane 面板。日常 90% 的时间你只需要会话。
SIGHUP,pi 会优雅关闭并退出(源码 interactive-mode.js 里注册了 SIGHUP/SIGTERM 处理)。在 tmux 里跑,pty 由 tmux 持有,pi 收不到 SIGHUP,于是继续干活。01安装
tmux 要装在 远程服务器 上(干活的是它),不是你的 Mac。先确认:
tmux -V # 例如输出 tmux 3.4
| 系统 | 安装命令 |
|---|---|
| Debian / Ubuntu | sudo apt update && sudo apt install -y tmux |
| CentOS / RHEL 7 | sudo yum install -y tmux |
| Fedora / RHEL 8+ / Rocky / Alma | sudo dnf install -y tmux |
| Arch / Manjaro | sudo pacman -S tmux |
| Alpine | sudo apk add tmux |
| openSUSE | sudo zypper install -y tmux |
| macOS(本地用) | brew install tmux |
没有 sudo?可以试 conda install -c conda-forge tmux、nix-shell -p tmux,或下载静态二进制放到 ~/bin;实在不行先用 screen(概念相同,见 第 8 章对比表)。
tmux -V 记下来。02第一课:创建 / 断开 / 连回 ★
这一章是整个教程的核心。练熟它,你就已经拿到 80% 的价值了。
① 创建会话
tmux new -s pi # -s 是 session 名字,不取名字会自动叫 0、1…
预期结果:屏幕底部出现一条绿色状态栏 ——
[pi] 0:bash* "myserver" 14:32 12-Jul-26
读法:[pi] 是会话名;0:bash* 是第 0 号窗口跑着 bash,* 表示当前窗口;右边是主机名和时间。
echo $TMUX 有输出就是「在」。或者直接看底部有没有那条状态栏。② 认识前缀键:所有快捷键的「开场白」
tmux 的快捷键都是 两步:先按 Ctrl+b(前缀键),松开,再按功能键。
③ 断开 detach:工作留在服务器上继续
# 跑一个"永不停"的命令,验证 tmux 真的在替你扛 while true; do echo "$(date +%T) 我还在跑,进程号 $$"; sleep 5; done
看到每 5 秒刷一行时间戳后,按 Ctrl+b松手 →d。预期:
[detached (from session pi)]
ps -ef | grep sleep,它还在。d = detach。等价于在 shell 里敲 tmux detach。
④ 查看有哪些会话
tmux ls
pi: 1 windows (created Sat Jul 12 14:30:00 2026) (detached)
(detached)= 没人在看它,但它活着 —— 这就是你要的状态(attached)= 有人正在看
⑤ 连回去 attach
tmux attach -t pi # -t = target;也常写成 tmux a -t pi
屏幕跳回你离开时的样子,循环还在刷时间戳,中间那段时间的日志一行不少 —— 这就证明它在你断开期间一直在工作。按 Ctrl+c 停掉循环。
tmux new -s pi → Ctrl+b d → 关掉 SSH/断网/合盖 →
重新 ssh 登录 → tmux attach -t pi偷懒神技:-A
tmux new -A -s pi # 已存在就 attach,不存在才新建 —— 每天只用敲这一条 # 顺手做个别名 echo "alias p='tmux new -A -s pi'" >> ~/.bashrc && source ~/.bashrc
多个终端同时看同一个会话
在第二个 SSH 终端(或手机上)再执行一次 tmux attach -t pi,两个屏幕 同步显示 同一画面,断开任意一个都不影响另一个。适合公司 + 家里 + 手机同时盯进度,或分享给同事。
干净地结束会话
exit # 推荐:最后一个窗口里敲 exit(或 Ctrl+d) tmux kill-session -t pi # 从外面杀掉指定会话 tmux kill-server # 杀掉所有会话(等于关掉整个管家)
03第二课:窗口 window
一个会话里可以开多个窗口,每个窗口是独立的全屏终端,像浏览器标签页。
| 按键(先 Ctrl+b 松手再按) | 作用 |
|---|---|
| c | 新建窗口(create) |
| n / p | 下一个 / 上一个窗口 |
| 0 … 9 | 跳到第 N 号窗口 |
| , | 给当前窗口改名 |
| w | 弹出窗口列表(上下键选,回车跳转) |
| & | 关闭当前窗口(会问 y/n) |
| f | 按名字搜索窗口 |
| l | 回到上一个用过的窗口 |
| $ / s | 会话改名 / 会话列表切换 |
跟练:开三个窗口,分别干三件事
tmux new -s dev # 窗口 0:先留着当 shell # ——— Ctrl+b 松手,按 c → 新窗口 1 ——— cd ~/myproject && pi # 让 pi 在窗口 1 里跑 # ——— Ctrl+b 松手,按 c → 新窗口 2 ——— tail -f logs/app.log # 盯日志 # ——— Ctrl+b 松手,按 c → 新窗口 3 ——— htop # 看资源(没装就 top) # ——— 改名:Ctrl+b 松手,按 , → 输入 pi → 回车
[dev] 0:bash 1:pi* 2:logs 3:top
用 Ctrl+b 1/2/3 来回切,用 w 看列表跳转。
04第三课:面板 pane
| 按键 | 作用 |
|---|---|
| % / " | 左右分屏 / 上下分屏 |
| 方向键 | 切换到相邻面板 |
| o / ; | 依次跳下一个 / 跳回上一个用过的面板 |
| z | 当前面板全屏 / 还原(超好用 ★) |
| x | 关闭当前面板(问 y/n) |
| q | 短暂显示面板编号,按数字直接跳 |
| 空格 | 切换布局(平铺/横排/竖排…) |
| Ctrl+方向键(或 Alt+方向键) | 调整面板大小(可连按) |
| { / } | 和相邻面板交换位置 |
| ! | 把当前面板「拆」成独立窗口 |
跟练:一边让 pi 写代码,一边看日志
tmux new -s work # 左面板 cd ~/myproject && pi # ——— Ctrl+b 松手,按 % → 右边出现新面板 ——— tail -f /var/log/nginx/access.log # ——— Ctrl+b 松手,按 " → 下面再来一个 ——— watch -n 2 'ps aux --sort=-%cpu | head -8' # ——— 想专心看 pi:Ctrl+b 松手,按 z 全屏;再按一次还原 ———
配了鼠标(见 第 7 章)后,可以直接用鼠标点面板切换、拖边框调整大小、滚轮滚屏。
05第四课:滚屏与复制粘贴
滚屏
配了鼠标就滚轮直接滚。没配鼠标时:
Ctrl+b [ → 进入 copy mode(可以滚动) 方向键 / PageUp / PageDown q → 退出(新手常以为卡死了,其实是在这个模式里)
默认只保留 2000 行历史,第 7 章会调大。
复制
有鼠标时最省事:按住 Shift(iTerm2/macOS 上按住 Option)用鼠标划选 —— 这是「绕过 tmux」用终端自己的选择,然后 Cmd+C / Ctrl+Shift+C 复制到 本地 剪贴板。
用 tmux 的 copy mode:
Ctrl+b [ → 进入 copy mode 空格 → 开始选择 方向键 → 扩大选择 回车 → 复制进 tmux 的 buffer Ctrl+b ] → 粘贴
06pi 用户实战场景
场景 1:让 pi 在你合上电脑后继续干活 ★
# ① 登录服务器 ssh you@server # ② 进入(或创建)会话 tmux new -A -s pi # ③ 进项目,启动 pi cd ~/myproject pi # → 给它一个长任务,等它开始转圈 # ④ 走人:Ctrl+b 松手,按 d # → 看到 [detached (from session pi)] # ⑤ 现在可以随便断网、关终端、关笔记本
回来时:
ssh you@server tmux attach -t pi # 或先 tmux ls 看一下
pi 还在转,或者已经干完了,中途输出一行不少。
万一 tmux 也没了(机器重启 / 被人 kill-server),pi 的会话是实时落盘的:
cd ~/myproject pi -c # 继续最近一次会话 # 或 pi -r # 从列表里挑
message_end)。断开瞬间正在流式生成的那一条回复会丢,
之前所有已完成的对话和工具结果都在。场景 2:同时跑多个 pi
tmux new -s multi # 窗口 1:Ctrl+b c → cd ~/backend && pi # 窗口 2:Ctrl+b c → cd ~/frontend && pi # 分别改名:Ctrl+b , → backend / frontend
Ctrl+b 1/2 在两个 pi 之间切换;Ctrl+b d 一起挂起,两个都继续跑。
场景 3 & 4:日志分屏 / 超长命令
- 分屏:Ctrl+b % 右边
tail -f;需要专注时 Ctrl+b z 把 pi 全屏。 - 超长命令:
docker compose build --no-cache后直接 Ctrl+b d 去睡觉,第二天tmux attach看结果。
场景 5:pi 的快捷键会冲突吗?
不会。tmux 前缀只占用 Ctrl+b,pi 常用的 Ctrl+T、Ctrl+O、Ctrl+X、Shift+Tab、Escape 都不受影响。
唯一要注意:别用 Ctrl+b 做别的事;Shift+Enter 换行需要第 7 章的额外配置。
07必做配置 ~/.tmux.conf
cat > ~/.tmux.conf <<'EOF' # ============ 基础体验 ============ # 开启鼠标:滚轮滚屏、点面板切换、拖边框调大小、划选复制 set -g mouse on # 历史缓冲从默认 2000 行提高到 50000 行 set -g history-limit 50000 # 窗口 / 面板从 1 开始编号 set -g base-index 1 set -g pane-base-index 1 setw -g renumber-windows on # 加快按键响应(对 vim / 快速连按友好) set -sg escape-time 10 # 正确声明 256 色 / 真彩色,减少乱码 set -g default-terminal "tmux-256color" set -ga terminal-overrides ",*256col*:Tc" # ============ pi 专用 ============ # pi 需要扩展键上报,否则 Shift+Enter / Ctrl+Enter 会被当成普通 Enter set -g extended-keys on # 仅 tmux >= 3.5 可用;版本低于 3.5 请删掉下面这行 set -g extended-keys-format csi-u # ============ 复制粘贴(可选)============ set -g set-clipboard on EOF
生效方式(任选其一):
# 方式一:在 tmux 外面执行 tmux source-file ~/.tmux.conf # 方式二:在 tmux 里按 Ctrl+b 松手,按 : ,输入下面这行回车 source-file ~/.tmux.conf
| tmux 版本 | extended-keys-format csi-u |
|---|---|
| ≥ 3.5 | 保留(推荐) |
| 3.2 – 3.4 | 删掉这一行,只留 extended-keys on;pi 仍支持 tmux 默认的 xterm 格式 |
| < 3.2 | 不支持 extended-keys,Shift+Enter 修不好,建议升级 tmux |
tmux kill-server 然后 tmux new -A -s pi。先确认里面没有正在跑的 pi。set -g prefix C-Space / unbind C-b / bind C-Space send-prefix08常见坑与排错
| 现象 | 原因 / 解决 |
|---|---|
| Ctrl+b d 没反应 | ① 别按住 Ctrl+b,要「松手再按 d」;② tmux show-options -g prefix 确认前缀;③ echo $TMUX 确认你在 tmux 里 |
sessions should be nested with care… | 你在本地 tmux 里又 ssh 到远程开 tmux(嵌套了)。给内层发前缀要按 两次 Ctrl+b |
no server running on /tmp/tmux-1000/default | 会话全没了(重启 / kill-server / OOM)。里面的 pi 也没了 → pi -c 续会话 |
| 断线重连后花屏 / 乱码 | tmux 里按 Ctrl+b r 刷新;或 tmux refresh-client -t pi;再不行敲 reset |
| 状态栏乱码、颜色不对 | 确认 echo $TERM 是 xterm-256color 之类;检查第 7 章两行 terminal 配置 |
| 中文错位 / locale 报错 | export LANG=en_US.UTF-8(或 zh_CN.UTF-8)写进 ~/.bashrc;用 locale 检查 |
| 进了一个滚不动的界面 | 那是 copy mode,按 q 退出 |
| pi 里 Shift+Enter 不换行 | 缺 extended-keys 配置;改完要 tmux kill-server 彻底重启 |
| 想用终端原生选择 | 划选时按住 Shift(iTerm2 / macOS 按 Option) |
| 想确认 pi 是否真在跑 | ps aux | grep -i "[p]i";tmux ls 看会话是否还在 |
替代方案对比
| 方案 | 交互式 TUI(pi) | 断线后存活 | 说明 |
|---|---|---|---|
| tmux | ✅ | ✅ | 官方推荐,功能最完整 |
screen | ✅ | ✅ | 老牌同类工具,前缀 Ctrl+a;screen -S pi / Ctrl+a d / screen -r pi |
nohup pi -p "任务" > task.log 2>&1 & | ❌ 无界面 | ✅ | 只能跑非交互模式,tail -f task.log 看进度 |
setsid pi … | ❌ | ✅ | 同上,日志重定向要自己管 |
| systemd user service | ❌ | ✅ | 适合长期常驻任务,配置较重 |
09速查表
日常五件套
会话 / 窗口 / 面板
| 会话 | 窗口 | 面板 |
|---|---|---|
tmux new -s NAME 新建tmux new -A -s NAME 连回或新建 ★tmux ls 列表tmux attach -t NAME 连回Ctrl+b d 断开 Ctrl+b $ 改名 Ctrl+b s 切换 tmux kill-session -t NAME
|
Ctrl+b c 新建 Ctrl+b 1…9 跳转 Ctrl+b w 列表 Ctrl+b , 改名 Ctrl+b & 关闭 Ctrl+b l 上一个 |
Ctrl+b % / " 分屏 Ctrl+b 方向键 切换 Ctrl+b z 全屏 ★ Ctrl+b x 关闭 Ctrl+b 空格 换布局 Ctrl+b ! 变独立窗口 鼠标拖边框调大小(需 mouse on) |
其他
source-file ~/.tmux.conf10pi 标准作业流程
# ——— 每天开工 ——— ssh you@server tmux new -A -s pi # 一条命令回到老地方 cd ~/myproject pi # 断过就用 pi -c 续会话 # ——— 要断网 / 关电脑 / 走人 ——— # 按 Ctrl+b,松手,按 d # 看到 [detached (from session pi)] 就可以安心走了 # ——— 回来 ——— ssh you@server tmux attach -t pi # ——— 确认它真的在干活(另开一个 SSH)——— tmux ls # 会话还在 = pi 还在 ps aux | grep -i "[p]i" # 进程还在 = 真在跑
三个心理障碍,提前打消
- 「Ctrl+b d 之后命令会不会停?」 不会。detach 只是把显示器拔掉,机器还在跑。2.3 节的
while实验就是用来验证这个的。 - 「关了终端会不会影响它?」 只要 pi 在 tmux 里就不影响。tmux server 是独立进程(
ps -ef | grep tmux)。 - 「tmux 会话会被谁杀掉?」 ① 服务器关机/重启;② 有人执行
tmux kill-server或kill-session;③ 内存不足被 OOM 杀(罕见)。日常最需要提防的是别手贱kill-server。
11tmux × AI Agent 调优手册
这一章面向「长期用 tmux 托管 AI agent(pi / Claude Code / Codex CLI 等)」的场景。每节都是「配置 + 为什么 + 怎么验证」。
11.1 让 agent 的按键正常工作(扩展键)
set -g extended-keys on set -g extended-keys-format csi-u # 仅 tmux >= 3.5;3.2–3.4 删掉这行
为什么:TUI 类 agent 需要区分 Shift+Enter、Ctrl+Enter、Ctrl+Backspace 这类组合键。tmux 默认会把它们压成普通 Enter,于是「多行输入」失效。pi 的文档明确要求 extended-keys on。
验证:tmux show -g extended-keys;改完必须 tmux kill-server 新开会话才生效。版本不够时只留 extended-keys on。
11.2 ESC 与 Alt 键不粘手
set -sg escape-time 10
为什么:tmux 默认要等 500ms 来判断「单独的 ESC」还是「Alt 组合键的前缀」。对 agent TUI 来说,这意味着按 Escape 中止任务要顿半秒才有反应,Alt+Enter(pi 的排队 follow-up 键)也可能被拆成两个按键。本地 10ms 够用;SSH 延迟大设 50–100 更稳。
搭配 pi:pi 自己也有 PI_TUI_ESC_TIMEOUT(SSH 下默认 100ms,本地 10ms)。如果 Alt 键经常被误判成 Escape,优先调大 tmux 的 escape-time。
11.3 焦点事件(attach/detach 后画面错位)
set -g focus-events on
为什么:切换窗口/重新 attach 时让 TUI 知道「焦点回来了」,触发重绘,画面错位和「假装卡住」会少很多。
注意:tmux man page 明确说改这个选项后要重新 detach + attach 一次才生效。
11.4 把 agent 的输出复制到本地剪贴板(OSC52)
set -g set-clipboard on
为什么:tmux 3.2 起 set-clipboard 默认是 external。设成 on 后 tmux 既接受应用(pi)发来的 OSC52,也会把它转发给你 本地 终端 —— 这样在服务器 tmux 里划选复制,回到本地可以直接 Cmd+V 粘贴。
前提:本地终端支持 OSC52(iTerm2 / Kitty / WezTerm / Ghostty / 新版 Windows Terminal)。macOS 自带 Terminal.app 不支持,只能继续用 Shift/Option 原生选择。
printf '\033]52;c;%s\a' "$(printf hello | base64)"
11.5 一眼看出「哪个 agent 在干活」
# 让终端标题栏显示会话名 + 面板标题
set -g set-titles on
set -g set-titles-string "#S | #T"
# 别让 shell 的自动改名覆盖 agent 设置的标题
setw -g automatic-rename off
# 在每个面板顶部显示编号与标题
set -g pane-border-status top
set -g pane-border-format " #{pane_index} #{pane_title} #{?pane_active,#[fg=green]●ACTIVE,#[default]} "为什么:多个窗口跑多个 agent 时,你能直接看到「pi / review / watch」而不是一堆 bash。#T 是面板标题,应用通过 OSC 0/2 设置它(allow-set-title 默认开启)。
加分项:配合 pi 自带示例扩展 examples/extensions/titlebar-spinner.ts,终端标题栏会在 agent 工作时转圈,窗口最小化也能看出它有没有卡死。
验证:tmux show -g set-titles、tmux show -g allow-set-title。
11.6 agent 崩了,最后那屏别消失
set -g remain-on-exit on
为什么:agent 进程退出后,面板默认自动关闭,最后那一屏报错就永远看不到了。开启后面板保留(显示 “Pane is dead”),你可以用 Ctrl+b [ 翻看崩溃前的输出,再 Ctrl+b x 关掉它。
只对某个窗口生效:tmux new-window -k(进程退出后保留面板并等待按键),或用 -m "自定义提示语" 设置 remain-on-exit-format。
11.7 从外部「投喂」和「读取」agent(脚本化)
# 把一整段 prompt 原样送进 pi 所在窗口(:1 是窗口号) tmux send-keys -t pi:1 -l "$(cat prompt.md)" tmux send-keys -t pi:1 Enter # 读取 agent 屏幕上最后 50 行(做监控 / 存档 / 告警) tmux capture-pane -p -t pi:1 -S -50 # 实时盯梢 watch -n 2 'tmux capture-pane -p -t pi:1 | tail -n 20'
为什么:send-keys 默认把参数按「键名」解析,;、-、# 之类字符会被吃掉,所以 长文本一定要加 -l(literal,按字面字节发送)。这是 shell 脚本驱动 agent 的标准姿势。
注意:-l 里的换行会被当作字面换行,多行 prompt 建议逐行发送,最后单独发 Enter 提交。
11.8 状态栏显示 agent 存活
#!/usr/bin/env bash # 把 PATTERN 换成你服务器上 pi 的进程特征(先跑 ps -ef | grep pi 看一眼) PATTERN="pi-coding-agent|/bin/pi" if pgrep -f "$PATTERN" >/dev/null 2>&1; then printf '#[fg=green]● pi 在跑' else printf '#[fg=colour240]○ pi 空闲' fi
set -g status-interval 5 set -g status-right "#(~/bin/pi-status) | %H:%M"
chmod +x ~/bin/pi-status
为什么:一眼判断「agent 还在不在」,不用切窗口。
性能提醒:#() 每 status-interval 秒执行一次并且会 fork 子进程,脚本要足够轻,别在里面跑全量 ps aux 解析。
11.9 多 agent 布局一键搭建
#!/usr/bin/env bash # 2 个 agent + 1 个监视面板 set -euo pipefail SESS=agents PROJ="$HOME/project" # 改成你的项目路径 if tmux has-session -t "$SESS" 2>/dev/null; then tmux attach -t "$SESS"; exit 0 fi tmux new-session -d -s "$SESS" -n main -c "$PROJ" tmux new-window -t "$SESS" -n review -c "$PROJ" tmux new-window -t "$SESS" -n watch -c "$HOME" # 主力和审查各起一个 pi tmux send-keys -t "$SESS:main" 'pi' C-m tmux send-keys -t "$SESS:review" 'pi -r' C-m # 监视窗口实时回放主力 agent 的屏幕 tmux send-keys -t "$SESS:watch" 'watch -n 5 "tmux capture-pane -p -t agents:main | tail -n 20"' C-m tmux select-window -t "$SESS:main" tmux attach -t "$SESS"
说明:C-m 就是回车;-d 表示后台建会话;-c 指定工作目录。写脚本的好处是布局可复现,换台机器粘过去就能用。
chmod +x ~/bin/agents-layout
11.10 稳定性与资源
# 杀掉某个会话时,自动切到别的会话,而不是直接把你踢出 tmux set -g detach-on-destroy off # 面板历史:agent 输出量大,50000 行足够;别开到 100 万(每个面板都占内存) set -g history-limit 50000
环境变量:tmux 里的新窗口继承的是 tmux server 启动时 的环境。API key 放在 ~/.bashrc 一般没问题;临时 export 的可以显式注入:
tmux set-environment -g OPENAI_API_KEY "$OPENAI_API_KEY"
tmux show-environment -g 会明文列出这些变量,同机上其他能 attach 到你 tmux socket 的进程/人都能看到。共享服务器上慎用。11.11 调优配置速用版
# ——— AI agent 专用区块 ——— set -g extended-keys on set -g extended-keys-format csi-u # tmux >= 3.5 set -sg escape-time 10 set -g focus-events on set -g set-clipboard on set -g set-titles on set -g set-titles-string "#S | #T" setw -g automatic-rename off set -g remain-on-exit on set -g detach-on-destroy off set -g status-interval 5 set -g status-right "#(~/bin/pi-status) | %H:%M"
A附录:把文件传到服务器
在你 本地 Mac 上执行(you@server 换成你的服务器地址):
scp ~/tmux-tutorial.md ~/tmux-tutorial.html you@server:~/
如果服务器没开 scp,用管道:
cat ~/tmux-tutorial.md | ssh you@server 'cat > ~/tmux-tutorial.md' cat ~/tmux-tutorial.html | ssh you@server 'cat > ~/tmux-tutorial.html'
HTML 是单文件、零依赖的:服务器上不需要任何运行时;也可以直接 open ~/tmux-tutorial.html(Mac)在本地浏览器里看。