远程编译怕被 SSH 掉线带走,Tmux 会话分离之后还能附着回去吗?

远程机器上编译或者跑批处理,SSH 一掉线,前台进程经常跟着没了。再连上去,开出来的是一条新终端,刚才那条任务也不在了。

tmux 官方 Wiki 给自己的定位是终端复用器:在一个终端里切换多个程序,把它们分离之后仍在后台继续跑,再附着到同一条或另一条终端上。入门页 列过典型用途,其中一条是保护远程服务器上正在运行的程序,避免连接断开把任务带走。页里举的场景也很常见。白天在公司用 SSH 连上远程机,在 tmux 里开编辑器、编译和几个 shell,离开时把会话分离。晚上换一台电脑再连同一台服务器,附着回去就能从中断的地方继续。GNU Screen 属于同一类工具,这里只按 tmux 的会话来讲。

用法围着自己的会话转:先创建,需要离开时分离,下次连上再附着。创建会话用 tmux new,需要名字时加 -s,例如 tmux new -smysession。不给名字的话,默认会从 0、1 往下排,自己起名会更好找。默认会新建一个窗口,里面是一个 pane,跑着 shell,底部通常还有一条绿色状态栏,左边是会话名,中间是窗口列表,当前窗口后面会标 *,上一个窗口标 -。前缀键默认是 C-b(Ctrl 和 b),先松开再按后面的键。分离会话是 C-b d,客户端退出,会话和里面的程序继续留在服务器上,终端里通常会打出 detached 和会话名。重新连上这台机器之后,tmux attach 会附着到最近用过、且尚未被附着的会话。要指定名字就用 tmux attach -tmysession。入门页还写了 tmux new -Asmysession:会话已在就附着,不在就创建。查看现有会话用 tmux ls。

还有一层容易忽略:只要任务已经跑在 tmux 会话里,SSH 被直接掐断时,client 没了,后台的 server 和会话仍在。不必把「先按一次 C-b d」当成唯一保命动作。手动分离更适合你主动离开,或准备换一台电脑再附着。入门页把这几件事并列过:防止远程连接断开带走进程,也允许同一台服务器上的程序从不同的本地电脑访问,顺便在一个终端里同时摆多个程序,有点像窗口管理器。

Wiki 里的层次是 client、session、window、pane。你从 SSH 里启动的是 client,状态保存在后台的 tmux server。每个 session 里可以有多个 window,window 之下还可以再拆 pane。附着回来之后,原先开着的窗口都还在,并不需要把编译进程重新丢到前台。第一次用的时候,先把创建、分离、再附着跑通,再补窗口和分屏也不迟:C-b c 开新窗口,C-b n / C-b p 在窗口之间切换,C-b l 回到上一个当前窗口,C-b % 左右拆分当前 pane,C-b " 上下拆分。忘了按键时,C-b ? 会列出默认绑定和简短说明,C-b : 打开命令提示符,可以输入和 shell 里类似的 tmux 命令。配置文件是家目录里的 .tmux.conf,入门页写明它只在 server 首次启动时执行,改完若 server 已在跑,要用 source-file 重新读入,不会每开一个会话就自动跑一遍。

只操作自己的会话即可,不要去附着不属于自己的会话。若所有会话、窗口和 pane 都没了,server 会自行退出。也可以在命令提示符里用 kill-server 把整个 server 关掉。更细的命令和选项可以再查 man 1 tmux 和官方 Wiki。

你现在是编译到一半才想起还没开会话,还是开工之前就会先 tmux new?