安卓 Termux 一切到后台 SSH 就断?mosh 加两个隐藏坑,一次修到位
URL
date
Aug 9, 2026
slug
termux-mosh-android-macos-persistent-shell
summary
安卓杀后台+TCP脆弱导致Termux SSH频繁断连:保活三开关+mosh+tmux,附zsh PATH与macOS防火墙两个坑
status
Published
tags
termux
mosh
ssh
macos
android
type
Post



在安卓手机上用 Termux SSH 连自己的 Mac 或服务器,是很多折腾党的日常。但你大概率遇到过这个场景:SSH 连得好好的,切出去回个微信,再切回来 - 会话已经断了,跑了一半的下载任务也没了。
client_loop: send disconnect: Broken pipe
Connection to your-host closed.这篇讲清楚三件事:为什么会断、怎么修到基本不再烦你、以及两个 macOS 上常见但容易被忽略的坑(zsh PATH 和应用防火墙)。全程可复现。
一、为什么切出 App 就断:不是网络,是安卓在杀进程
先说结论:"切出 App 秒断"这个特定症状,不是网络问题,是安卓的电源管理在杀 Termux 的后台进程(切网/断网导致的断连是另一类,下文分开处理)。
用十岁小孩能懂的话说:安卓觉得"你都不看这个 App 了,它还占着电干嘛",于是把 Termux 和它养的所有子进程(包括你的 ssh)直接掐死。SSH 是 TCP 长连接,客户端进程一死,连接自然就断。
更麻烦的是这里有两层杀手:
- 电池优化:经典的后台限制,白名单能解决
- Phantom Process Killer:Android 12 新增的机制,专杀 App 的子进程(ssh 正是 Termux 的子进程),电池白名单管不住它
所以只做"允许后台运行"是不够的,两层都要处理。
另外先把问题拆干净 - 你遇到的断连其实是两类,解法不同、不能互相替代:
- A 类:客户端进程被杀(切 App 后安卓杀 Termux)→ 靠本节的保活三开关
- B 类:进程还活着,但 TCP 连接断了(切 WiFi/5G、电梯断网、NAT 超时)→ 靠下一节的 mosh
Broken pipe 两类都可能触发,判别方法:切回 Termux 看 shell 提示符还在不在 - 提示符都没了是 A 类,提示符在但连接死了是 B 类。二、基础保活:三个开关
1. Termux wake lock
在 Termux 里跑:
termux-wake-lock通知栏出现 "Termux wake lock held" 就生效了。
2. 电池白名单
设置 → 应用 → Termux → 电池 → 不受限制。国产 ROM(小米/华为/OPPO 等)还要在「自启动管理/后台管理」里额外加白名单。
3. 关掉 Phantom Process Killer(Android 12+)
如果做完前两步、切 App 后 Termux 里的进程还是被杀(A 类症状复发),再上这一步。需要电脑 adb:
adb shell settings put global settings_enable_monitor_phantom_procs false注意:这是全局系统设置,具体行为随 Android 小版本和厂商 ROM 有差异,系统大版本更新后可能被重置。想恢复默认就把
false 换成 true 再跑一次。三、根治方案:换 mosh
保活解决 A 类,但 B 类它管不了:WiFi 切 5G、电梯里断网几秒,TCP 连接照样死。B 类的根治是把 SSH 换成 mosh。
mosh(mobile shell)是 MIT 出的移动优先远程终端:
- UDP + 状态同步:不维护"连接",只同步终端状态。切网、换 IP、断网几分钟,回来会话原封不动
- 本地回显:打字不用等服务器回包,高延迟网络下手感天差地别
- 首次握手和认证走 SSH,之后的 UDP 流量用 mosh 自己的 AES 加密协议(注意它不支持 SSH 的端口转发等高级功能)
边界要讲清楚:mosh 抗的是网络中断。如果 mosh 客户端进程本身被安卓杀了(A 类),新起的 mosh 恢复不了旧会话 - 所以上一节的保活和这一节的 mosh 是互补关系,不是二选一,远端现场的最后一道保险是下文的 tmux。
安装两边都要装:
# 手机 Termux 侧
pkg install mosh
# Mac 侧(服务器是 Linux 就 apt install mosh)
brew install mosh然后把连接命令从
ssh user@host 换成:mosh user@host理论上到此结束。但如果你的服务器是 macOS,大概率会撞上下面两个坑 - 这才是本文的重点。
四、坑 1:明明 brew 装了,却报 command not found: mosh-server
第一次连,直接失败:
zsh:1: command not found: mosh-server
Connection to your-host closed.
/data/data/com.termux/files/usr/bin/mosh-bin: Did not find mosh server startup message.明明
brew install mosh 成功了,mosh-server 也真实存在于 /opt/homebrew/bin/,为什么找不到?根因:mosh 客户端是先 SSH 到服务器、再在远端启动 `mosh-server`。而这种非交互 SSH 场景下,zsh 不加载 `.zprofile`,Homebrew 的 PATH 根本不在环境里。
验证很简单,SSH 非交互跑一句:
ssh your-host 'echo $PATH'
# 输出: /usr/bin:/bin:/usr/sbin:/sbin <- 没有 /opt/homebrew/binzsh 的启动文件加载规则是:
Homebrew 默认把 PATH 写在
.zprofile,所以交互登录一切正常,mosh 的非交互启动路径就瞎了。修法:把 PATH 加进
.zshenv(唯一在非交互场景也会加载的文件)。Apple Silicon 的 brew 前缀是 /opt/homebrew,Intel Mac 是 /usr/local,用 brew --prefix 通吃:echo "export PATH=\"$(brew --prefix)/bin:\$PATH\"" >> ~/.zshenv验证修复:
ssh your-host 'command -v mosh-server'
# 输出: /opt/homebrew/bin/mosh-server <- 修好了顺带一提:这个坑不止咬 mosh。所有"经由非交互 SSH 调用 brew 装的工具"的场景(rsync 调远端 rsync、scp 后处理、远程脚本)都会踩,
.zshenv 一次修,同类全部受益。五、坑 2:macOS 防火墙静默拦 UDP
PATH 修好后再连,可能出现第二种症状:连接看似建立了,但终端黑屏卡住。
同一局域网/同一 VPN 内,最常见的元凶是 macOS 应用防火墙:它默认拦截未知程序的传入连接,而 mosh 恰恰需要服务器在 UDP 60000-61000 端口收包。SSH(TCP 22,由系统 sshd 处理)不受影响,所以你从来没注意过它。(如果是跨公网/路由器 NAT/云服务器安全组,UDP 还可能被这些层拦,需要相应放行 - 本文场景是内网直连,只涉及 macOS 这一层。)
修法有两种:
方案 A(最简单):连接的瞬间,Mac 屏幕上会弹窗「是否允许 mosh-server 接受传入连接?」- 点允许即可,一次生效。实测这就是最顺滑的路径,前提是你人在 Mac 前或能看到屏幕。
方案 B(无人值守):命令行加白名单,需要 sudo:
MS=$(realpath /opt/homebrew/bin/mosh-server)
sudo /usr/libexec/ApplicationFirewall/socketfilterfw --add "$MS"
sudo /usr/libexec/ApplicationFirewall/socketfilterfw --unblockapp "$MS"注意
realpath:防火墙白名单登记的是真实二进制路径,而 brew 的 mosh-server 是指向 Cellar 版本目录的软链。这意味着 brew 升级 mosh 后真实路径会变、老规则失效 - 升级后如果又开始黑屏,重跑上面两行(或再点一次弹窗允许)即可。六、最后一块拼图:服务端 tmux
mosh 解决"网络断连",tmux 兜住"客户端进程死亡":手机端 Termux 真被杀了、或者你想换台设备接管同一个现场,远端的 tmux 会话还在:
mosh user@host -- tmux new -A -s main这一条命令的意思是:mosh 连上后自动附着到名为 main 的 tmux 会话(不存在则创建)。从此手机、平板、电脑任何设备连上来,看到的都是同一个现场。
边界同样讲清楚:tmux 抗的是客户端死亡,服务器重启它也活不了 - 跨重启的任务续跑要靠任务自身的断点续传或 systemd/launchd 之类的服务化,不在本文范围。
七、完整清单(TL;DR)
手机侧(一次性):
termux-wake-lock+ 电池白名单
- Android 12+:
adb shell settings put global settings_enable_monitor_phantom_procs false
pkg install mosh
服务器侧(macOS,一次性):
brew install mosh
echo "export PATH=\"$(brew --prefix)/bin:\$PATH\"" >> ~/.zshenv- 关键,否则非交互 SSH 找不到 mosh-server
- 首次连接时在 Mac 弹窗点「允许」(或 socketfilterfw 加白名单)
日常使用:
mosh user@host -- tmux new -A -s main之后切 App、切网络、锁屏 - 只要保活生效、UDP 可达,回来时你的会话还在原地等你;就算 Termux 真被杀了,重连一条命令,tmux 里的现场也一个字不少。