‹ 指南

Mosh 会话被杀掉后,自己能回来 v26.0.22+

被系统杀掉、被划掉、崩溃、手机重启:下次打开 Term,mosh 会话自己接回来。

需要 Term v26.0.22 或更高版本。

撰写于 · 更新于

被杀掉的是哪一半

手机不是服务器。为了省电,HarmonyOS 会挂起长时间待在后台的应用;内存紧张时干脆把它结束掉。你自己从最近任务里划掉、应用崩溃、手机重启,结果都一样:进程没了。

但对 mosh 来说,没的只是客户端那一半。主机上的 mosh-server 还在运行,你的 shell、正在跑的程序、当前目录、刚 export 的环境变量,都原封不动地留在那里,只是再没有谁知道怎么连回去。以前这就是一次真正的损失:重新登录、重新 cd、重新跑一遍,主机上还多留下一个没人认领的 mosh-server。

现在它自己回来

如果 Term 被杀掉时 mosh 会话还活着,下次打开它会自己接回来:不用重新走一遍 SSH 登录,也不会新起一个 mosh-server,接回来的就是原来那个 shell。在主机那一端看来,这跟你从 Wi-Fi 切到蜂窝网络没什么两样,而这本来就是 mosh 最擅长的事。

下面两张是真机上的验证。杀之前先在会话里 export MARK=resume_proof_77,新开的 shell 不可能有这个变量。强制结束应用、重新打开、再跑一次 env | grep MARK,它还在。同一个 shell,不是悄悄重连了一次。

杀之前 · 11:24 一个名为 Sandbox (mosh) 的会话:export MARK=resume_proof_77 之后,env | grep MARK 打印出 MARK=resume_proof_77。状态栏时间 11:24。
杀之前:会话里设了 MARK=resume_proof_77,env | grep MARK 认得它。紧接着应用被强制结束。
恢复之后 · 11:27 同一个会话在应用重启之后:整屏历史原样保留,末尾又跑了一次 env | grep MARK,同样打印出 MARK=resume_proof_77。状态栏时间 11:27。
恢复之后:三分钟后重新打开应用,整屏重绘,上面的历史一行不少;再跑一次 env | grep MARK,resume_proof_77 还在。同一个 shell,同一个进程。

恢复的那几秒

启动时如果有可以恢复的会话,Term 会先弹一个小窗:应用自己的转圈图标,加上「正在恢复 N 个会话…」,下面是「已完成 / 总数」的计数。多个会话一起接,不用一个个排队。全部接上就直接关掉,你落回原来的标签页。

主机列表上方的模态小窗:转圈图标、Resuming 1 session… 和 0 / 1 的计数。
启动时:恢复过程中的小窗,背后的界面照常显示。它自己会关,不用点。
主机列表:Sandbox (mosh) 那一行带着 MOSH 标记和一个绿色圆点。
接上之后,主机列表里那台 mosh 主机重新亮起绿点:会话是活的,标签页也回来了。

如果服务器已经不在了

能不能接回来,并没有保证:主机重启过、有人手动收掉了 mosh-server,或者它已经超过「Mosh 会话超时」自己退出了。

这种时候 Term 会试大约 5 秒,然后把结果写在同一个小窗上(N 个已恢复 · M 个无法连接),停一下再关。它只问这一次:接不上的会话,下次启动不会再提起。

主机上那个 mosh-server 到底愿意等多久,由「设置 → 终端 → Mosh 会话超时」决定:1 天到 1 个月,默认 1 周,也可以选永不。等得越久,隔了很长时间再打开也越有可能接得回来;共用的主机上则短一点更干净。

同一个小窗,计数那一行显示 0 resumed · 1 unreachable。
对面没了:试了大约五秒之后,小窗直接给出结果,停一下自己关掉。这个会话不会再被提起。

相关:Mosh 进阶设置:端口、会话超时、初始化脚本

几点说明

正常关标签页不会留下东西

这套机制只在应用「非正常死亡」时才起作用。你自己关掉 mosh 标签页时,Term 照旧会去结束服务器上那个会话,必要时再用 SSH 连回去把残留进程收掉:主机上不会因此攒下孤儿 mosh-server,下次启动也没有任何东西要恢复。

这些信息不出这台手机

Term 重新接回来所需要的东西,只存在于你手机本机,不上云、不同步、不经过任何第三方。它跟你的主机和私钥放在同一个地方,受同样的保护:静态加密,而且手机开机之后没有解锁过,就连读都读不出来。会话一结束,这条记录立刻删除。

接回来的是画面,不是历史

这一点跟平时的 mosh 一样:mosh 传的是当前这一屏,不是逐行的字节流,所以恢复之后能回滚的历史仍然只有 mosh 会话本来就有的那些。要真正的回看,还是在服务器上跑 tmux/zellij,而且 tmux new -A -s main 配合 mosh 初始化脚本,本来就是最省心的组合。