- 开发工具
【免费下载链接】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.
在 Linux 系统运维与自动化中,/proc/driver/rtc是查看硬件实时时钟(RTC)状态的关键入口:RTC 时间日期、闹钟(alarm)设置、IRQ 使能状态、电池状态等信息都以键 : 值的纯文本格式暴露。jc 的proc_driver_rtc解析器可以将该文件内容(或管道输入)转换为标准 JSON、YAML 或 Python 字典,其中yes/no会被自动转换为布尔值、数字字段会尝试转换为整数,从而可以无缝接入jq、自动化脚本和 Python 库调用。读完本文,你将掌握三种调用方式(CLI 管道、CLI 文件直读、Python 模块)、完整的输出 Schema 字段含义、--raw原始模式的行为差异,并能从源码层面理解该解析器的行级拆分逻辑与类型转换实现。
适用场景与兼容性前提
/proc/driver/rtc是 Linux 内核暴露 RTC 驱动状态的 procfs 接口,因此该解析器仅适用于 Linux 平台。这一点在解析器元数据中明确声明(jc/parsers/proc_driver_rtc.py 中compatible = ['linux'])。
从源码结构看,解析入口首先会调用jc.utils.compatibility(__name__, info.compatible, quiet)做平台检查。该函数定义在 jc/utils.py:如果当前sys.platform不在兼容列表中且quiet=False,则向STDERR打印一条警告(说明当前 OS 不支持、列出受支持平台,并提示若处理的是来自受支持平台的输出可忽略该警告,用-q选项可抑制)。需要注意这只是警告而非异常——在 macOS 或 Windows 上解析从 Linux 机器采集回来的driver_rtc文本内容依然可以正常工作,只是会多一条警告输出。
三种调用方式
解析器文档(docs/parsers/proc_driver_rtc.md)给出了三种等价用法:
方式一:管道 +--proc自动识别
$ cat /proc/driver/rtc | jc --proc这里的--proc是 jc 的/proc文件自动分发器。其实现位于 jc/parsers/proc.py:它维护了一组"签名正则",用文件开头的若干行特征来识别具体是哪种/proc文件,然后调用对应的具体解析器。/proc/driver/rtc的识别签名是(jc/parsers/proc.py):
driver_rtc_p = re.compile(r'^rtc_time\t: .*\nrtc_date\t: .*\nalrm_time\t: .*\n')即要求文件开头连续三行为rtc_time、rtc_date、alrm_time(各带制表符分隔的: 值)。匹配成功后,procmap字典会将其路由到proc_driver_rtc模块(jc/parsers/proc.py),通过jc.lib.get_parser('proc_driver_rtc')动态加载并调用其parse()函数(jc/lib.py)。如果所有签名都不匹配,则抛出ParseError('Proc file could not be identified.')。
方式二:jc直接读文件路径(魔法语法)
$ jc /proc/driver/rtcjc支持以/proc/<路径>作为参数的"魔法语法",同样支持通配符批量读取多个文件(如jc /proc/*/stat),此时所有输出会被包裹在数组中,并附带_file字段用于关联输入输出文件。注意使用此语法时,所有jc选项必须放在/proc路径之前。
方式三:显式指定解析器名称
$ cat /proc/driver/rtc | jc --proc-driver-rtc按proc-<name>(CLI)/proc_<name>(模块)的命名约定直接调用具体的 proc 子解析器,跳过自动识别环节。
Python 模块方式
import jc result = jc.parse('proc', open('/proc/driver/rtc').read()) # 或 result = jc.parse('proc_driver_rtc', open('/proc/driver/rtc').read())jc.parse()是 jc 提供的高层 API(jc/lib.py),可接受解析器模块名字符串或模块对象,内部完成动态加载、兼容性与输入类型检查,并统一调用目标解析器的parse()函数。低层级也可直接import jc.parsers.proc_driver_rtc后调用其parse()。
输出 Schema 与字段含义
解析后的输出是一个扁平字典,共 18 个字段(docs/parsers/proc_driver_rtc.md 中的 Schema):
{ "rtc_time": string, "rtc_date": string, "alrm_time": string, "alrm_date": string, "alarm_IRQ": boolean, "alrm_pending": boolean, "update IRQ enabled": boolean, "periodic IRQ enabled": boolean, "periodic IRQ frequency": integer, "max user IRQ frequency": integer, "24hr": boolean, "periodic_IRQ": boolean, "update_IRQ": boolean, "HPET_emulated": boolean, "BCD": boolean, "DST_enable": boolean, "periodic_freq": integer, "batt_status": string }字段含义可归纳为四类:
- 时间与闹钟:
rtc_time/rtc_date是硬件 RTC 当前的时间(HH:MM:SS)与日期(YYYY-MM-DD);alrm_time/alrm_date是 RTC 硬件闹钟的预设值,未设闹钟时通常为00:00:00;alarm_IRQ表示是否启用了闹钟触发的中断,alrm_pending表示是否有待处理的闹钟事件。 - IRQ 状态:
update IRQ enabled/update_IRQ对应每秒一次(update)时钟中断,periodic IRQ enabled/periodic_IRQ对应用户可配置频率的周期中断;periodic IRQ frequency是实际启用的周期中断频率(示例中为 1024 Hz,即内核CONFIG_HZ高配值),max user IRQ frequency是驱动允许用户空间设置的最大频率(示例中为 64 Hz)。 - 格式与平台特性:
24hr表示 RTC 以 24 小时制计时;BCD表示 RTC 寄存器以 BCD 编码读写;DST_enable表示是否由 RTC 硬件本身处理夏令时;HPET_emulated为true时说明该"RTC"实际上是内核基于 HPET 等定时器模拟出来的(常见于虚拟机环境,此时通常没有物理电池,batt_status恒为okay)。 - 电池健康:
batt_status是 CMOS 电池电压状态的字符串,正常为okay。
值得注意的"双命名"现象:输出中同时存在update IRQ enabled/periodic IRQ enabled(来自驱动rtc_sysfs暴露的update_irq_enabled等带空格属性名)与update_IRQ/periodic_IRQ(传统rtc驱动的文件名风格),二者语义相近但来源不同,解析器会原样保留两种键名,自动化脚本中应选取自己内核版本实际存在的字段做判断。
完整输入输出示例
原始输入(仓库测试夹具 tests/fixtures/linux-proc/driver_rtc,格式为键<制表符>: 值,键与冒号之间用制表符对齐):
rtc_time : 16:09:21 rtc_date : 2022-09-03 alrm_time : 00:00:00 alrm_date : 2022-09-03 alarm_IRQ : no alrm_pending : no update IRQ enabled : no periodic IRQ enabled : no periodic IRQ frequency : 1024 max user IRQ frequency : 64 24hr : yes periodic_IRQ : no update_IRQ : no HPET_emulated : yes BCD : yes DST_enable : no periodic_freq : 1024 batt_status : okay处理后输出(jc --proc -p,-p为 pretty print):
{ "rtc_time": "16:09:21", "rtc_date": "2022-09-03", "alrm_time": "00:00:00", "alrm_date": "2022-09-03", "alarm_IRQ": false, "alrm_pending": false, "update IRQ enabled": false, "periodic IRQ enabled": false, "periodic IRQ frequency": 1024, "max user IRQ frequency": 64, "24hr": true, "periodic_IRQ": false, "update_IRQ": false, "HPET_emulated": true, "BCD": true, "DST_enable": false, "periodic_freq": 1024, "batt_status": "okay" }原始模式输出(jc --proc -p -r):yes/no保持字符串原样,数字也不再转换为整数:
{ "rtc_time": "16:09:21", "rtc_date": "2022-09-03", "alrm_time": "00:00:00", "alrm_date": "2022-09-03", "alarm_IRQ": "no", "alrm_pending": "no", "update IRQ enabled": "no", "periodic IRQ enabled": "no", "periodic IRQ frequency": "1024", "max user IRQ frequency": "64", "24hr": "yes", "periodic_IRQ": "no", "update_IRQ": "no", "HPET_emulated": "yes", "BCD": "yes", "DST_enable": "no", "periodic_freq": "1024", "batt_status": "okay" }对照两份输出即可看出--raw(或模块参数raw=True)的作用边界:它关闭的是"类型转换"这一后处理步骤,而不影响键值对的拆分本身——即使原始模式下,1024仍是字符串"1024",yes仍是字符串"yes"。
源码级实现解析
解析器完整实现仅百余行,位于 jc/parsers/proc_driver_rtc.py,核心是parse()与_process()两个函数。
行级拆分:parse()
parse(data: str, raw: bool = False, quiet: bool = False) -> Dict的处理流程(jc/parsers/proc_driver_rtc.py):
- 前置检查:
jc.utils.compatibility(...)做平台兼容警告(见前文);jc.utils.input_type_check(data)校验输入必须是str/bytes,防止误传字典等类型(jc/utils.py)。 - 空数据短路:
jc.utils.has_data(data)判断输入是否只含空白字符,为空则直接返回{}(jc/utils.py),因此该解析器对空输入是安全幂等的。 - 逐行拆分:
for line in filter(None, data.splitlines()): split_line = line.split(':', maxsplit=1) key = split_line[0].strip() val = split_line[1].rsplit(maxsplit=1)[0] raw_output[key] = valsplit(':', maxsplit=1)在第一个冒号处切开,因此值中即使再含冒号(如rtc_time : 16:09:21的时间部分)也不会被截断;key.strip()容忍键前/后的空白与制表符(这正是原文档中24hr\t\t: yes这类双制表符对齐行也能正确解析的原因);rsplit(maxsplit=1)[0]则从右侧最多切一刀取左段,配合整体逻辑把值右侧的空白去掉。最终raw_output就是一个"原样文本"的键值字典,raw=True时直接返回它,否则交给_process()。
类型转换:_process()
后处理函数(jc/parsers/proc_driver_rtc.py)对每个键值做两件事:
for key, val in proc_data.items(): try: proc_data[key] = int(val) except: pass if val == 'yes': proc_data[key] = True if val == 'no': proc_data[key] = False- 先尝试
int(val):成功则值变为整数(如periodic IRQ frequency从"1024"变1024),失败(时间、okay等)则保持字符串; - 再做精确匹配:值恰好为
'yes'转True、恰好为'no'转False(注意区分大小写,且只有全等匹配才转换,例如值"no"以外的其他文本不受影响)。
由于时间字段本身含冒号但整体不是整数,它们始终停留在字符串阶段;batt_status的"okay"同理。这段实现的副作用值得留意:如果某内核版本让某字段输出"yes"之外的布尔表示(如"enabled"),解析器不会猜测转换,会原样保留字符串——这一点在使用jq做布尔判断时需要知道。
测试验证与行为边界
测试用例位于 tests/test_proc_driver_rtc.py,覆盖了两个关键路径:
test_proc_driver_rtc:读取夹具 tests/fixtures/linux-proc/driver_rtc,断言parse(..., quiet=True)的结果与预期 JSON 夹具 tests/fixtures/linux-proc/driver_rtc.json 完全一致,验证了上文示例中全部 18 个字段的类型与取值;test_proc_driver_rtc_nodata:断言parse('', quiet=True)返回{},印证了空输入不抛异常的行为。
此外该解析器在元数据中标记hidden = True(jc/parsers/proc_driver_rtc.py),从源码结构看,这意味着它不出现在常规帮助列表的主展示中,但仍可通过jc -hh/jc -a查看,并可直接以--proc-driver-rtc调用——如果你用jc -h找不到它属于正常现象。
典型管道用法
结合jq做状态断言,例如检查 CMOS 电池是否健康、RTC 是否 24 小时制:
$ cat /proc/driver/rtc | jc --proc-driver-rtc | jq '{battery: .batt_status, is_24hr: .["24hr"], alarm_irq: .alarm_IRQ}' { "battery": "okay", "is_24hr": true, "alarm_irq": false }在 Python 自动化脚本中读取电池状态与周期中断频率:
import jc with open('/proc/driver/rtc') as f: rtc = jc.parse('proc_driver_rtc', f.read(), quiet=True) if rtc.get('batt_status') != 'okay': print('RTC battery fault!') print('periodic freq:', rtc.get('periodic_freq'))总结:jc 的proc_driver_rtc解析器以"首个冒号切分 + 整数/布尔后处理"的简洁策略,把/proc/driver/rtc的纯文本状态表转换为可直接供jq与 Python 消费的结构化数据;--raw/raw=True提供了关闭类型转换的逃生门;通过jc --proc的签名正则路由或直接指定--proc-driver-rtc均可稳定命中该解析器。适用前提为 Linux 平台(跨平台处理采集数据仅产生警告);字段集随内核 RTC 驱动实现可能略有差异(如 HPET 模拟环境下无真实电池),脚本中建议用get()防御性取值。
- 开发工具
【免费下载链接】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.
相关推荐
jc proc-cpuinfo 解析器:将 Linux /proc/cpuinfo 精准转换为结构化 JSON
jc proc cpuinfo 解析器:将 Linux /proc/cpuinfo 精准转换为结构化 JSON 本文基于 proc_cpuinfo 解析器文档
开发工具jc proc_diskstats 解析器:将 /proc/diskstats 转换为 JSON 以结构化分析磁盘 I/O 统计
jc proc_diskstats 解析器:将 /proc/diskstats 转换为 JSON 以结构化分析磁盘 I/O 统计 本文基于 proc_disks
开发工具jc proc_devices 解析器实战:将 /proc/devices 设备号与设备名结构化为 JSON
jc proc_devices 解析器实战:将 /proc/devices 设备号与设备名结构化为 JSON 本文基于 jc 仓库中的 proc_devices
开发工具
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考