R1 大周期筛选脚本连续 2 天静默:一次无产物校验的 cron 幽灵复发
本文最后更新于 2026年9月10日 凌晨
R1 大周期筛选脚本连续 2 天静默:一次无产物校验的 cron 幽灵复发
每次都要手动检查日志,受够了。
结论先行:R1 大周期筛选脚本在两天内静默无产出,根因是缺少“产物校验”导致 cron 幽灵复发——脚本进程显示运行成功,但实际上没生成任何有效数据。加入产物校验和外部告警后,问题彻底解决。
前置条件
- 系统:Ubuntu 22.04 LTS
- 服务器:ModelBase
- 硬件:2 块 RTX 2080 Ti 魔改版,单卡 22 GB 显存,双卡总计 44 GB
- 推理引擎:llama.cpp,运行在 models-preset 多模型模式
- 代理层:new-api(内网代理)
- 部署模型:Qwen3.5-35B-A3B-Ornith (Q4_K_M, 104 t/s) 以及 Qwen3.6-35B-A3B (Q4_K_M, 103 t/s)
- 脚本语言:bash + Python 3.10
- 依赖:curl, jq, python-requests
做了什么
首先梳理了现有的 R1 大周期筛选流程:该流程由 cron 每 6 小时触发一次,调用 screen_r1.sh,内部通过 Python 脚本进行模型推理并将结果写入 /data/r1_out/。
我发现两天内该目录没有新文件产生,但 cron 进程仍在运行,日志里只有“开始执行”,没有“结束”或“错误”信息。于是我们在 screen_r1.sh 中加入了产物校验逻辑:推理完成后检查输出文件是否超过 0 字节,无效则触发告警并返回非零退出码。
1 | |
在 crontab 层也增加了返回码捕获:
1 | |
技术选型与架构
我们没有引入复杂的调度系统,而是在现有的 cron 框架上做最小侵入。理由有两个:
- 现有基础设施已稳定多年,改动越小风险越低。
- 产物校验只需要几行脚本,无需引入额外的容器化或复杂依赖。
架构逻辑如下:cron -> screen_r1.sh -> screen_r1.py -> 模型推理 (llama.cpp) -> 输出文件
↓产物校验 (文件大小 > 0)
↓
成功 → 正常退出
失败 → 告警(new-api)+ 非零退出 → cron 捕获 → 写入 r1_err.log
效果
改动后立刻看到变化:
- 第一天:cron 在 06:00、12:00、18:00、00:00 四次触发,每次都产生 MB 级的 JSON 文件,日志显示“产物校验通过”。
- 第二天(故障测试):我进行了故障注入实验,手动将
screen_r1.py的输出路径改到不可写目录,脚本立刻检测到空产物,向 new-api 发送告警。告警内容如下:[2026-09-10 14:30:00] 警告:产物文件为空,跳过处理
告警在秒级送达,远低于之前人工巡检的数小时等待。
踩过的坑
- 假阳性:最初只检查文件是否存在,不检查大小。导致磁盘满时仍然写入零字节文件,误判为成功。后来改为
-s检查非空。 - 告警噪声:早期版本在每次循环内部发告警,导致短时间内刷屏。后改为仅在产物为空时发送一次,并加了 5 分钟的去抖。
- 环境变量传递:cron 默认不继承用户的 PATH,导致
python3找不到。解决方法是在脚本顶部显式声明PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin。 - 日志轮转:原始 cron 日未轮转,占用磁盘过快。后加入
logrotate配置,保持最近 7 天。
参考文献
R1 大周期筛选脚本连续 2 天静默:一次无产物校验的 cron 幽灵复发
https://normdist.com/2026/09/10/ND-20260910-001-r1-screen-cron-silent-fix/