Post

用 tmux 守护 SSH 远程工作流

用 tmux 守护 SSH 远程工作流

想要解决的问题

经常用 SSH 连远程的开发环境,挂着 Claude Code 跑长任务。 但是网络一断、电脑一关,所有终端窗口都没了,连接回来又要从头开始。

更烦的是一个项目通常需要好几个终端:

  • 一个跑 claude
  • 一个 vim 编辑代码
  • 一个 docker logs 看日志
  • 一个做 git 操作

每次重新打开都要 cd 到目录、启动各种进程,又费劲又容易忘。

理想状态是:

  • SSH 断了,远端的进程还在跑,重连后能立刻回到刚才的状态
  • 窗口/分屏的布局一次配置好,之后直接复用

tmux 两件事都能做。

工作原理

tmux 在服务器端运行一个持久的会话守护进程。 SSH 断开时,tmux 会话不会终止,而是继续在后台运行。 下次 SSH 登录后,可以重新 attach 这个会话, 所有进程(包括 Claude Code)都保持原样。

持久会话

第一次登录

1
2
3
4
5
6
7
8
9
10
ssh your-server

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

# 在 tmux 里启动 Claude Code
claude

# 按 Ctrl+b 再按 d 来 detach(脱离会话,保持后台运行)
# 或者直接关闭 SSH 客户端

第二次登录(甚至从另一台电脑)

1
2
3
4
ssh your-server

# 回到之前的 Claude Code 实例
tmux attach -t claude

常用命令

命令作用
tmux new -s <name>创建新会话
tmux attach -t <name>接入会话
tmux ls列出所有会话
Ctrl+b d脱离当前会话(保持运行)
tmux kill-session -t <name>结束会话
Ctrl+b :命令模式

三层结构

要把布局自动化之前,先理清 tmux 的三层结构。

1
2
3
4
5
6
Session(会话)
├── Window(窗口)        ← 类似浏览器标签页
│   ├── Pane(窗格)      ← 窗口内的分屏区域
│   └── Pane
├── Window
└── Window
层级类比常用操作
Session一个完整的工作空间tmux newtmux attach
Window浏览器标签页Ctrl+b c 新建、Ctrl+b n 下一个、Ctrl+b <数字> 切换
Pane窗口内的分屏Ctrl+b % 垂直分、Ctrl+b " 水平分、Ctrl+b <方向键> 切换

常用快捷键

1
2
3
4
5
6
7
8
9
10
Ctrl+b c        # 新建窗口
Ctrl+b ,        # 重命名当前窗口
Ctrl+b n        # 下一个窗口
Ctrl+b p        # 上一个窗口
Ctrl+b <数字>   # 切换到指定窗口

Ctrl+b %        # 垂直分屏(左右)
Ctrl+b "        # 水平分屏(上下)
Ctrl+b <方向键> # 在窗格间移动
Ctrl+b z        # 最大化/还原当前窗格

复用窗口布局

每次手动 split、cd、启动进程比较麻烦。 把布局写成一个脚本,下次只要执行一下就能恢复整套布局。

~/bin/dev.sh

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#!/bin/bash
SESSION="dev"
PROJ=~/workspace/myproj

# 会话已存在就直接 attach
tmux has-session -t $SESSION 2>/dev/null
if [ $? -eq 0 ]; then
    tmux attach -t $SESSION
    exit 0
fi

# Window 0:左 claude,右 vim
tmux new-session -d -s $SESSION -n 'code' -c $PROJ
tmux send-keys -t $SESSION:0 'claude' C-m
tmux split-window -h -t $SESSION:0 -c $PROJ
tmux send-keys -t $SESSION:0.1 'vim' C-m

# Window 1:跑日志
tmux new-window -t $SESSION:1 -n 'logs' -c $PROJ
tmux send-keys -t $SESSION:1 'docker compose logs -f' C-m

# Window 2:留着做 git 操作
tmux new-window -t $SESSION:2 -n 'git' -c $PROJ

tmux select-window -t $SESSION:0
tmux attach -t $SESSION

加上执行权限:

1
chmod +x ~/bin/dev.sh

之后每次 SSH 上来:

1
~/bin/dev.sh
  • 第一次执行:从零创建好整套布局
  • 之后执行:直接 attach 回已经在跑的会话

每个项目可以复制一份脚本,改一下 SESSIONPROJ 就能用。

注意事项

  • 服务器重启会丢失:服务器重启后 tmux 会话和其中的进程都会终止。 需要跨重启持久化的话,可以结合 tmux-resurrect 这类插件。
  • 多设备切换:在公司电脑 detach,回家用家里的电脑 attach 到同一个会话, Claude Code 会继续从上次的状态接着跑。
  • 异常断开:网络闪断重连后,部分交互式输出可能显示异常, 按回车或 Ctrl+l 刷新即可。
This post is licensed under CC BY 4.0 by the author.