tmux —— 会话保持与分屏协作
tmux —— 会话保持与分屏协作
分类:04 文本处理(终端效率) 适用:全平台(tmux 3.x) 一句话:SSH 断了任务还在跑,一个终端里开多个窗格,还能多人同看一个会话。
1. 它解决什么问题
- 跑长任务(备份、编译、数据导入)时 SSH 断开,进程被 SIGHUP 杀掉。
- 一边看日志一边敲命令,反复切换窗口。
- 远程协助同事,让他看到你的终端操作。
- 服务器上没有图形界面,需要多路并行。
替代品:screen(更老,功能少)、byobu(tmux 的封装)、zellij(新式)。
2. 安装
apt install -y tmux
dnf install -y tmux
apk add tmux
3. 会话管理(核心)
tmux # 新建匿名会话
tmux new -s work # 新建命名会话
tmux new -s work -d # 后台新建(不切换进去)
tmux ls # 列出会话
tmux attach -t work # 接入
tmux a # 接入最近一个
tmux a -t work # 简写
tmux kill-session -t work # 杀掉会话
tmux kill-server # 杀掉所有会话(⚠️)
tmux rename-session -t old new
在会话内:
| 快捷键 | 作用 |
|---|---|
Ctrl-b d |
分离(detach),会话继续跑 |
Ctrl-b $ |
重命名会话 |
Ctrl-b s |
会话列表中选择 |
Ctrl-b ( / ) |
切到上/下一个会话 |
Ctrl-b是默认前缀键(prefix),下面写作C-b。所有快捷键都是先按C-b松开,再按功能键。
4. 窗口(window)
C-b c # 新建窗口
C-b , # 重命名窗口
C-b n / p # 下一个 / 上一个
C-b 0-9 # 切到第 n 个
C-b w # 窗口列表
C-b & # 关闭当前窗口(会确认)
C-b l # 上次使用的窗口
命令行操作:
tmux new-window -n logs 'tail -f /var/log/nginx/error.log'
tmux list-windows -t work
tmux select-window -t work:2
5. 窗格(pane)
C-b % # 左右分屏
C-b " # 上下分屏
C-b 方向键 # 切换窗格
C-b o # 循环切换
C-b z # 当前窗格最大化/还原(超好用)
C-b x # 关闭窗格
C-b ! # 把窗格拆成独立窗口
C-b { / } # 与相邻窗格交换位置
C-b 空格 # 切换布局
C-b q # 显示窗格编号
C-b Alt+方向 # 调整窗格大小
6. 滚动与复制
C-b [ # 进入复制模式(可上下翻页)
# 复制模式内:
# 方向键/PgUp/PgDn 移动
# Space 开始选择,Enter 复制并退出
# q 退出
C-b ] # 粘贴
C-b ~ # 显示最近的消息(调试用)
开启鼠标(在 ~/.tmux.conf):
set -g mouse on
开启后可以直接滚轮翻页、拖拽选中、点击切窗格。
与系统剪贴板互通(Linux + X11/Wayland):
set -g set-clipboard on
# 或者复制时调用 xclip
bind -T copy-mode-vi Enter send-keys -X copy-pipe-and-cancel "xclip -i -selection clipboard"
7. 常用配置 ~/.tmux.conf
# 前缀改为 Ctrl-a(更顺手,注意与 screen/bash 冲突)
set -g prefix C-a
unbind C-b
bind C-a send-prefix
# 从 1 开始编号,符合直觉
set -g base-index 1
setw -g pane-base-index 1
# 鼠标
set -g mouse on
# 历史行数
set -g history-limit 50000
# 关闭时自动重排窗口编号
set -g renumber-windows on
# 更快的按键响应(vim 用户)
set -sg escape-time 10
# 状态栏
set -g status-interval 5
set -g status-left "[#S] "
set -g status-right "%Y-%m-%d %H:%M"
# 分屏快捷键更顺手(| 和 -)
bind | split-window -h -c "#{pane_current_path}"
bind - split-window -v -c "#{pane_current_path}"
# 用 vim 键位在复制模式移动
setw -g mode-keys vi
重载配置:
tmux source-file ~/.tmux.conf
8. 脚本化与自动化
# 一条命令搭好排障布局
tmux new-session -d -s debug -n monitor
tmux split-window -h -t debug
tmux split-window -v -t debug:0.1
tmux send-keys -t debug:0.0 'top' C-m
tmux send-keys -t debug:0.1 'tail -f /var/log/app/error.log' C-m
tmux send-keys -t debug:0.2 'watch -n2 "ss -s"' C-m
tmux attach -t debug
常用命令:
| 命令 | 作用 |
|---|---|
send-keys -t <target> 'cmd' C-m |
在指定窗格执行命令 |
capture-pane -t <target> -p |
抓取窗格当前内容(可用于日志留存) |
capture-pane -t <target> -p -S -1000 |
抓最近 1000 行 |
pipe-pane -t <target> -o 'cat >> /tmp/pane.log' |
把输出持续写入文件 |
respawn-pane -k -t <target> 'cmd' |
重启窗格内进程 |
set-option -t <target> remain-on-exit on |
进程退出后保留窗格,便于看报错 |
9. 实战场景
9.1 长任务防断线
tmux new -s import
# 在会话里执行
mysql -u root -p db < big_dump.sql
# 觉得要断网:C-b d 分离
# 之后回来
tmux a -t import
9.2 多人共享同一会话(远程协助)
# A 创建会话
tmux new -s pair
# B 通过 SSH 连同一台机器
tmux attach -t pair
两人看到同一个屏幕,输入会互相干扰。要只读观察,用 attach -r:
tmux attach -r -t pair # 只读模式
更规范的协作可以用 wemux 或 tmate(走公网中继)。
9.3 排障四分屏
tmux new -s t -d
tmux split-window -h -t t
tmux split-window -v -t t:0.0
tmux split-window -v -t t:0.2
tmux send-keys -t t:0.0 'top' C-m
tmux send-keys -t t:0.1 'iostat -x 1' C-m
tmux send-keys -t t:0.2 'tail -f /var/log/messages' C-m
tmux send-keys -t t:0.3 'watch -n 1 "ss -s"' C-m
tmux attach -t t
9.4 留存窗格输出作为证据
tmux pipe-pane -t work:0.0 -o 'cat >> /tmp/session-$(date +%F).log'
# 结束后
tmux pipe-pane -t work:0.0 # 停止
9.5 开机自动拉起会话
# crontab
@reboot tmux new-session -d -s monitor 'bash /opt/scripts/monitor.sh'
10. 常见坑
C-b被其他程序占用:Emacs、screen 也用C-b,改前缀为C-a或C-\。- 嵌套 tmux:在 tmux 里再 ssh 到一台机器又开 tmux,内层要用
C-b C-b发前缀。 - 分离后进程被杀:通常是脚本里
exec或进程不处理 SIGHUP;tmux 本身不会杀会话内进程。 - 重启机器会话全丢:tmux 不持久化,需要
tmux-resurrect/tmux-continuum插件。 - 复制到系统剪贴板失败:需要
xclip/wl-copy,且 SSH 场景只能依赖终端自身的选中复制。 mouse on影响选中:开启后按住 Shift 才是终端原生选择。- 状态栏中文乱码:终端 locale 与字体问题,不是 tmux 配置问题。
tmux ls显示(attached)但仍占用:说明有客户端没正常断开,tmux attach -d强制踢掉。kill-server会杀掉所有会话,包括同事在用的,执行前tmux ls确认。- 日志文件过大:
pipe-pane是持续追加,配合 logrotate 或定时截断。 send-keys里的引号:命令含空格/引号时用单引号包住整条,C-m表示回车。
11. 速查表
tmux new -s name # 新建
tmux ls # 列表
tmux a -t name # 接入
tmux kill-session -t name # 删除
tmux new -d -s name # 后台新建
C-b d # 分离
# 窗口
C-b c / , / n / p / w / & / 0-9
# 窗格
C-b % / " / 方向键 / o / z / x / !
# 复制
C-b [ / ] ,Space 选择,Enter 复制
# 脚本
tmux send-keys -t s:0.0 'cmd' C-m
tmux capture-pane -t s:0.0 -p -S -500
tmux pipe-pane -t s:0.0 -o 'cat >> /tmp/x.log'