Files
market_sync/docs/works/2026-07-03-04-systemd-drift-detection.md
T
gao cf45f98a8a feat(daily_check): systemd unit drift 自动检测
work #04 (2026-07-03):user 重申 sync 目标强调 timer/service/依赖/编码格式
全链路审计,发现 5 处 systemd unit drift:work #01 (4h timeout) 和 work #02
(morning.timer) 代码改了但没 cp 到 /etc/systemd/system/,等于没修。

根因:deployment 与 repo 各自演进无任何告警机制。

修复:在 daily_sync_check 加 _check_systemd_drift() 段,对比
bin/systemd/ 与 /etc/systemd/system/ 下所有 market-sync* unit:
- missing_in_etc (未部署) → status=not_deployed
- drifted (两边有但内容不一致, SHA256 比对) → status=drifted
- orphan_in_etc (/etc 有 repo 没维护, 捕获僵尸 unit) → status=orphan

drift 合入 alerts 让 webhook 也带;report schema_version 1→2。

立即验证:跑 daily_check 抓到 5 处 drift(4 未部署 + 1 内容不一致),
status=warning 让 webhook 自动发出——以后任何 deployment drift 都逃不掉。

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-03 11:37:21 +08:00

75 lines
3.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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 自动段。