Files
efi-kernel/文档/03-命令手册.md
lou 53e7d1e5f2 底座文档 11 份 + 修掉"同锁调用互相排队、双双卡死"
文档/ (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
2026-09-16 21:13:31 +08:00

7.7 KiB
Raw Permalink Blame History

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 停内核(先驱动后内核)