- 开发工具
【免费下载链接】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 项目中的efibootmgr解析器(jc/parsers/efibootmgr.py),说明如何将 Linux 下efibootmgr命令输出的 UEFI 启动项信息(BootCurrent、BootOrder、Bootxxxx 启动选项、镜像与内存镜像配置等)转换为结构化 JSON,支持-v详细输出,并给出 CLI 与 Python 模块两种使用方式。读者读完可掌握在自动化脚本、运维巡检与启动项管理中直接消费结构化 UEFI 引导数据的能力。
一、解析器概览与适用场景
efibootmgr是 Linux 下管理 UEFI 启动管理器(Boot Manager)的经典命令行工具,用于查询与编辑 NVRAM 中的启动条目。其输出为纯文本格式,包含当前启动项、超时、启动顺序、各启动选项的设备路径等,逐行解析繁琐且易错。jc 的efibootmgr解析器将其转换为字典/JSON,便于管道到jq或直接进入 Python 数据结构进行二次处理。
依据 jc/parsers/efibootmgr.py 中的解析器元数据:
version = '1.0',作者 Yaofei Zheng;compatible = ['linux'],即该解析器仅在 Linux 平台适用;magic_commands = ['efibootmgr'],这是 jc 通过命令名自动关联解析器的标识;tags = ['command']。
注意:读取 UEFI 启动项通常需要 root 权限,因此示例命令均以sudo执行;解析器本身只负责文本处理,不执行系统命令。
二、命令行用法(CLI)
2.1 基础用法:解析标准输出
$ sudo efibootmgr | jc --efibootmgr2.2 解析详细输出(-v)
efibootmgr -v会在每个启动选项中附带 UEFI 设备路径(如HD(...)、VenHw(...)、PciRoot(...)等),该解析器同样支持:
$ sudo efibootmgr -v | jc --efibootmgr2.3 由 jc 直接执行命令
也可以让 jc 自行运行efibootmgr并解析结果(基于magic_commands自动识别):
$ sudo jc efibootmgr2.4 输出 JSON 并美化
配合 jc 的-p选项输出带缩进的 JSON,便于阅读:
$ sudo efibootmgr -v | jc --efibootmgr --p运行后得到的完整示例输出如下(对应文档中的示例数据):
{ "boot_current": "0002", "timeout_seconds": 0, "boot_order": [ "0002", "0000", "0001" ], "mirrored_percentage_above_4g": 0.0, "mirror_memory_below_4gb": false, "boot_options": [ { "boot_option_reference": "Boot0000", "display_name": "WARNADO", "uefi_device_path": "HD(1,GPT,05b9944c-1c60-492b-a510-7bbedccdc...", "boot_option_enabled": true }, { "boot_option_reference": "Boot0001", "display_name": "Embedded NIC 1 Port 1 Partition 1", "uefi_device_path": "VenHw(3a191845-5f86-4e78-8fce-c4cff59f9daa)", "boot_option_enabled": true }, { "boot_option_reference": "Boot0002", "display_name": "opensuse-secureboot", "uefi_device_path": "HD(1,GPT,c5d4f69d-6fc2-48c7-acee-af3f30336...", "boot_option_enabled": true } ] }三、Python 模块用法
在 Python 中通过jc.parse()接口调用,传入efibootmgr命令输出文本即可:
import jc result = jc.parse('efibootmgr', efibootmgr_command_output)其中efibootmgr_command_output为efibootmgr或efibootmgr -v的 stdout 字符串。返回值为字典(Dictionary),可继续转成 JSON 或直接按键访问,例如:
boot_order = result['boot_order'] for opt in result['boot_options']: if opt['boot_option_enabled']: print(opt['display_name'])parse函数的签名与参数说明见 jc/parsers/efibootmgr.py:
def parse(data: str, raw: bool = False, quiet: bool = False) -> JSONDictType| 参数 | 类型 | 说明 |
|---|---|---|
data | string | 待解析的文本数据(efibootmgr命令输出) |
raw | boolean | 为True时返回未处理(raw)输出,即保留字符串字段,不做类型转换 |
quiet | boolean | 为True时抑制警告信息(例如平台兼容性提示) |
返回值为字典:raw=True时返回原始字符串字段,否则返回经过类型转换的结构化数据。
四、输出 Schema 详解
解析器输出的顶层结构包含以下字段(schema 定义见 jc/parsers/efibootmgr.py):
| 字段 | 类型 | 含义 |
|---|---|---|
boot_current | string | 当前启动项编号(如"0002") |
timeout_seconds | integer | 启动菜单超时秒数 |
boot_order | string[] | 启动顺序编号数组(原输出为逗号分隔,解析后拆分为数组) |
mirrored_percentage_above_4g | float | 4G 以上镜像内存百分比 |
mirror_memory_below_4gb | boolean | 4G 以下内存是否镜像 |
boot_options | object[] | 每个启动选项的详细记录,见下表 |
boot_options数组中的每个元素:
| 字段 | 类型 | 含义 |
|---|---|---|
boot_option_reference | string | 启动选项引用号(如"Boot0000") |
display_name | string | 启动选项显示名称(如"opensuse-secureboot") |
uefi_device_path | string | UEFI 设备路径(仅-v输出包含,如HD(...)、VenHw(...)、PciRoot(...)) |
boot_option_enabled | boolean | 该启动选项是否启用 |
类型转换细节(_process)
_process函数(jc/parsers/efibootmgr.py)负责将原始字符串转换为正确的 Python 类型:
timeout_seconds:通过jc.utils.convert_to_int转为整数(原输出如Timeout: 0 seconds,秒单位被剥离);boot_order:按逗号,拆分为字符串数组;boot_option_enabled:原始输出中启用标记为*(如Boot0000*),解析器将其转换为布尔值True,无*则为False;mirrored_percentage_above_4g:转换为float;mirror_memory_below_4gb:原始值"false"转为布尔False,其余视为True。
uefi_device_path 说明
uefi_device_path仅在efibootmgr -v详细输出中存在,常见形式包括:
- 硬盘分区路径:
HD(1,GPT,<GUID>,0x800,0x100000)/File(\EFI\debian\shimx64.efi) - 硬件厂商路径:
VenHw(<GUID>) - 外设与 NVMe 组合路径:
PciRoot(0x1)/Pci(0x4,0x0)/NVMe(...)/HD(...)
从源码结构看,该字段是按 Tab 分隔解析得到的第二列(boot_record[1]),未启用-v时该列不存在,输出中自然省略。
五、源码解析逻辑深入
parse函数的主体流程(jc/parsers/efibootmgr.py)逐行扫描efibootmgr输出,按行首关键字分流:
BootCurrent行:取冒号后内容,去空格后存入boot_current;Timeout行:取冒号后内容存入timeout_seconds(字符串,后续_process转 int);BootOrder行:取冒号后内容存入boot_order(字符串,后续按逗号拆分);Boot行(即Boot0000* ...这类启动选项记录):按 Tab 切分得到boot_record:boot_record[0][0:8]取前 8 个字符作为boot_option_reference(如Boot0000);boot_record[0][8]取第 9 个字符作为启用标记(*或空格);boot_record[0][10:]取剩余部分作为display_name;boot_record[1](若存在)作为uefi_device_path;
MirroredPercentageAbove4G行:存入mirrored_percentage_above_4g(字符串,后续转 float);MirrorMemoryBelow4GB行:存入mirror_memory_below_4gb(字符串,后续转 bool)。
所有启动选项收集到boot_opt_list后统一放入raw_output["boot_options"]。
解析器在入口处还会调用jc.utils.compatibility做平台兼容性检查,以及jc.utils.input_type_check校验输入类型;当输入为空数据时(jc.utils.has_data判断),直接返回空字典(测试中parse('', quiet=True)的期望结果为{})。
六、测试验证与真实样例
仓库为efibootmgr解析器提供了针对 openSUSE Leap 15.5 的两组真实 fixture 与单元测试:
- 输入样例:tests/fixtures/opensuse-leap-15.5/efibootmgr.out(普通输出)与 tests/fixtures/opensuse-leap-15.5/efibootmgr-v.out(
-v详细输出); - 期望输出:tests/fixtures/opensuse-leap-15.5/efibootmgr.json 与 tests/fixtures/opensuse-leap-15.5/efibootmgr-v.json;
- 测试用例:tests/test_efibootmgr.py。
以-v输出为例,原始文本中Boot0002 Embedded NIC 1 Port 1 Partition 1(无*)在 JSON 中对应"boot_option_enabled": false,且Boot0001的display_name为"RecoveryBoot",设备路径为HD(3,GPT,...)/File(EFI\boot\bootx64.efi),验证了启用标记、名称与设备路径的解析规则;12 个启动选项的BootOrder(0004,0001,...)也正确展开为 12 个元素的数组。
测试覆盖了三个场景:
- 空数据:
parse('', quiet=True)返回{}; - 普通输出:
efibootmgr输出解析结果与efibootmgr.json完全一致; - 详细输出:
efibootmgr -v输出解析结果与efibootmgr-v.json完全一致。
这些测试同时印证了boot_options元素在无-v输出时省略uefi_device_path的行为。
七、实战:结合 jq 与自动化脚本
拿到结构化 JSON 后,可无缝接入jq或脚本做启动项审计,例如:
# 列出所有已启用的启动项名称与引用号 $ sudo efibootmgr -v | jc --efibootmgr | jq -r '.boot_options[] | select(.boot_option_enabled) | "\(.boot_option_reference): \(.display_name)"' # 获取当前启动项及其顺序位置 $ sudo efibootmgr | jc --efibootmgr | jq '{current: .boot_current, order: .boot_order}' # 检查镜像内存配置(如涉及内存镜像的服务器巡检) $ sudo efibootmgr | jc --efibootmgr | jq '{mirrored_percentage_above_4g, mirror_memory_below_4gb}'在 Python 脚本中则可直接消费字典:
import subprocess import jc out = subprocess.check_output(['sudo', 'efibootmgr', '-v'], text=True) data = jc.parse('efibootmgr', out) print(f"当前启动项: {data['boot_current']}") print("启动顺序:", " -> ".join(data['boot_order'])) enabled = [o['display_name'] for o in data['boot_options'] if o['boot_option_enabled']] print("已启用启动项:", enabled)八、注意事项
- 平台限制:解析器声明
compatible = ['linux'],仅适用于 Linux 环境下的efibootmgr输出; - 权限要求:读取 NVRAM 启动项通常需要 root,示例均使用
sudo;解析器本身只处理文本,不负责执行命令; - 版本差异:不同厂商固件(Dell、HP 等)可能输出额外的字段(如
BootNext、Firmware等),当前解析器(版本 1.0)仅提取上述固定字段,其余行将被忽略;这也解释了为何MirroredPercentageAbove4G/MirrorMemoryBelow4GB仅在部分固件输出中出现,解析器对其做了存在性判断; - raw 模式:如需保留原始字符串形态(不做 int/float/bool 转换),可调用
jc.parse('efibootmgr', data, raw=True); - quiet 模式:在非 Linux 平台或脚本批量调用时,可传
quiet=True抑制兼容性警告。
- 开发工具
【免费下载链接】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 解析器实战:使用 jc --gpg 将 gpg --with-colons 输出转换为 JSON
jc 解析器实战:使用 jc gpg 将 gpg with colons 输出转换为 JSON 导读 本文介绍 jc(JSON Convert)项目中的 gpg
开发工具jc 解析 dmidecode:将 Linux 硬件信息 DMI 输出转换为 JSON 的完整指南
jc 解析 dmidecode:将 Linux 硬件信息 DMI 输出转换为 JSON 的完整指南 导读 dmidecode 是 Linux 系统上读取 SMB
开发工具jc 解析器实战:将 `debconf-show` 包配置输出转换为 JSON
jc 解析器实战:将 debconf show 包配置输出转换为 JSON 本指南围绕 jc 项目的 debconf show 解析器展开,讲解如何把 Debi
开发工具
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考