OpenClash 一启动,网络就断了,或者内核刚起来又退出,先别急着换配置。退出不等于内存不足,要先找 OOM 证据。 OOM 是 Out of Memory,指内存不足;Linux 在这种情况下可能杀掉进程,释放内存。
比较有效的顺序是:保存故障前后日志,确认被杀的是哪个进程;再分别观察启动、规则更新和正常运行时的内存;有证据指向规则加载,才检查规则数量与格式。只看一张“内存用了 90%”的截图,很难判断原因。
以下依据 2026 年 11 月 7 日核对的 OpenClash、mihomo 和 Linux 官方资料,适用于 OpenWrt 类系统上的排查。没有在具体路由器上做性能实测,也没有可通用的内存容量门槛。
先留下日志,确认是不是 OOM
OpenClash 是管理 mihomo 代理核心的 LuCI 插件,LuCI 就是路由器的网页管理界面。系统、插件和代理核心要分开看。路由器总内存紧张,不等于所有内存都被 mihomo 占用;代理核心退出,也不一定经过了系统的 OOM 处理。
在自己已登录的路由器终端里,逐条运行下面的只读命令。它们用于查看状态,不会修改配置:
free
cat /proc/meminfo
dmesg
logread
free 看物理内存和交换空间概况,dmesg 看内核日志,logread 看系统日志。固件可能裁剪工具或参数,先用不带选项的写法;缺少工具时查看本机帮助或后台日志,不要照搬其他发行版的参数。
先把完整输出保存到自己的电脑,再查找 invoked oom-killer、Out of memory、Killed process 等文字。它们是排查线索,实际措辞会随内核版本和情况变化。重点核对故障时间、相邻的内存信息,以及 Killed process 后面的 PID 和进程名;PID 就是系统分配给进程的编号。
“某进程触发 oom-killer”和“某进程被杀”也要分开读。触发内存分配失败的进程,未必就是最后被杀的那个;被杀的进程也未必是唯一造成内存压力的程序。只截其中一行,会丢掉判断需要的上下文。
如果没有找到 OOM 记录,先保留“原因未确定”这个结论,继续看同一时刻的内核和插件报错。日志缺失也不能证明从未发生 OOM。已经断网或反复重启时,先恢复此前能用的配置,别为了补一张截图连续触发故障。对外提供日志前,删掉订阅地址、密码、令牌和不需要公开的地址信息。
看可用内存,再看核心进程占了多少
/proc/meminfo 里容易混淆的是 MemFree 和 MemAvailable。前者是当前空闲内存;后者估计在不使用交换空间的情况下,新程序还能用到多少内存,会考虑部分可回收缓存。MemFree 很低,不能单独作为内存耗尽的证据。 MemAvailable 也只是估计值,不能保证下一次分配一定成功。
要看核心进程,可以先运行 ps,找到实际运行的核心及其 PID。进程名以本机显示为准,不要假定一定叫 mihomo。然后查看对应的 status 文件:
# 把 1234 换成刚刚核对的核心 PID
cat /proc/1234/status
不需要把整页都读懂,先找这几项:
| 字段 | 表示什么 | 怎么用 |
|---|---|---|
| VmRSS | 当前驻留在物理内存里的进程内存,简称 RSS | 观察核心占用怎样变化 |
| VmHWM | 该进程运行期间记录的 RSS 峰值 | 辅助判断是否曾经冲高 |
| VmSize | 进程的虚拟地址空间大小 | 不能当成实际占用的物理内存 |
这些统计适合判断方向,不是精密测量。固件没有提供某个字段时,就记为“未提供”,不要拿其他数字代替。核心已经退出时,对应文件可能已不存在;重启后也要重新核对 PID,不能把两个进程的数据接成同一次运行。
分开记录启动、更新和正常使用
在不影响日常联网的条件下,保留下面几个阶段的时间、系统 MemAvailable、核心 PID 和 VmRSS;能读到 VmHWM 时也一起记下:
- 启动前,记系统可用内存,并注明当时核心是否在运行。
- 启动或规则更新期间,留意日志中正在处理什么,以及内存是否明显下降。
- 启动完成、空闲后,再记一次。
- 正常使用一段时间后复查,同时注明流量和其他程序是否有变化。
如果只在启动或更新阶段出问题,优先检查那次加载的规则和相关错误。如果运行一段时间才出问题,就保留多次记录,连同其他进程的变化一起看。一次快照可能漏掉短暂峰值;看到数值增长,也不能直接认定为内存泄漏。
这一步的作用是缩小范围。例如,“每次更新同一份规则时退出”和“开机后一直有其他程序占用大量内存”,下一步要查的东西就不同。不要同时换内核、换规则和改运行模式,否则即使暂时恢复,也难以知道是哪项变化起了作用。
怀疑规则加载,先核对 behavior 和 format
配置中的 rule-providers 是供分流使用的规则集合。需要同时看两个字段:behavior 说明规则内容属于哪类,format 说明文件按什么格式读取。文件名后缀不能替代这两项检查。
按本次核对的 mihomo 官方文档,format 可选 yaml、text、mrs,默认是 yaml;mrs 目前只支持 domain 和 ipcidr,不支持 classical。
| behavior | 内容类型 | 能否使用 mrs |
|---|---|---|
| domain | 域名规则集合 | 可以,须提供对应的 mrs 文件 |
| ipcidr | IP 地址段规则集合 | 可以,须提供对应的 mrs 文件 |
| classical | 使用多种规则语法的集合 | 当前不能直接改成 mrs |
文本规则和 mrs 的加载方式不同。核对的 mihomo 代码中,文本路径会逐条处理规则,mrs 则读取对应的二进制结构。这给了检查规则格式的理由,却不能推出“换成 mrs 一定省多少内存”,也不能保证解决这台设备的 OOM。
准备调整时,先备份能用的配置,确认实际内核版本支持所用格式。若同一规则来源提供内容对应的 mrs 版本,可按它的说明核对文件、behavior、format 和路径;自己转换则需要使用 mihomo 的规则转换功能。只把后缀改成 .mrs,或者只改 format 字段,都不会把原文件转换成 mrs。
也可以检查有没有自己明确不需要、却一直在加载的规则源。每次只调整一项,并保留恢复办法;改完既看内存,也检查原先需要的分流是否仍然正确。不要为了让占用数字变小,就删除承担隐私或访问控制用途的规则。
还有一个容易看错的字段:size-limit 限制的是下载文件的字节数,不是核心的运行内存上限。文件体积小,也不等于加载后的占用一定小。
GEO 加载模式要另查,仍然 OOM 就带证据反馈
如果配置使用 GEO 数据,也就是 GEOIP、GEOSITE 等规则使用的数据文件,再核对 geodata-loader。当前官方文档列出 standard 和 memconservative,后者面向内存受限设备优化,也是文档给出的默认值。它管的是 GEO 文件加载,不能当成所有 YAML 或 rule-provider 的通用省内存开关;已经使用默认值时,重复填一遍也不代表完成了优化。
调整后仍然出现 OOM,向相应项目反馈时,整理好这些材料:固件、OpenClash 和实际内核版本;故障发生在启动、更新还是正常使用期间;OOM 前后完整日志;各阶段的 MemAvailable、核心 PID 和 RSS;涉及规则集合的类型与格式。配置和日志先脱敏,再按项目要求提交。
手里只有断网现象,就从日志开始;已经确认 OOM,再用分阶段记录定位;确定与规则加载相关,才逐项测试规则数量和适用的格式。每次修改都留下前后记录和可恢复配置,下一次排查才能接着往下走。