先定读者,再定输出
值班的同学凌晨三点打开终端,只想一眼看到"哪台机器有问题";交接班的人想对比昨天和今天;告警系统只想拿到一个结构化的结论。同一份脚本输出要同时喂饱这三种读者,靠的不是加日志,而是约束格式。
先定读者,再定输出
大多数体检脚本一开始都是给自己写的:echo "checking disk..."、echo "done",跑通了就上线。三个月后没人看得懂输出,因为里面混了三类信息:进度日志、检查结果、异常堆栈。它们的受众完全不同。
- 进度日志给写脚本的人调试用,应该走
stderr,或者只在--debug下出现; - 检查结果给值班和交接班的人看,走
stdout,格式必须稳定; - 结构化数据给告警系统和 CI 看,用
--format=json单独输出。
把这三样混在同一个 stdout 里,是脚本"活不过半年"的最常见原因。
结论先行:第一屏就要能下判断
不要按脚本内部执行顺序输出。检查项的执行顺序是代码结构决定的,和严重程度无关。第一行固定放汇总,例如:
[FAIL] 共 24 项,通过 20,警告 2,失败 2:disk_var、ntp_offset
下面再按 FAIL → WARN → INFO → PASS 排序,同一级别内按检查项 id 字典序。每行固定五个字段:状态、检查项 id、当前值、阈值、建议动作。id 用英文短名并保持稳定,比如 disk_var 而不是"根分区使用率检查",因为 id 会被 grep、被写进白名单、被告警规则引用,改一次就要改五处。
让 diff 有意义:输出必须可比较
体检脚本真正的价值在横向对比——和昨天比、和同机房的另一台比。所以输出要能被 diff:
- 时间戳只出现在 header 里,行内一律不放;
- 所有列表按 id 排序,不按发现顺序;
- 数值统一单位与精度,用
printf "%.1f%%"而不是直接打印浮点; - 列宽固定,中文放最后一列,避免对齐被多字节字符打乱。
把结果写到 /var/log/healthcheck/latest.txt,同时保留最近 30 份带日期的副本。噪声为 0 之后,diff yesterday.txt today.txt 的输出就是当天真正发生的变化。
阈值与抑制:别让同一件事报三次
没有抑制机制的体检脚本会在磁盘满之前先把人逼疯。三个最小可用的手段:
- 分级:只有
FAIL触发告警,WARN进日报,INFO只在--verbose下出现; - 连续计数:状态文件里存
{id: {count, last_notify}},连续 3 次失败才告警,恢复时补一条恢复通知; - 带过期的白名单:豁免项必须写
expires: 2025-06-30,到期自动失效。没有过期时间的白名单,半年后就是一张"没人敢删"的清单。
阈值不要硬编码在脚本里。放到 healthcheck.conf,脚本只负责读和比,调阈值不需要改代码、不需要 review。
退出码与双通道输出
退出码是脚本和外部世界唯一的强约定,别浪费它:0 全部通过,1 有 WARN,2 有 FAIL,3 脚本自身出错。这样 CI 里直接 ./check.sh || notify 就能用,也能区分"机器有问题"和"脚本挂了"。
同时提供 --format=json,字段名和文本输出保持一致:jq -r '.items[] | select(.status=="FAIL") | .id' 就能取出失败项去驱动自动化处置。人看文本、机器看 JSON,两份输出共用同一份采集结果,不要写两套逻辑。
- 点赞
- 收藏
- 关注作者
评论(0)