# 2026-07-03 — work #04: daily_check 加 systemd unit drift 自动检测 ## 发现 user 重申 sync 目标时强调"timer、system service、依赖、编码格式都要考虑",触发全链路审计: | Audit | 结论 | |---|---| | 1. PG 编码 | ✅ UTF8 / UTC / en_US.utf8 | | 2. stock_code 格式(10 张表) | ✅ 100% hermes (SH600000),0 漂移 | | 3. dataset_registry 依赖链 | ✅ 12 dataset 全部 deps 解析正确,无自依赖 | | 4. systemd unit 漂移 | ❌ **5 处 drift** | | 5. 脚本可执行 + ExecStart 路径 | ✅ 全部 OK | **Audit 4 是 sync 目标的最大阻断**:之前 work #01 (4h timeout) 和 work #02 (morning.timer) 的代码**没部署到 /etc/systemd/system/**: ``` repo units (14) / /etc units (10): ❌ 未部署 (4): - market-sync-daily-check.{service,timer} (work #01) - market-sync-morning.{service,timer} (work #02) ⚠️ 内容不一致 (1): - market-sync.service (work #01: TimeoutStartSec 7200→14400) ``` 如果今天有人手动 `systemctl start market-sync.service`,跑的是 /etc 里**旧版**(2h timeout),仍会被 17:30 截断——work #01 形同虚设。 ## 根因 deployment 与 repo 各自演进,无任何机制告警。`market_sync_run.sh` 注释甚至没说明要 cp 到哪里。这是**流程缺口**,不是代码 bug。 ## 解决 `bin/daily_sync_check.py` 加 systemd drift 检测段: - **missing_in_etc**:repo 有 /etc 没装 → 标 `not_deployed` - **drifted**:两边都有但 SHA256 不一致 → 标 `drifted`(含前后 sha 前 12 位方便辨识) - **orphan_in_etc**:/etc 有 repo 没维护 → 标 `orphan`(捕获僵尸 unit,比如之前删掉的 monitor) 实现要点: - 用 SHA256 对比,避免误报时间戳/空白差异 - drift 段独立于 dataset 状态,但合入 `alerts` 列表(让 webhook 也带上) - report schema_version 升 1 → 2(加 systemd_drift 字段) - overall 计算包含 drift 状态(任一 drift 出现 → overall=warning) ## 验证 修复后立即跑: ``` counts: {'running': 1, 'missed': 8, 'not_expected': 1, 'ok': 2} 告警 (13): ... - [not_deployed] systemd/market-sync-daily-check.service ... - [not_deployed] systemd/market-sync-morning.service ... - [ drifted] systemd/market-sync.service ... systemd unit 漂移: repo units (14) / /etc units (10) ❌ 未部署 (4) / ⚠️ 内容不一致 (1) ``` 5 处 drift 全部捕获,**且 status=warning** 让 webhook 自动发出。 ## 关联 - work #01: 2026-07-03-01-market-sync-timeout.md(修了代码但没部署,drift 检测让这事不再隐蔽) - work #02: 2026-07-03-02-morning-no-trigger.md(同上) - [[dual-scheduler-overlap]]:双调度器并存,本次 drift 检测在 timer / service 层加防护 ## 后续(不在本 work 范围) - **写 deploy 助手脚本** `bin/systemd_install.sh`,一行 `sudo bin/systemd_install.sh` 把 repo 所有 unit cp 到 /etc + daemon-reload + enable + restart。降低手动部署出错概率。 - **加 PG drift 检测**:跑 SQLAlchemy `Base.metadata` 对比实际 PG `information_schema.tables/columns`,检测 schema 漂移(model 改了但没跑 migration)。 - **加 stock_code 漂移检测**:本次是 audit 一次性检查,应该也进 daily_check 自动段。