12 · Status 系统仪表盘
Status 把采集分层:高频指标必须便宜,昂贵信息必须缓存,首次画面必须快于“收集全部”。
三种输出,三种消费者
- TTY 默认进入 Bubble Tea 仪表盘。
- stdout 非 TTY 或
--json输出单次 JSON。 --watch按间隔输出 NDJSON,复用同一个 warm collector。
自动 JSON 让 mo status | jq 不需要额外参数;NDJSON 每行独立,适合日志与流式处理,不必维护一个不断增长的 JSON 数组。
快速首屏与分层刷新
TUI 先执行 fast collection 绘制首屏,随后立即做 full collection。稳定运行时:
- 每 1 秒采集 fast;
- 进程信息按较高频率刷新;
- 每 30 秒采集 full。
Collector 将静态硬件信息缓存 10 分钟、Bluetooth 缓存 30 秒,并保留 120 点历史环形缓冲。网络和磁盘 IO 通过两次累计计数求 delta,不能被静态缓存替代。
先采 CPU,再并发做重活
Full collection 在启动其他 collector goroutine 前先采样 CPU,避免 system_profiler、磁盘检查等自身开销污染被观测值。随后并发采内存、磁盘修正、Trash、代理、电池、温度、GPU、Bluetooth 与进程。
快路径会用缓存的修正字段覆盖粗略字段,但磁盘 IO 与网络仍保持实时。这是一种“鲜度按字段分级”,不是整个 snapshot 同一过期时间。
所有子进程强制 LC_ALL=C,防止不同语言环境改变系统命令输出格式,导致解析器把逗号小数、翻译后的标签或单位当成数据。
健康分数不是简单平均
基础权重为 CPU 30、内存 25、磁盘 20、温度 15、IO 10。每类有自己的阈值与惩罚曲线;电池与 uptime 可追加小惩罚;SMART 报告 failing 时总分封顶 44。
封顶表达了一个重要语义:关键硬件故障不能被其他五项“平均成健康”。健康分是风险聚合,不是装饰性百分比。
持续高 CPU 的身份问题
进程 watcher 用 PID + PPID + command 作为身份,防止 PID 重用把新进程继承为“已持续超限”。默认只有 CPU 超过 100% 并持续 5 分钟才触发,降回阈值下即重置。
这比一次 top 排名更接近诊断:多核 macOS 中 100% 约等于持续占用一个核心,短构建和启动尖峰不应被标红。
响应式终端布局
宽度不超过 80 时单列,超过 80 时双列;高度不足时动态减少 core rows。卡片覆盖 CPU、内存、磁盘、进程、网络、电池与健康分。键位偏好持久化,用户可切换类别和 CPU 核心展示。
关键源码索引
cmd/status/main.go:JSON、NDJSON 与 TUI 入口。cmd/status/metrics.go:fast/full 分层与缓存。cmd/status/metrics_health.go:健康分规则。cmd/status/process_watch.go:持续 CPU 识别。cmd/status/view.go:响应式卡片布局。
下一章回到分发链:安装器如何验证二进制,更新器又如何从损坏的旧安装中自愈。