meow_crash 62781084; meow_svcd da6ebc66→605646c4(仅+68行上报挂点); 宿主5场景全过(上报链路/dmesg增量/无卡迁移/铁律验证/CLI)
82 lines
4.4 KiB
Markdown
82 lines
4.4 KiB
Markdown
# meow_crash — MeowOS 系统级崩溃捕获(二期组件)
|
||
|
||
> 状态:设计落盘 + 实现(agent 任务)。`meow_crash` 是 svcd 托管的小守护,负责把
|
||
> svcd 服务的异常退出与内核 oops/应用崩溃记录到日志,供事后排查。
|
||
> 定位见 FRAMEWORK_DESIGN §10(Supervisor 树 / 崩溃隔离)、APPS.md §4.5(统一日志系统)、
|
||
> devdocs/plan/SYS_BASELINE.md(svcd 子进程化,监护挂点)、devdocs/plan/APP_LOG_MANAGER.md。
|
||
|
||
## 1. 角色
|
||
|
||
`meow_crash` = 崩溃事件**记录器**(只读一条上报消息落盘,无共享内存、无 dlopen),
|
||
由 svcd 以 `fork+exec+setpgid` 托管(`/usr/bin/meow_crash` + `services.d/meow_crash.conf`
|
||
trigger=boot)。svcd 托管服务均为前台常驻(svcd waitpid),故 meow_crash
|
||
**不 daemonize**,svcd 崩则它是子进程被 waitpid 感知;它崩则 svcd 按 `on-fail` 重启它,
|
||
且其崩溃不影响 svcd(崩溃隔离)。
|
||
|
||
## 2. 捕获源
|
||
|
||
### ① svcd 服务异常退出(主源)
|
||
svcd 在 `reap_children()` 检测到**异常退出**(非 0 退出码 / 被信号杀,且非受控
|
||
stop/restart)时,经 AF_UNIX `/tmp/meow_crash.sock` 发**单行**文本(best-effort):
|
||
|
||
```
|
||
SVC <service_name> <exit|sig> <num> <epoch_sec> <uptime_sec>
|
||
```
|
||
|
||
- 全程非阻塞:客户端 socket 置 O_NONBLOCK;connect 失败即放弃(可短 poll POLLOUT
|
||
≤150ms 用于本地 listen backlog 排空,绝不重试)。**svcd 绝不被此带崩。**
|
||
- meow_crash 不在线 → 该条丢弃(符合「若 crash 不在线则跳过」)。
|
||
|
||
### ② 内核 oops / 应用崩溃(辅助,v1 不强求)
|
||
周期性(1s)`dmesg` 抓取,记录上次读取偏移(`g_dmesg_prev_len`),只扫**新增**段,
|
||
捕获含 `segfault`/`oops`(大小写不敏感)的行。环回/替换时全量扫并靠去重环防重复。
|
||
v1 不扫描 `/tmp` core 转储(不强求,留作后续)。
|
||
|
||
## 3. 落盘
|
||
|
||
- 有卡:`<card>/MeowOS/logs/crash_<bootts>.log` 追加写。`<bootts>` 复用
|
||
`/tmp/meow_bootts`(launcher 缓存的 boot 时间戳,`meow_` 前缀剥掉),同一 boot
|
||
会话跨进程共用;读不到则按 墙钟-uptime 计算并缓存。
|
||
- 无卡/写失败:`/tmp/meow_crash.log`(tmpfs,256KB 滚动,超出即重建)。
|
||
- 卡出现:`poll_card()` 把 /tmp 缓冲整段搬入卡日志后删除(对齐 launcher
|
||
`log_poll_card` 语义)。
|
||
- 总量:`log_cleanup_old()` 统计 logs/ 下 `meow_*` 与 `crash_*`,超过 1GB 按 mtime
|
||
删最旧(与 launcher 的 LOG_SIZE_LIMIT 同纪律,launcher 只管 meow_*,本守护并管)。
|
||
|
||
一行一条格式:
|
||
```
|
||
<epoch_sec> <uptime_sec> <source> <detail...>
|
||
```
|
||
- `source`:`svc`(来自 svcd)或 `dmesg`(内核行)。
|
||
- `detail`:`<name> exit=<code>` / `<name> signal=<sig>` / 内核行原文。
|
||
|
||
## 4. CLI(root 免鉴权,读文件,不依赖守护在线)
|
||
|
||
| 命令 | 说明 |
|
||
|---|---|
|
||
| `meow_crash dump` | 打印本 boot 崩溃清单(卡 `crash_<bootts>.log`;无卡/无文件回退 /tmp) |
|
||
| `meow_crash tail [N]` | 打印最近 N 条(默认 20,上限 100) |
|
||
| `meow_crash`(无命令) | svcd 拉起 → 前台常驻守护 |
|
||
|
||
`dump`/`tail` 把 epoch 转可读 `YYYY-MM-DD HH:MM:SS` 展示。
|
||
|
||
## 5. 测试钩子(宿主集成测试)
|
||
|
||
| 钩子 | 作用 |
|
||
|---|---|
|
||
| `--card <path>` / `MEOW_CRASH_CARD` | 覆写卡挂载点(宿主指向临时目录即走「有卡」路径) |
|
||
| `--sock <path>` / `MEOW_CRASH_SOCK` | 覆写上报 socket |
|
||
| `MEOW_CRASH_NOCARD=1` | 强制无卡(验证 /tmp 回退 + 后续迁移) |
|
||
| `MEOW_CRASH_DMESG_FILE=<path>` | 从文件读「假 dmesg」(宿主注入内核行) |
|
||
|
||
## 6. 边界 / 诚实标注
|
||
|
||
- **v1 不扫描 core 转储**(任务:「不强求」)。当前只做 svcd 上报 + dmesg 增量。
|
||
- **svcd 上报的 skip 语义**:受控 stop(stop_requested)与 restart 命令
|
||
(restart_pending)的退出**不**上报,只记真实异常退出(避免把管理员停服务当崩溃)。
|
||
- **dmesg 捕获**依赖设备 `dmesg` 可用(busybox;root)。宿主用 `MEOW_CRASH_DMESG_FILE`
|
||
注入。首扫会捕获本 boot 已存在的 crash 行(内核环在重启时清空,不会跨 boot 混入)。
|
||
- **固件打包需知 / 板载 conf 预置**:本任务按约束未改 `S89meow_svcd` 与固件脚本。
|
||
需在**打包/首启预置**阶段把 `patch_v2/meow_crash/meow_crash.conf` 落到
|
||
`/usr/data/meow/services.d/meow_crash.conf`(参照 S89 对 mdnsd/perf/power 的预置方式)。
|