Termux 自动化运维实战:定时任务防杀与 Tailscale 跨网络访问
在 Android 手机上跑自动化任务,像在流沙上盖房子。你以为地基打好了,一觉醒来,发现系统已经把你的进程连根拔起,不留字条,不给解释。《庄子》里说「适来,夫子时也;适去,夫子顺也」,Android 的后台管理大概深谙此道,只是被杀的进程未必那么豁达。
这篇文章记录一次 Termux 定时任务失踪事件的完整排查,以及由此引出的一个教训:你以为你要的是一个 IP 地址,其实你要的是一条回家的路。
问题现象
某天早晨,发现 Termux 上的定时采集任务没有执行。手机 IP 能 ping 通,但 SSH(端口 8022)连接被拒绝。就像敲一扇有灯光的门,里面有人,但没人来开。
排查过程
第一步:确认网络与服务状态
| |
Termux 进程还在,但 sshd 没有运行。门在,锁在,钥匙孔被人用水泥封了。
第二步:排查 sshd 未自启的原因
手动启动 sshd 后 SSH 进去检查,发现 Termux 使用 termux-services(基于 runit)管理服务。sshd 的服务目录下存在一个 down 文件——runit 的设计哲学是:有这个文件就不自动启动,沉默而忠实。
| |
删除 down 文件,让 runit 接管:
| |
注意:SSH 会话中
$SVDIR环境变量为空,必须手动 export 后才能使用sv命令。这是一个容易反复踩的坑。
第三步:排查定时任务未执行的原因
查看 cron 日志,最后一条记录停在前一天下午。之后晚间和次日早晨的任务都没有执行:
| |
而 crond 进程是当天早上才启动的(通过 PID 文件时间戳判断),早晨的任务在 crond 启动之前就已经错过了。cron 的脾气众所周知:错过就是错过,不补,不道歉,不解释。
根因:Android 系统在夜间杀掉了 Termux 进程,crond 随之停止。Termux 重启后 crond 恢复,但错过的任务石沉大海。
解决方案
方案一:配置服务自启动
确保 sshd 和 crond 都由 termux-services 管理且没有 down 文件:
| |
方案二:@reboot 补救机制
既然 Android 杀进程不可避免,那就换个思路:不阻止死亡,而是在复活后检查遗产。
利用 cronie 的 @reboot 指令(crond 启动时执行一次),加一个检查脚本:
| |
在 crontab 中添加:
| |
sleep 60 是给依赖服务恢复留出时间。这样即使 Termux 被杀后重启,crond 恢复时会自动检查并补跑漏掉的任务。逻辑很简单:醒来第一件事,看看今天的活干了没有。
方案三:手机端防杀措施
在小米手机上做以下设置,降低 Termux 被杀的概率:
- 设置 Termux 为自启动应用
- 在最近任务中锁定 Termux(下拉锁定)
- 电池设置中将 Termux 设为「无限制」
- Termux 内执行
termux-wake-lock获取唤醒锁
这些措施降低概率,但不能杜绝。Android 的后台管理是个黑箱,你做了所有正确的事,它仍然可能在某个深夜动手。所以方案二的补救机制才是真正的兜底。
需求溯源:从获取 IP 到 Tailscale 组网
原始需求
写一个脚本获取手机 IP 地址。
追问根本问题
手机局域网 IP(如 192.168.x.x)会随 WiFi 网络变化。但更关键的问题是:如果手机和电脑不在同一个网络,即使知道局域网 IP 也连不上。192.168.x.x 是局域网地址,出了这个路由器的门,就是一串没有意义的数字。
真正要解决的不是「获取 IP」,而是「跨网络远程访问手机」。写一个 IP 查询脚本,就像给一个找不到路的人发一张详细的室内平面图——精确,但无用。
最短路径:Tailscale
Tailscale 为每台设备分配固定的虚拟 IP(100.x.x.x),不管设备在哪个物理网络,都能直接互联。
工作原理
- 每台设备运行 Tailscale 客户端,生成 WireGuard 密钥对
- 设备向 Tailscale 协调服务器注册公钥和网络位置
- 协调服务器告诉每台设备其他设备的地址和公钥
- 设备之间直接建立 WireGuard 点对点加密隧道(NAT 穿透)
- 只有极少数穿不透的情况才走 DERP 中继服务器
核心特点:协调服务器只交换地址信息,实际数据点对点直连,不经过 Tailscale 服务器。这个设计很克制——中心只做介绍人,不做中间商。
免费版(Personal)限制
| 项目 | 限制 |
|---|---|
| 用户数 | 3 人 |
| 设备数 | 100 台 |
| 子网路由 | 无限制 |
| 商业用途 | 不允许 |
个人使用完全够用,官方承诺个人免费版永久免费。
部署效果
| |
手机在家里、在办公室、在旅途中、用移动数据,都是同一个地址。地址不再是物理位置的附庸,而是身份的锚点。
与其他网络工具的兼容性
Tailscale 只接管 100.x.x.x 地址段的流量,其他网络工具工作在应用层,两者互不干扰。
写在最后
这次排查从一个没跑的 cron 任务开始,经过 sshd 自启修复、补救机制设计、需求溯源,最终落在 Tailscale 组网。回头看,最有价值的不是任何一个技术方案,而是那个追问:「你要解决的根本问题是什么?」
在技术工作中,人们常常带着一个具体方案来,方案本身没有错,但它回答的可能是一个错误的问题。写一个获取 IP 的脚本,逻辑上无可挑剔,但它解决的是「不知道 IP 是多少」,而真正的困境是「知道了也连不上」。《韩非子》说「郑人买履」,量好了尺码却忘了试鞋。技术世界里这样的事,每天都在发生。