日志审计报告离线自测(log-audit-report-test.py)¶
位置:
deploy/nfos/tools/log-audit-report-test.py| 语言:python3 | 是否需要 root:否
工具性质:离线自测(会写临时文件;不联网、不调 journalctl、不需要 root)
运行前提:仓库检出必须在场 —— 加载 deploy/nfos/log-audit.py。可从任意位置运行(工具自动向上找到含 deploy/nfos 的祖先目录)
部署状态:随仓库检出运行,不部署到 /opt/Cy/services/system.d/nfos/
用途¶
对 deploy/nfos/log-audit.py 做离线自测,覆盖报告生成、状态文件原子替换、自动恢复与窗口解析回退。
源码 docstring 的用法与覆盖点(逐字引用):
python3 .scratch/log-audit-report-test.py
覆盖:
1. 报告文件:无命中 → 写“未发现异常”;有命中 → 签名/计数/最多 3 条样例
2. 目录不存在时自动 mkdir -p(幂等,跑两次)
3. 状态文件:本轮活动键 + 时间戳(原子替换)
4. 自动恢复:只恢复 `nfos.log:` 前缀的键;平台不可达时返回 recovered=False 而不抛异常
5. 窗口表达式解析失败时回退为原样字符串(不抛异常)
实际执行的 6 组用例:1(无命中报告)、1b(库缺 log_anomaly 条目时的 aborted 报告,备节点实测形态)、2(有命中:签名/计数/最多 3 条样例 / 工单号 / 自动恢复结果 / --dry-run 另存 *-dryrun.md)、3(报告目录被删后自动 mkdir -p 且重复写入幂等)、4(状态文件覆盖更新 + 原子替换后无残留 .tmp)、5(recover_stale 只碰 nfos.log: 前缀,空列表/None 安全)、6(window_bounds 解析失败原样保留)。
被测入口:write_report、state_put、recover_stale、window_bounds,以及模块常量 REPORT_DIR、STATE_FILE。
典型场景¶
- 改动
log-audit.py的write_report/ 自动恢复逻辑之后的提交前回归; - 备节点出现“特征库里没有
detect=log_anomaly的条目”导致审计空跑时,用 1b 用例确认报告文案是本次审计未执行而不是误写成“未发现异常”; - 平台不可达(
nfarmsd挂掉)时确认自动恢复不抛异常、报告仍照常产出。
用法与参数¶
源码 docstring 给出的用法(逐字引用,.scratch/ 为升级前旧路径,本页按新位置书写):
本工具不接受任何命令行参数;它在进程内改写三个环境变量(只影响本进程,不写入系统环境):
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| (无) | — | — | 无 argparse、不读 sys.argv |
NFOS_DIR |
环境变量(进程内设置) | <repo>/.tmp/log-audit-test/nfos |
被加载模块的 NFOS 目录 |
NFOS_LOG_AUDIT_REPORT_DIR |
环境变量(进程内设置) | <repo>/.tmp/log-audit-test/reports |
报告输出目录 |
NFARMSD_API |
环境变量(进程内设置) | http://127.0.0.1:9 |
故意指向必然连不上的端口,用于验证“平台不可达不抛异常” |
无参数时的默认行为:跑完 1–6 组全部用例,打印结论与 ALL_PASS,结束时删除自己的临时目录。
示例¶
从仓库根目录执行:
期望输出(实测:检查项 27、失败 0,末行 ALL_PASS):
中间会打印 == 1. 报告文件:无命中 == … == 6. 窗口解析回退 == 与逐项 ok ...。
| 情形 | 期望退出码 |
|---|---|
全部通过(检查项 N,失败 0 + ALL_PASS) |
0 |
存在失败项(检查项 N,失败 M 后逐条列出 FAIL) |
1 |
| 被加载模块缺失 / 模块级代码抛异常 | 1(importlib 异常,Python traceback,非自检语义) |
依赖与权限¶
- 语言/版本:Python 3(
#!/usr/bin/env python3)。 - 第三方依赖:无,标准库
importlib.util/io/json/os/shutil/sys/tempfile。 - 仓库依赖:必需 —— 加载
<repo>/deploy/nfos/log-audit.py;_nf_repo_root()向上找第一个含deploy/nfos的祖先目录。 - 权限:不需要 root;需要工作区写权限(写
<repo>/.tmp/log-audit-test/)。
风险与注意事项¶
- 会写文件(仅自己的临时目录):
<repo>/.tmp/log-audit-test/,内含测试用报告(含*-dryrun.md)与状态文件;正常结束时shutil.rmtree删除。 - 不碰线上:
NFARMSD_API被指向127.0.0.1:9,因此不会真的调用nfarmsd写恢复;不调用journalctl、不读/opt/Cy/logs以外的真实日志、不需要 root —— 源码 docstring 自述“不联网、不调 journalctl、不需要 root”。 - 环境变量是进程内注入:三个变量在脚本内
os.environ[...] = ...覆盖,只影响本进程与被它 import 的模块;不会改系统/用户环境,也不会污染父 shell。 - 会执行被测模块的模块级代码:
log-audit.py的模块级常量(如REPORT_DIR、STATE_FILE)会在加载时按注入的环境变量求值 —— 这正是用例 3/4 能重定向报告目录与状态文件的原因。 - 断言锁定的是报告文案契约(
未发现异常、本次审计未执行、/libs/apply、已恢复、dry-run、命中条数:0、命中次数:3等):改动这些文案需同步改本自测。
回滚¶
本工具不部署到线上、不改线上系统;唯一的落盘物是它自己的临时目录。
- 落盘位置:
<repo>/.tmp/log-audit-test/(报告目录 + 状态文件 +nfos/子目录)。 - 正常情况下运行结束自动删除;被中断时手动清理:
- 不写
deploy/nfos/state/、不写/opt/Cy/logs/,因此无需回滚线上报告或状态文件。