跳转至

三库 YAML 转义修复(fix-lib-yaml.py)

位置:deploy/nfos/tools/fix-lib-yaml.py | 语言:python3 | 是否需要 root:否

工具性质:会原地改写传入文件的修复器(不是只读工具) 运行前提:需要 PyYAML(唯一带非标准库依赖的工具);目标文件路径由命令行给出 部署状态:随仓库检出运行,不部署到 /opt/Cy/services/system.d/nfos/


用途

修复三库 YAML(deploy/nfos/signature-library.yml、rule-library.yml、template-library.yml)里“双引号标量非法转义”的写法。

源码 docstring 记录的病根(逐字引用):

背景:正则模式在 YAML 双引号里必须写成 `\\s`(双反斜杠),
但新增条目写成了 `"\[notice\]"` —— YAML 双引号只认 \\ \" \n \t 等,
`\[` 是非法转义 → yaml.safe_load 整库解析失败 → 平台 signatures=0、apply 报 invalid。

修法(源码 docstring 逐字):

修法:逐行取 `- "..."` 形式的标量,单独试解析;失败则按“反斜杠是字面量”的原意重建:
  · 内容不含单引号 → 改成 YAML 单引号(单引号里反斜杠是字面量,最省事)
  · 内容含单引号   → 保留双引号,把反斜杠与双引号正确转义
幂等:已正确的行不动。

关键实现边界:

环节 源码行为
命中行 仅匹配 ^(\s*- )"(.*)"(\s*(?:#.*)?)$,即列表项形式的双引号标量(含行尾注释)
跳过条件 yaml.safe_load('"..."') 能解析成功 → 该行不动(幂等来源)
兜底 单引号版仍不合法(极罕见)→ 退回双引号全转义
写回 io.open(path, "w", encoding="utf-8", newline="\n") —— 统一 LF 换行
打印上限 每个文件最多打印前 12 条改动(ch[:12])

典型场景

  • 新增特征条目后平台 signatures=0 或 /libs/apply 报 invalid / 整库解析失败时,先跑一次修转义;
  • 合并别人提交的三库 YAML(手工编辑容易写出 "\[...\]" 这类非法转义)后做一次归一化;
  • 作为“YAML 双引号里塞正则”的机械修复步骤,配合 yaml.safe_load 复验。

用法与参数

源码 docstring 给出的用法(逐字引用):

用法:python fix-lib-yaml.py <文件> [<文件>...]

参数只有位置参数,不经过 argparse,直接取 sys.argv[1:]:

参数 类型 默认值 说明
sys.argv[1:] 一个或多个文件路径 空(不修复任何文件) 逐个文件原地修复;相对路径按当前工作目录解析

无参数时的默认行为:不处理任何文件,直接打印 合计修复 0 行 并以 0 退出(不会去猜三库路径)。

示例

先备份、再修复、再复验(推荐顺序:本工具没有 --dry-run,也不自己备份):

Copy-Item deploy/nfos/signature-library.yml deploy/nfos/signature-library.yml.bak
python deploy/nfos/tools/fix-lib-yaml.py deploy/nfos/signature-library.yml

期望输出形态(每个文件一行 + 明细,末行合计):

  signature-library.yml:修复 2 行
    :318   - "\[notice\]"
           → - '\[notice\]'
  合计修复 2 行

Windows 提示:打印文件名用的是 path.split("/")[-1],传反斜杠路径时不会切分,会打印成完整路径;这只是显示差异,不影响修复。

情形 期望退出码
正常结束(含“修复 0 行”) 0
缺少 PyYAML 2(先打印 需要 PyYAML,在写任何文件之前退出)
目标文件不存在 / 不可写 1(Python traceback,非自检语义)

缺依赖时的实测形态(本机实测:当前 Python 环境未安装 PyYAML,因此无参数运行也会直接停在这一步):

python deploy/nfos/tools/fix-lib-yaml.py
需要 PyYAML

退出码 2。要真正执行修复,需先 pip install PyYAML;注意:不要为了跑一次修复而盲目装库,且安装前先确认这是预期环境(本批其余 16 个工具都不需要任何第三方包)。

依赖与权限

  • 语言/版本:Python 3。
  • 第三方依赖:PyYAML(import yaml)—— 本批 17 个工具中唯一带非标准库依赖的工具;缺失时守卫式退出码为 2。
  • 仓库依赖:无(文件由命令行给出;不给参数则什么都不做)。
  • 权限:不需要 root;但需要对目标 YAML 有写权限(原地改写)。

风险与注意事项

  • 会改文件(原地写):这是本批工具里少数会改动源码树文件的工具。传入路径即被写入,不做备份、无 --dry-run、无 diff 文件输出。
  • 换行会被归一化:写回固定 newline="\n",原本 CRLF 的文件会整体变成 LF,可能造成比预期更大的 diff。
  • 只覆盖列表项形式:- "..." 之外的双引号标量(如 key: "...")不修;fix-lib-yaml.py 不能替代全库 yaml.safe_load 复验。
  • 修复规则是“把反斜杠当字面量”,若原意确实是 YAML 转义(\n、\t、\"),该行的解析失败原因不同,通常不会被误改(能解析成功的行一律不动)。
  • 三库 YAML 属于线上平台读取的特征库数据:本工具只改仓库里的源文件,不会推送/生效到服务器;生效仍需走正常发布与 /libs/apply 流程。

回滚

本工具不部署到线上、不改线上系统;它的“产物”就是被改写的 YAML 文件本身。

  • 变更点:命令行传入的每个 YAML 文件(原地覆盖写)。
  • 清理/恢复方式:用运行前的备份覆盖回去:
Copy-Item deploy/nfos/signature-library.yml.bak deploy/nfos/signature-library.yml -Force
  • 除此之外无临时目录、无缓存、无状态文件;删除 .bak 备份即完成清理。