Skip to content

[问题 & 建议] 加载大型 GEOSITE 规则集时启动超时/重试机制优化 #4873

@mwnu

Description

@mwnu

Verify Steps

  • Tracker 我已经在 Issue Tracker 中找过我要提出的问题
  • Branch 我知道 OpenClash 的 Dev 分支切换开关位于插件设置-版本更新中,或者我会手动下载并安装 Dev 分支的 OpenClash
  • Latest 我已经使用最新 Dev 版本测试过,问题依旧存在
  • Relevant 我知道 OpenClash 与 内核(Core)、控制面板(Dashboard)、在线订阅转换(Subconverter)等项目之间无直接关系,仅相互调用
  • Definite 这确实是 OpenClash 出现的问题
  • Contributors 我有能力协助 OpenClash 开发并解决此问题
  • Meaningless 我提交的是无意义的催促更新或修复请求

OpenClash Version

v0.47.028

Bug on Environment

Official OpenWrt

OpenWrt Version

Openwrt 6.6.73

Bug on Platform

Linux-mipsle-hardfloat

Describe the Bug

当配置文件包含大型 GEOSITE 规则集(如 GEOSITE,category-ads-allgeosite:cngeosite:geolocation-! cn)时,OpenClash 频繁启动失败,表现为约 5 秒后自动重启,陷入失败的重启循环

To Reproduce

失败率估计:

  • 已启动状态下重启:100% 失败
  • 插件关闭状态下手动启动:90% 失败
  • 关闭所有其他插件和脚本:80% 失败
  • 开启插件状态下重启路由器(自启):60% 失败
  • 关闭插件后重启路由器(自启):30% 失败
  • 删除 GEOSITE 规则或使用小配置:0% 失败(100% 成功)

OpenClash Log

**故障日志:**
- 插件日志:`错误:内核启动失败,请查看《内核日志》排查失败原因`
- 内核日志:最后一行日志在加载 `geosite:cn`,并多次重试

OpenClash Config

**已排除因素:**
- 路由器 CPU 和内存性能充足,不是硬件性能问题
- 于路由器和openclash插件设置无关,控制变量仅在配置包含大型 geosite 规则集时出现

Expected Behavior

功能建议(以下AI辅助,不一定准确)

建议在 OpenClash 中添加以下可配置选项:

方案一:内核启动超时时间(推荐)

  • 位置:设置 → 运行模式 → 内核启动超时时间
  • 参数名core_startup_timeout
  • 默认值:10 秒(当前硬编码值)
  • 建议范围:10-300 秒
  • 说明:等待 clash 进程完全启动并加载配置的最大时间

方案二:启动检测重试次数

  • 位置:设置 → 运行模式 → 启动检测重试次数
  • 参数名core_startup_retry
  • 默认值:10 次(当前 CORE_WAIT <= 10)
  • 建议范围:10-600 次
  • 说明:检测内核状态的重试次数,每次间隔 1 秒

方案三:procd 重启延迟调整

  • procd_set_param respawn 300 5 3 中的延迟从 5 秒调整为可配置
  • 或者在检测到 geosite 规则时自动延长延迟时间

预期效果

实现此功能后:

  • 用户可根据配置文件大小调整超时时间(如设置为 60-300 秒)
  • 内核有足够时间完整加载 geosite.dat 等大文件
  • 大型 GEOSITE 规则集的启动成功率达到 100%
  • 彻底解决无限重启循环问题

参考案例

此问题在 Merlin Clash 中也存在,通过"检查日志重试次数"设置(从 20 调整到 120)完美解决。该设置本质上延长了启动检测的等待时间,允许配置文件完整加载。

相关代码位置

  • 文件:luci-app-openclash/root/etc/init.d/openclash
  • 关键行:
    • 第 693-696 行:CORE_WAIT 循环(10秒超时)
    • 第 747-757 行:HTTP API 检测(120秒超时)
    • 第 794 行:procd_set_param respawn 300 5 3
  • 相关函数:check_core_status(), start_fail(), start_run_core()

Additional Context

问题根源分析

通过分析 /etc/init.d/openclash 源码,发现存在硬编码的启动超时检测机制

1. 进程启动超时(10秒)

# 第693-696行
while ( [ -z "$(pidof clash)" ] && [ "$CORE_WAIT" -le 10 ] )
do
   sleep 1
   let CORE_WAIT++
done
  • 脚本最多等待 10 秒检测 clash 进程启动
  • 加载大型 geosite. dat 文件时,内核可能处于繁忙状态,进程不稳定或短暂阻塞
  • 10 秒超时对于大配置文件来说严重不足

2. procd 自动重启机制(5秒间隔)

# 第794行
procd_set_param respawn 300 5 3
  • 参数含义:respawn <阈值秒数> <重启延迟> <最大重启次数>
  • 当进程异常退出时,procd 会在 5 秒后自动重启
  • 这正是用户体感"约 5 秒就重启"的原因

3. HTTP API 检测超时(120秒,但实际更早失败)

# 第747-757行
while ( [ -n "$(pidof clash)" ] && [ "$CORE_HTTP_CODE" != "200" ] && [ "$TUN_WAIT" -le 120 ] )
do
   CORE_HTTP_CODE=$(curl -m 5 -o /dev/null -s -w '%{http_code}' -H 'Content-Type: application/json' -H "Authorization: Bearer ${da_password}" -XGET http://${lan_ip}:${cn_port}/group)
   let TUN_WAIT++
   sleep 1
done
if [ "$CORE_HTTP_CODE" != "200" ]; then
   LOG_OUT "Error: Core Status Abnormal, Please Check The Log Infos!"
   start_fail
fi
  • 理论上有 120 秒超时,但由于前面的 10 秒进程检测失败,往往更早触发 start_fail()

完整失败流程:

  1. clash 进程启动,开始加载配置文件
  2. 加载大型 geosite.dat 时内核繁忙,进程可能短暂阻塞或崩溃
  3. CORE_WAIT 在 10 秒内检测不到稳定进程,或 HTTP API 未就绪
  4. 触发 start_fail() → 杀死进程 → 退出
  5. procd 检测到异常退出,5 秒后自动重启
  6. 重启后遇到相同问题 → 无限循环

对比:Merlin Clash 的解决方案

Merlin Clash 插件提供了 "检查日志重试次数" 设置:

  • 默认值:20 次,触发相同问题。
  • 调整为 60-120 次后,一次即能启动,成功率达到 100%。
  • 本质上是延长了启动检测的容忍时间,允许内核有足够时间加载大配置

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions