☰
jc 解析器实战指南:使用 `systemctl_lj` 将 systemd 任务队列(list-jobs)输出转换为 JSON
2026/9/26 10:15:37 网站建设 项目流程
  • 开发工具

【免费下载链接】jc

CLI tool and python library that converts the output of popular command-line tools, file-types, and common strings to JSON, YAML, or Dictionaries. This allows piping of output to tools like jq and simplifying automation scripts.

项目地址:https://gitcode.com/gh_mirrors/jc/jc
点击查看免费下载

本文聚焦于 jc 项目中的systemctl_lj解析器,它专门用于将 Linux 上systemctl list-jobs命令输出的 systemd 任务队列文本转换为结构化 JSON 数据。读完本文,你将掌握systemctl_lj的 CLI 与 Python 模块两种调用方式、完整的输出 Schema 与类型转换规则、解析器对真实输出(包括空数据与结尾统计行)的容错处理原理,以及如何结合仓库中的测试夹具进行验证。

什么是systemctl_lj解析器

systemctl list-jobs是 systemd 提供的用于查看当前待执行与正在执行的任务(job)队列的命令,它会列出任务编号(JOB)、目标单元(UNIT)、任务类型(TYPE,如 start/stop/restart)以及任务状态(STATE,如 waiting/running)。默认输出是面向终端阅读的文本表格:

JOB UNIT TYPE STATE 3543 nginxAfterGlusterfs.service start waiting 3545 glusterReadyForLocalhostMount.service start running 3506 nginx.service start waiting 4 jobs listed.

这种表格格式适合人眼观察,却难以直接交给脚本与自动化工具处理。jc 项目中的systemctl_lj解析器(源文件位于 jc/parsers/systemctl_lj.py)正是为了解决这个问题而存在:它读取systemctl list-jobs的文本输出,将其转换为由字典组成的列表,每个字典对应一个任务,包含job、unit、type、state四个字段,从而让输出可以无缝衔接jq等 JSON 处理工具,简化系统管理自动化脚本。

从解析器元数据(info类)可以看到其定位:版本 1.7,作者 Kelly Brazil,compatible = ['linux'](仅面向 Linux 平台),magic_commands = ['systemctl list-jobs']表示 jc 可以在 CLI 中直接识别并匹配该命令的输出,tags = ['command']归类为命令输出解析器。

CLI 用法:两种调用方式

方式一:管道输入

将systemctl list-jobs的输出通过管道交给 jc,并指定--systemctl-lj解析器:

systemctl list-jobs | jc --systemctl-lj

方式二:jc 直接包装命令

利用解析器的magic_commands能力,让 jc 直接运行命令并解析输出:

jc systemctl list-jobs

两条命令的效果等价。man 手册(man/jc.1)中也登记了--systemctl-lj这一 CLI 选项,shell 补全脚本(completions/jc_bash_completion.sh、completions/jc_zsh_completion.sh)同样包含对该选项的补全支持。

常用输出修饰参数

与 jc 所有命令解析器一致,systemctl_lj支持两个重要的输出修饰开关:

  • -p(pretty):以缩进美化格式输出 JSON,便于阅读;
  • -r(raw):跳过类型转换,直接输出"未处理"的原始字符串字段(详见下文 Schema 章节)。

组合使用示例:

systemctl list-jobs | jc --systemctl-lj -p systemctl list-jobs | jc --systemctl-lj -p -r

Python 模块用法

除了命令行,systemctl_lj同样可以作为 Python 库函数使用。解析器名称是systemctl_lj,对应模块jc.parsers.systemctl_lj,核心入口为parse(data, raw=False, quiet=False)函数:

import jc # 假设 systemctl_lj_command_output 为 systemctl list-jobs 的文本输出 result = jc.parse('systemctl_lj', systemctl_lj_command_output)

函数签名与参数含义(与文档及源码实现一致):

参数类型默认值说明
datastring无待解析的文本数据
rawbooleanFalse为True时返回未转换类型的原始结构数据
quietbooleanFalse为True时抑制警告信息(如平台兼容性警告)

返回值恒为"字典列表"(List of Dictionaries),具体形态取决于raw取值:

  • raw=False(默认):经过类型转换、符合 Schema 的处理后数据;
  • raw=True:与文本一一对应的原始字符串字段。

在解析入口处,源码先调用jc.utils.compatibility(__name__, info.compatible, quiet)检查平台兼容性(非 Linux 平台且未指定quiet时会给出警告),再通过jc.utils.input_type_check(data)校验输入类型,最后调用jc.utils.has_data(data)判断是否存在可解析的数据——这些前置检查共同保证了解析器在异常输入下也能安全返回。

输出 Schema 详解

文档中定义的systemctl_lj输出 Schema 如下:

[ { "job": integer, "unit": string, "type": string, "state": string } ]

各字段与systemctl list-jobs输出列的对应关系及类型转换规则:

字段对应列处理后类型说明
jobJOBinteger任务编号,由字符串经convert_to_int转换为整数
unitUNITstring任务作用的 systemd 单元名,如nginx.service
typeTYPEstring任务类型,如start、stop、restart、reload等
stateSTATEstring任务状态,如waiting(排队等待)、running(执行中)

字段名的映射方式非常直接:解析器取文本输出的首行作为表头(转为小写后按空白拆分),再用dict(zip(header_list, entry_list))将表头与每一行数据逐一配对。这意味着如果未来 systemd 改变列顺序或增加列,解析器仍能按新表头自适应生成字段。

类型转换细节:raw 与 processed 的差异

_process()函数是类型转换的关键实现(见 jc/parsers/systemctl_lj.py):

def _process(proc_data): int_list = {'job'} for entry in proc_data: for key in entry: if key in int_list: entry[key] = jc.utils.convert_to_int(entry[key]) return proc_data

它仅将job字段从字符串转换为整数,其余字段保持字符串。因此:

  • 默认输出中,job是无引号的整数(如3543);
  • 使用-r(raw)时,job保留原始字符串形式(如"3543"),便于保留原始文本的逐字段快照。

这与文档给出的两组示例完全吻合。

真实示例:从文本到 JSON

文档示例取自 Ubuntu 18.04 的真实系统,仓库测试夹具(tests/fixtures/ubuntu-18.04/systemctl-lj.out)中保存了对应的原始输入:

JOB UNIT TYPE STATE 3543 nginxAfterGlusterfs.service start waiting 3545 glusterReadyForLocalhostMount.service start running 3506 nginx.service start waiting 4 jobs listed.

默认(processed)输出

systemctl list-jobs | jc --systemctl-lj -p
[ { "job": 3543, "unit": "nginxAfterGlusterfs.service", "type": "start", "state": "waiting" }, { "job": 3545, "unit": "glusterReadyForLocalhostMount.service", "type": "start", "state": "running" }, { "job": 3506, "unit": "nginx.service", "type": "start", "state": "waiting" } ]

raw 输出

systemctl list-jobs | jc --systemctl-lj -p -r
[ { "job": "3543", "unit": "nginxAfterGlusterfs.service", "type": "start", "state": "waiting" }, { "job": "3545", "unit": "glusterReadyForLocalhostMount.service", "type": "start", "state": "running" }, { "job": "3506", "unit": "nginx.service", "type": "start", "state": "waiting" } ]

EXAMPLES 速查文档(EXAMPLES.md)中也收录了同样的用例,并给出了等价写法jc -p systemctl list-jobs,可作为日常速查参考。

解析器源码原理:逐行拆解

深入 jc/parsers/systemctl_lj.py 的parse()主逻辑,其处理流程可以归纳为四个阶段:

  1. 前置校验:依次执行平台兼容性检查(jc.utils.compatibility)、输入类型检查(jc.utils.input_type_check)。
  2. 清理输入:用list(filter(None, data.splitlines()))剔除所有空行;随后对每一行执行非 ASCII 字符清洗——entry.encode('ascii', errors='ignore').decode(),将可能的乱码或特殊字符安全剥离,避免污染后续解析。
  3. 提取表头:取清理后的第一行,转为小写并按空白split()成表头字段列表,作为后续字典的键。
  4. 逐行解析:遍历剩余行。遇到包含'No jobs running.'或'jobs listed.'的行立即终止循环——这正是 systemd 在任务队列为空(No jobs running.)或队列末尾(N jobs listed.)时的输出特征;否则以entry.split(maxsplit=4)拆分当前行(限制最大拆分次数为 4,保证 UNIT 列即使包含空格也不会被错误拆开),与表头配对生成字典并追加到结果列表。

