53e7d1e5f2
文档/ (2026-09-16; 老板定调: 这是 agent 底座, 所以必须扎实, 现在越扎实以后开发越简单)
00-索引 文档地图 + 30 秒概念速查 + 三条命令跑起来 + 事实源优先级
01-快速上手 体检 -> 建库 -> 起内核 -> 起驱动 -> 收工, 全带实测输出; 第一次最易踩的四个坑
02-写一个驱动 五分钟最小驱动 / 形态选择 / 能碰哪些表 / 汇报与调用两份模板 / 交付检查表
03-命令手册 两层每条命令 + 日志选项 + 退出码约定 + --json 样例 + 日常十条
04-契约与调用 一次调用的完整生命周期 / 六条仲裁 / 锁与按需拉起 / 排障表
05-日志与排障 三条道怎么读 + "症状->判据->处置"总表 + 断电收尸语义
06-架构与不变量 分层 / 14 条硬不变量 / 主流程表 / 双真相 / 为什么故意不做 / 已知薄弱点
07-模块与接口 逐模块职责与公开接口 + "想改 X -> 动哪几处"连带清单
08-数据模型 8 张表逐字段 (谁写谁读) + events.kind 字典 + 状态机 + 快照 + 排查 SQL
09-扩展指南 六个配方 (加子命令/加字段/加表/加日志来源/加自测/改判定) + 同步清单
10-验收与质量门 四道门 + 五份自测明细 + pyright 严格档 + 26 条已知坑总表 + 发布 checklist
规矩: 不重复设计文档 / 每条命令实测过再写 (含 jq 表达式) / 代码>设计>文档 的事实源优先级 /
改代码必须同步文档 (清单在 09 末尾) / 暂时没做到的事写成"已知边界"不含糊过去
修复: 同锁串行化原来是死的 (实测抓到的真缺陷)
旧行为: db.领调用 只领 pending (waiting 没人再碰) + db.同锁在跑 把 waiting 也算"占着锁"
-> 同一把锁上两条请求互相排队, 双双停在 waiting 谁也不跑 (实测 id 16/17);
而 收权超时 只收 running -> 排队连超时都没有 = 死锁
修法: ① db.领调用 的 SQL 改 state IN ('pending','waiting') -- 每轮把排队的领回来重判, 锁一空就推进
② db.同锁在跑 只认 state='running' (排队的还没拿到锁, 不挡人)
③ 内核.转发调用 waiting 分支补 deadline (排队也立期限); 内核.收权超时 遍历 running + waiting
④ 抽出 内核.期限文本() 统一算 deadline
实测: 两条同锁调用串行跑完 (19.started_at == 18.finished_at); 排队者超时被收权 (events 有记录)
回归: 自测db.py 调用组 +4 条断言 (waiting 不算占着锁 / waiting 会被重新领 / ...);
去掉一条依赖生产库全局计数的脆弱断言
其它: 内核 与 引导器 的 用法() 末尾加文档指引
验收: uvx pyright 0 errors / 0 warnings; 五份自测全过 (进程/内核 58/配置/db/日志 86);
试跑引导器.py PASS 11 / FAIL 0 / 残留无; 残留进程 0
7.7 KiB
7.7 KiB
03 · 命令手册
两个入口:引导器(
python3 UEFI.boot.py …,管环境和内核进程)和 内核(./.venv/bin/python 内核/内核.py …,管驱动)。 键盘上只需要记两条:UEFI.boot.py <命令>、内核/内核.py <命令>—— 引导器除了自己那 5 个词,其余原样透传内核。
0. 归属一眼看清
python3 UEFI.boot.py ← 引导器: 自检 | 环境 | 包 | 内核 | 日志
└─ 其余一律透传给内核 ─────► ./.venv/bin/python 内核/内核.py 列表 | 扫描 | 启动 | 停止 | 重启 | 状态 | 日志 | 事件 | 清单 | 调度
两条铁律:内核对驱动的命令(启动/停止/重启/状态/日志/事件/清单)在引导器那侧不做体检门槛
("看/收尾"必须能在环境坏掉时用);引导器起停内核(内核 启动/重启)会先例行体检,有阻塞项就拦住不让动。
1. 引导器自己的命令(5 个词)
| 命令 | 作用 | 退出码 |
|---|---|---|
UEFI.boot.py(无参数) |
体检 → 移交内核的默认动作(列表) |
内核的退出码 |
UEFI.boot.py -h / --help / 帮助 |
打印用法 | 0 |
UEFI.boot.py 版本 |
打引导器 + 内核版本 | 0 |
UEFI.boot.py --check / 自检 / 检查 |
只体检,不启内核 | 0 全过 / 1 有阻塞项 |
UEFI.boot.py 环境 [--json] |
体检 6 项,逐项给结论 + 修复命令 | 同上 |
UEFI.boot.py 环境 重建 |
按 python 要求重建 venv(旧 venv 改名 .venv.bak-<时间戳> 留退路) |
0 / 1 |
UEFI.boot.py 包 [--json] |
包状态台账(读 uv pip list,失败回落 importlib.metadata) |
0 / 1 |
UEFI.boot.py 包 安装 [名...] |
装包(显式;走 环境.efi.json 的国内源) |
0 / 1 |
UEFI.boot.py 日志 [选项] |
引导器自己的动作日志;--内核 / --输出 转看内核那两份 |
0 / 1 参数错 |
python3 UEFI.boot.py --check
python3 UEFI.boot.py 环境 --json | jq .checks # 机器读: 6 项结论 + blocking_ok
python3 UEFI.boot.py 日志 -n 30 # 引导器动作 (体检/包/移交/内核启停)
python3 UEFI.boot.py 日志 --级别 WARN -g 内核 # 只看警告里跟内核有关的
环境 --json 的输出(机器读,别跟人读的表格混):
{ "efi": 1, "ts": "2026-09-16T21:03:40+08:00", "引导器": "引导器 v0.1",
"blocking_ok": true, "ok": true,
"checks": [ { "序号": 1, "名称": "解释器版本", "结果": true, "必需": true, "详情": "…", "修复": "" }, … ] }
2. 内核进程管理(归引导器)
| 命令 | 作用 | 退出码 |
|---|---|---|
内核 状态 |
有没有在跑(pid + /proc/<pid>/cmdline 交叉校验)/ 上次运行 / 今日次数 / 未收尾台账 |
0 / 1 |
内核 启动 [参数...] |
前台跑一次(输出实时可见;默认动作 = 常驻调度,会一直挂着) | 内核的码 |
内核 启动 --守护 [参数...] |
后台常驻(--守护 是引导器的开关,不转给内核) |
0 起得来 / 1 起不来 |
内核 停止 |
先校验 cmdline 再 SIGTERM 进程组,超时升 SIGKILL;顺手收尾 kernel_runs 半截记录 |
0(幂等)/ 1 有残留 |
内核 重启 |
停干净了才启(没停干净不启,一次只动一件事) | 0 / 停的码 |
内核 日志 [选项] |
内核日志;默认看结构化 内核.log,--输出 看命令输出/崩溃原文 |
0 / 1 参数错 |
python3 UEFI.boot.py 内核 启动 --守护
python3 UEFI.boot.py 内核 状态
python3 UEFI.boot.py 内核 日志 --级别 WARN -n 50
python3 UEFI.boot.py 内核 日志 --输出 -n 100 # 命令输出 + 未捕获的崩溃原文
python3 UEFI.boot.py 内核 停止
3. 内核自己的命令(管驱动)
| 命令 | 作用 | 退出码 |
|---|---|---|
列表 |
驱动清单表(默认动作) | 0 |
扫描 |
只扫不启:认文件夹 → 9 条校验 → 写注册表 → 收尸 → 落快照 | 0 / 1 驱动根不存在 |
启动 <驱动名> |
拉起一个驱动(幂等:在跑就直说);拉起前轮转它的日志 | 0 / 1 起不来 |
停止 <驱动名> |
校验 cmdline → SIGTERM 进程组;级联停下游;超时升 SIGKILL |
0 / 1 |
重启 <驱动名> |
停干净了才启 | 0 / 1 |
状态 [驱动名] [--json] |
直读 /proc 的现场判定(不信库里的旧 pid);不带名字 = 全部 |
0 / 1 没这个驱动 |
日志 [驱动名] [选项] |
不带名字 = 驱动日志台账;带名字 = 那个驱动的日志;--全部 = 所有驱动各一段 |
0 / 1 没这个驱动 / 1 参数错 |
事件 [-n 50] |
全局事件流(events 表 = 总线,最近的在上面) |
0 |
清单 |
输出清单 JSON(注册表 + 状态 + 契约,重定向就是文件) | 0 |
调度(= 无参数) |
常驻调度内核(前台阻塞;--守护 由引导器负责) |
0 |
./.venv/bin/python 内核/内核.py 列表
./.venv/bin/python 内核/内核.py 启动 样板常驻
./.venv/bin/python 内核/内核.py 状态 样板常驻 --json
./.venv/bin/python 内核/内核.py 日志 # 台账: 谁有日志 / 占用 / 行数 / 最后改动
./.venv/bin/python 内核/内核.py 日志 --全部 -n 20 # 所有驱动各一段
./.venv/bin/python 内核/内核.py 事件 -n 30
./.venv/bin/python 内核/内核.py 清单 > 清单.json
4. 日志选项(三处认同一套,解析只有一份)
UEFI.boot.py 日志 … / UEFI.boot.py 内核 日志 … / 内核/内核.py 日志 … 都认这些开关:
| 开关 | 含义 |
|---|---|
-n 200 |
尾部行数(含轮转的历史份一起数) |
-f |
实时跟(先吐 10 行,Ctrl+C 停;一次只能跟一个来源) |
--级别 DEBUG|INFO|WARN|ERROR |
只要这个级别及以上;驱动原始日志按字样猜级别(不是规范) |
-g 关键词 |
只要含它的行(不区分大小写) |
--json |
JSON Lines:结构化日志拆成 {时刻,级别,来源,消息};裸行给 来源:"" + 猜的级别 |
--全部 |
所有驱动各一段(== 名字 == 分隔) |
--内核 / --引导器 / --输出 |
换来源:内核结构化 / 引导器动作 / 内核 stdio |
参数写错 → 打用法 + 退出码 1(不猜、不静默用默认值)。
三条道分别是什么 → 05-日志与排障.md。
5. 退出码约定(脚本里能直接判)
| 码 | 含义 |
|---|---|
| 0 | 成了(内核 停止 在"本来就没跑"时也回 0,幂等) |
| 1 | 有事:体检有阻塞项 / 没这个驱动 / 起不来 / 参数写错 / 有残留进程 |
| 2 | 命令不认识(内核会顺手打一遍 用法) |
| 其它 | 透传命令一律原样返回内核的退出码(引导器不解释、不包一层) |
| -1 | 用在 试跑引导器.py 里表示"超时"(前台常驻内核挂住不返回 = 预期,不算错) |
6. 日常十条(贴在手边)
python3 UEFI.boot.py --check # 1 环境有事没事
python3 UEFI.boot.py 内核 启动 --守护 # 2 起总调度
./.venv/bin/python 内核/内核.py 列表 # 3 看驱动清单
./.venv/bin/python 内核/内核.py 状态 # 4 看现场状态(直读 /proc)
./.venv/bin/python 内核/内核.py 启动 <名> # 5 起一个
./.venv/bin/python 内核/内核.py 日志 <名> -f # 6 实时跟它的输出
./.venv/bin/python 内核/内核.py 事件 -n 30 # 7 看总线最近发生了什么
./.venv/bin/python 内核/内核.py 重启 <名> # 8 改完配置/代码后
./.venv/bin/python 内核/内核.py 停止 <名> # 9 停一个(级联停下游)
python3 UEFI.boot.py 内核 停止 # 10 停内核(先驱动后内核)