Linux 怎样用 lsblk JSON 输出设备层级
来源:17golang原创
时间:2026-10-18 02:27:29 467浏览 收藏
想把 Linux 块设备交给脚本处理时,推荐把 lsblk 当成“固定字段的 JSON 数据源”使用:先用 --list-columns 确认字段,再用 -J -o NAME,TYPE,SIZE,PKNAME,MOUNTPOINTS --tree 输出设备树。JSON 顶层通常是 blockdevices,子设备放在父节点的 children 数组里;如果没有 NAME 列,也没有显式 --tree,就不要期待层级数组出现。
本文只讨论 lsblk 的 JSON 字段和树形关系,不把示例输出当成本机运行结果。官方项目地址:https://github.com/util-linux/util-linux/;命令手册:https://man7.org/linux/man-pages/man8/lsblk.8.html。
先固定 JSON 的字段边界
lsblk 默认展示列会随版本和环境变化,脚本不应直接解析默认表格。先列出当前版本支持的字段,再只选择业务真正需要的列。NAME 用来表达设备名称和层级,TYPE 帮助区分磁盘、分区或映射设备,PKNAME 可以辅助回看父设备,MOUNTPOINTS 则可能包含多个挂载点。
# 先查看当前 lsblk 可以接受哪些输出列,避免凭记忆写错字段名。 lsblk --list-columns # 固定脚本需要的列,并显式打开树形关系。 lsblk --json --tree --output NAME,TYPE,SIZE,PKNAME,MOUNTPOINTS # 需要机器可比较的大小时,再把 SIZE 改为字节单位输出。 lsblk --json --tree --bytes --output NAME,TYPE,SIZE,PKNAME,MOUNTPOINTS
字段名建议写成大写列名,既容易和手册对应,也能减少本地化环境下的歧义。--bytes 只影响尺寸的表示方式,不会改变设备之间的层级关系。

用 blockdevices 和 children 读取设备树
打开 JSON 后,可以把顶层 blockdevices 看作根节点集合。整块磁盘通常在根数组里,分区或映射设备可能嵌套在它的 children 中。下面的内容是为了说明字段形状而写的静态示例,实际设备名称、容量和挂载点会随主机变化。
{
"blockdevices": [
{
"name": "sda",
"type": "disk",
"size": "100G",
"pkname": null,
"children": [
{
"name": "sda1",
"type": "part",
"size": "99G",
"pkname": "sda",
"mountpoints": ["/"]
}
]
}
]
}
不要只按数组下标取值。某个节点可能没有 children,也可能有空数组;挂载点还可能是 null 或包含多个元素。更稳妥的做法是把“当前节点”和“子节点遍历”分开处理。
# jq 只读取根节点名称、类型和子节点数量;没有 children 时按空数组处理。
lsblk --json --tree --output NAME,TYPE,SIZE,PKNAME,MOUNTPOINTS \
| jq '.blockdevices[] | {name, type, size, child_count: ((.children // []) | length)}'
# 递归展开设备树;注释说明遍历目的,避免把层级误读成平面列表。
flatten_device() {
local node="$1"
# 先输出当前节点,再递归处理 children,保持父子关系。
jq -c '{name, type, pkname, mountpoints} | .'
上面的递归函数只展示处理思路:真实脚本还应决定如何接收完整 JSON、如何处理多根节点以及如何记录解析错误。它的关键不是“把输出变成一张表”,而是先保留设备树,再由业务决定是否扁平化。

脚本化时处理 null、空 children 和路径
读取 JSON 时,至少要区分三种情况:字段不存在、字段存在但值为 null、字段是空数组。比如根磁盘的 pkname 常常没有父设备,不能把 null 拼成字符串;没有子设备时也不要把缺失的 children 当作错误。
# 输出设备路径时显式使用 --paths,避免脚本自行拼接 /dev 路径。 lsblk --json --tree --paths --output NAME,PATH,TYPE,PKNAME,MOUNTPOINTS # 只查询指定设备,减少脚本把无关设备混进结果的机会。 lsblk --json --tree --paths --output NAME,PATH,TYPE,PKNAME /dev/sda
如果需要机器读取,JSON 解析器应按类型读取字段,而不是把所有值都当成数字或字符串。尤其是挂载点列表、缺失的子节点和空挂载点,都是正常数据状态。需要稳定接口时,把列清单写进脚本,并为缺列或解析失败保留清楚的错误信息。
空结果和层级缺失怎样判断
如果输出有设备但没有 children,先看命令是否包含 NAME 或 --tree,再检查是否使用了 --list。手册明确提示,列表模式不提供设备关系;把它用于 CSV 风格汇总时可以,但不适合还原父子树。
新接入或刚修改的设备可能还没有被 udev 完整登记。此时可以在具备相应权限的维护脚本里先等待设备事件同步,再重新读取;不要把一次空字段直接解释成设备不存在。权限不足、容器设备可见性和命名空间也可能让结果与宿主机不同。
| 现象 | 优先检查 | 不要直接推出 |
|---|---|---|
| 没有 children | NAME 列、--tree、是否使用 --list | 不能直接推出没有分区 |
| 字段为 null | 字段语义和设备类型 | 不能统一替换成空字符串或 0 |
| 输出为空 | 设备参数、权限、容器可见性和 udev 状态 | 不能直接推出系统没有块设备 |
| size 难以比较 | 是否需要 --bytes | 不能按人类可读单位直接排序 |
为什么 JSON 里没有 children?
通常先检查是否包含 NAME 列或显式使用 --tree,并确认没有切换到 --list。是否真的存在子设备,还要结合当前设备类型和权限判断。
PKNAME 和 children 有什么区别?
children 直接承载 JSON 中的嵌套关系,PKNAME 是节点上的父设备名称字段。脚本需要展示树时优先遍历 children,需要辅助索引时再使用 PKNAME。
怎样让 lsblk 输出适合长期脚本?
使用显式的 --output 列表,按需要加入 --tree、--paths 和 --bytes,并在解析器中保留 null、空数组和缺失字段的区别。
可以把这条经验记成一个固定模板:先列出可用字段,再用 --json --tree --output ... 固定接口,最后递归处理 blockdevices 与 children。这样得到的是可解释的设备层级,而不是依赖某个发行版默认表格的脆弱文本。
-
501 收藏
-
501 收藏
-
501 收藏
-
501 收藏
-
501 收藏
-
144 收藏
-
121 收藏
-
272 收藏
-
228 收藏
-
136 收藏
-
442 收藏
-
279 收藏
-
434 收藏
-
465 收藏
-
文章 · linux | 1小时前 | 服务管理 · Linux systemd systemd.socket ListenStream Accept socket activation systemd.service376 收藏
-
123 收藏
-
194 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 立即学习 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 立即学习 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 立即学习 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 立即学习 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 立即学习 485次学习