最终,若raw=True直接返回原始字典列表,否则交给_process()完成job字段的整数转换后返回。

边界情况:空数据与空队列

对于完全没有数据的情况,parse('', quiet=True)会返回空列表[]——这一点由单元测试显式覆盖(见下文测试章节)。而对于"有数据但队列为空"的情况(输出只有No jobs running.及统计行),解析逻辑同样会在命中结束标记时停止,不会产生虚假的任务条目。

测试与验证:仓库如何保证正确性

systemctl_lj的正确性由单元测试(tests/test_systemctl_lj.py)保障,测试覆盖了两个场景:

  • test_systemctl_lj_nodata:调用jc.parsers.systemctl_lj.parse('', quiet=True)断言返回[],验证空输入安全;
  • test_systemctl_lj_ubuntu_18_4:读取 Ubuntu 18.04 真实夹具输出 tests/fixtures/ubuntu-18.04/systemctl-lj.out,断言解析结果与预期 JSON tests/fixtures/ubuntu-18.04/systemctl-lj.json 完全一致。

其中预期的 JSON 内容为:

[{"job": 3543, "unit": "nginxAfterGlusterfs.service", "type": "start", "state": "waiting"}, {"job": 3545, "unit": "glusterReadyForLocalhostMount.service", "type": "start", "state": "running"}, {"job": 3506, "unit": "nginx.service", "type": "start", "state": "waiting"}]

可以看到job字段在预期输出中已经是整数类型,与_process()的类型转换行为一一对应。如果你需要在本地复现验证,可以运行项目根目录的测试脚本(如runtests.sh),或直接执行:

python -m unittest tests.test_systemctl_lj

解析器元信息与兼容性说明

根据 docs/parsers/systemctl_lj.md 与源码info类的记录:

  • 版本:1.7
  • 作者:Kelly Brazil(kellyjonbrazil@gmail.com)
  • 兼容平台:仅 Linux(compatible = ['linux']),在非 Linux 平台调用时 jc 会输出兼容性警告,除非传入quiet=True
  • 输入来源:systemctl list-jobs命令标准输出
  • 输出形态:List of Dictionaries(原始或处理后的结构化数据)

需要注意的是,本文所述行为均以当前仓库 jc/parsers/systemctl_lj.py 的实现为准;由于解析器依赖systemctl list-jobs首行表头与固定统计行格式,若 systemd 未来大幅调整输出格式,解析结果可能随之变化。在使用时,请确保运行环境为 Linux 且 systemd 输出保持默认的列式文本布局(不带--no-legend等改变表头或统计行的参数)。

结语:让 systemd 任务队列进入自动化流水线

systemctl_lj解析器为系统管理员与运维脚本提供了一条从 systemd 任务队列到 JSON 的直通路径:既可以在 shell 中用systemctl list-jobs | jc --systemctl-lj即时获得结构化数据,也可以在 Python 中通过jc.parse('systemctl_lj', ...)深度集成。配合-r开关保留原始字符串、quiet抑制告警、以及仓库中配套的测试夹具与速查示例,你可以放心地将任务队列监控、批量服务启停编排等场景交给这一解析器,再交由jq或 Python 程序进一步加工。

  • 开发工具

【免费下载链接】jc

CLI tool and python library that converts the output of popular command-line tools, file-types, and common strings to JSON, YAML, or Dictionaries. This allows piping of output to tools like jq and simplifying automation scripts.

项目地址:https://gitcode.com/gh_mirrors/jc/jc
点击查看免费下载
上一篇:Winboat 自动化部署指南:一键安装与 Windows 服务的无缝集成
下一篇:JavaScript数据拟合终极指南:regression-js让数据分析更简单

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询