- 运维
- 配置管理
- 后端
【免费下载链接】salt
Software to automate the management and configuration of infrastructure and applications at scale.
导读
Salt 的输出器(outputter)负责把 minion 返回的数据格式化成人类可读或机器可解析的文本。其中json_out模块将返回数据序列化为标准 JSON,是脚本化、自动化对接 Salt 时最常用的输出器。本文以 salt.output.json_out.rst 为骨架,结合 salt/output/json_out.py 源码、tests/pytests/unit/output/test_json_out.py 与 tests/pytests/integration/cli/test_salt_call.py 集成测试,带你掌握--out=json的完整用法、--out-indent与output_indent的取值语义,以及输出器在 Salt 内部的调度与序列化细节。
一、模块定位:Salt 的 JSON 输出器
Salt 内置多种输出器(highstate、json、key、nested、pprint、raw、txt、yaml等),完整清单见 doc/ref/output/all/index.rst。json_out模块的虚拟名(virtual name)是json,通过__virtual__()将模块重命名为json,因此在命令行中写--out=json即可触发它(见 salt/output/json_out.py)。
json_out的核心价值在于:输出是标准 JSON,任何语言的 JSON 解析器都能直接消费,特别适合需要把 Salt 执行结果喂给 CI/CD、监控告警、自研 Web 平台的场景。
二、触发方式:命令行与配置双入口
2.1 命令行指定
所有 Salt CLI(salt、salt-call、salt-run、salt-key等)都支持通用输出选项(定义见 doc/ref/cli/_includes/output-options.rst):
salt '*' test.ping --out=json salt '*' network.hw_addr en0 --out=json--out的取值见 salt/utils/parsers.py,它映射到dest="output"。
2.2 配置文件中固化
如果不希望每次敲命令都带参数,可以在 Master 或 Minion 配置文件中设置output和output_indent,例如conf/master、conf/minion。配置后所有输出默认走 JSON。
三、缩进控制:--out-indent 与 output_indent
这是json_out文档中最核心的配置话题,官方文档明确给出三种取值语义(见 salt/output/json_out.py):
| 取值 | 语义 |
|---|---|
Null(None) | 每个 minion 的返回结果合并为单行JSON |
pretty | 使用四空格缩进,且对键排序(sort_keys) |
| 整数 | 指定缩进级别(空格数);负数等价于单行 |
3.1 通过 CLI 标志设置
# 单行紧凑输出(每 minion 一行,适合逐行解析) salt '*' test.ping --out=json --out-indent=-1 # 按空格数缩进 salt '*' test.ping --out=json --out-indent=2 # 键排序 + 四空格缩进(pretty) salt-call test.ping --out=json --output-indent=pretty--out-indent与--output-indent是同一选项的两个别名,在 salt/utils/parsers.py 中声明,dest="output_indent"、type=int。注意:CLI 层面它是整数类型,所以pretty这种字符串取值只能通过配置文件output_indent设置。
3.2 配置文件方式
在conf/master或conf/minion中设置:
output: json output_indent: pretty # 或 None,或整数四、按 minion 逐条输出的设计
Salt 的输出器是按 minion 粒度工作的:每个 minion 的返回数据到达 Master 后,会被各自序列化为一个独立的 JSON 对象(见 salt/output/json_out.py)。
$ salt '*' network.hw_addr en0 --out=json --out-indent=-1 {"dave": {"en0": {"hwaddr": "02:b0:26:32:4c:69", ...}}} {"jerry": {"en0": {"hwaddr": "02:26:ab:0d:b9:0d", ...}}} {"kevin": {"en0": {"hwaddr": "02:6d:7f:ce:9f:ee", ...}}} {"mike": {"en0": {"hwaddr": "02:48:a2:4b:70:a0", ...}}} {"phill": {"en0": {"hwaddr": "02:1d:cc:a2:33:55", ...}}} {"stuart": {"en0": {"hwaddr": "02:9a:e0:ea:9e:3c", ...}}}官方文档特别提醒(见 salt/output/json_out.py):部分 JSON 解析器能猜出对象边界,但很多不能。可靠的做法是使用单行输出格式,逐行解析——每行一个完整 JSON 对象,天然避免跨行截断问题。例如配合jq:
salt '*' test.ping --out=json --out-indent=-1 | jq -r 'keys[]'五、源码级实现剖析
5.1 output() 的缩进决策逻辑
json_out.output(data, **kwargs)是模块入口(见 salt/output/json_out.py),其完整决策树如下:
- 若
__opts__中不存在output_indent键:直接以indent=4输出(默认行为,等价于四空格缩进但不排序); - 若
output_indent为None:indent=None,输出为单行紧凑 JSON; - 若为
"pretty":indent=4且sort_keys=True,键按字典序排序; - 若为整数:直接作为缩进空格数;负数被归一化为
None(单行)。
最终统一调用:
salt.utils.json.dumps(data, default=repr, indent=indent, sort_keys=sort_keys)其中default=repr非常关键:当返回数据里含有 JSON 无法原生序列化的对象(如 Python 的datetime、自定义类)时,会退而求其次用repr()的字符串形式代替,保证整体仍是合法 JSON。
5.2 异常兜底
except UnicodeDecodeError as exc: log.error("Unable to serialize output to json") return salt.utils.json.dumps({"error": "Unable to serialize output to json", "message": str(exc)}) except TypeError: log.debug("An error occurred while outputting JSON", exc_info=True) return salt.utils.json.dumps({})遇到不可解码的字节序列时,返回一个带error/message字段的 JSON 错误对象,方便调用方程序化感知失败;遇到其他序列化TypeError时返回{},保证任何情况下输出的都是合法 JSON,不会向管道吐出裸异常堆栈。
5.3 底层序列化封装 salt.utils.json
json_out使用的 salt/utils/json.py 是对标准库json的封装,几个值得注意的点:
- Unicode 兼容:
dumps/dump默认ensure_ascii=False,中文等非 ASCII 字符原样输出而非转义成\uXXXX,便于阅读与传输(见 salt/utils/json.py)。这解释了单元测试test_unicode_output中"Д"能原样出现在输出里(见 tests/pytests/unit/output/test_json_out.py); - 快速库优先:
import_json()按ujson → yajl → json的顺序尝试导入,优先使用更快的 C 实现(见 salt/utils/json.py); - bytes 兼容:
loads遇到 Python < 3.6 无法直接解析的 bytestring 时自动转成 Unicode 再解析(见 salt/utils/json.py)。
六、输出器调度与回退机制
当用户指定--out=json后,数据流向为(见 salt/output/init.py):
display_output()先调用try_printout()取格式化结果;try_printout()通过salt.loader.outputters(opts)加载所有输出器,若指定的输出器不存在,则回退到nested,再不行回退到raw(见 salt/output/init.py);- 若指定了
--out-file/--output-file,结果写入文件(追加模式)而非 stdout;否则通过print_cli()打印。
因此即使json_out模块异常,Salt 仍会兜底输出而不是静默丢弃数据。
七、测试验证:行为即契约
json_out的行为被单元测试与集成测试双重锁定,可作为你验证本地 Salt 环境输出行为的参照:
- 单元测试 tests/pytests/unit/output/test_json_out.py 覆盖:无
output_indent时默认输出、pretty键排序、整数缩进、0/负数缩进、Unicode 输出; - 集成测试 tests/pytests/integration/cli/test_salt_call.py 用真实 CLI 断言了三种缩进下的精确输出:
# --out-indent=-1 {"local": true} # --out-indent=0 { "local": true } # --out-indent=1 { "local": true }这些断言与源码中"负数 → 单行、整数 → 空格数"的规则完全一致,是理解行为最可靠的参考。
八、实战建议
- 脚本解析首选单行:
--out=json --out-indent=-1保证每个 minion 一条记录,逐行json.loads()即可,避免依赖解析器的对象边界猜测能力; - 日志/审计用 pretty:需要人读时用
--output-indent=pretty(四空格 + 键排序,输出确定性强,便于 diff); - 程序化错误感知:序列化失败时输出的是带
error字段的合法 JSON,调用方应显式检查该字段; - 结果落盘:配合
--out-file将 JSON 结果直接追加写入文件,供下游批处理消费。
从 CLI 标志到output_indent配置,从单行逐条解析到repr兜底与 Unicode 原样输出,json_out是理解 Salt 输出器体系(模块加载、虚拟名、回退机制)的最佳切入口;如需查看其他输出器,可继续阅读 doc/ref/output/all/index.rst 中的yaml_out、nested等模块文档。
- 运维
- 配置管理
- 后端
【免费下载链接】salt
Software to automate the management and configuration of infrastructure and applications at scale.
相关推荐
RemoveWindowsAI 命令行参数速查:3 种组合搞定 90% 的清理场景
RemoveWindowsAI 命令行参数速查:3 种组合搞定 90% 的清理场景 RemoveWindowsAI 是一个用于移除 Windows 11 中 C
运维配置管理后端Salt Master 配置完全指南:从 /etc/salt/master 到源码级参数解析
Salt Master 配置完全指南:从 /etc/salt/master 到源码级参数解析 Salt(SaltStack)是一个用于大规模基础设施与应用配置管
运维配置管理后端Velero CLI 完全解析:`get restores` 命令的参数、输出格式与源码级实现原理
Velero CLI 完全解析: get restores 命令的参数、输出格式与源码级实现原理 本文以 Velero(前身 Ark)早期版本 v0.5.0 的
云原生灾备存储后端
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考