blkid 命令详解与参数实测(Ubuntu 22.04)
blkid 命令逐参数实测详解:全量识别、-o full/value/list 三种输出、-s 字段过滤、UUID 挂载闭环,以及设备复用后的缓存旧值与 -c/-p 穿透、退出码语义,附 UUID/LABEL/PARTUUID/PARTLABEL 四标识对比,全部命令与回显在 Ubuntu 22.04(util-linux 2.37.2)实测通过。
blkid 命令详解与参数实测(Ubuntu 22.04)
目标:全面掌握 blkid 命令——无参数全量识别、
-o full/value/list三种输出形态、-s字段过滤、用取到的 UUID 直接挂载闭环,以及设备复用后的缓存旧值现象与-c/-p穿透、退出码语义,全部命令与回显已在 Ubuntu 22.04(util-linux 2.37.2)实测通过。
一、环境信息
- 操作系统:Ubuntu 22.04.5 LTS(x86_64)
- 内核版本:6.8.0-138-generic(
uname -r实测) - blkid 版本:util-linux 2.37.2(
blkid --version实测) - 测试介质:
/root/demo/img/ext4.img(dd 创建的 64 MiB 映像)→ losetup 关联/dev/loop17→ mkfs.ext4 格式化 → 挂载/mnt/ext4-demo - 环境特征:系统存在 17 个回环设备与一块 800G 磁盘(sda1/sda2/sda3 三个分区),blkid 能同时读到 loop 设备上的 squashfs 与磁盘上的 ext4/vfat
二、命令概览
2.1 语法与实测环境准备
blkid 的核心语法:blkid [<dev> ...](探测并打印设备上的文件系统标识)、blkid -o <format>(指定输出格式)、blkid -s <tag>(只显示指定标签)。准备一块格式化好的 ext4 测试盘:
💡 技术拓展:"识别设备上是什么文件系统"有几种方式,取值口径横向对比——
工具 原理/职责 适用场景 blkid 低层探测 + 结果缓存,输出 UUID/TYPE 全套标签 取 UUID 写 fstab、脚本取值 lsblk -f 挂在拓扑树里顺带显示 FSTYPE/UUID 浏览设备时一眼带过 df -T 只对已挂载文件系统显示类型 关心挂载后的类型 file -s 直接读超级块做魔术数识别 无 blkid 环境的兜底探测 本文主角是 blkid:探测最专一、输出最结构化(
-o/-s可裁剪);缓存机制(-c/-p)是它的独有坑点,见 3.8 实测。
$ mkdir -p /root/demo/img
$ dd if=/dev/zero of=/root/demo/img/ext4.img bs=1M count=64
64+0 records in
64+0 records out
67108864 bytes (67 MB, 64 MiB) copied, 0.0421241 s, 1.6 GB/s
$ losetup -f --show /root/demo/img/ext4.img
/dev/loop17
$ mkfs.ext4 -F /dev/loop17
mke2fs 1.46.5 (30-Dec-2021)
Discarding device blocks: 0/16384 done
Creating filesystem with 16384 4k blocks and 16384 inodes
Allocating group tables: 0/1 done
Writing inode tables: 0/1 done
Creating journal (1024 blocks): done
Writing superblocks and filesystem accounting information: 0/1 done
$ mkdir -p /mnt/ext4-demo
$ mount /dev/loop17 /mnt/ext4-demo
2.2 --help 全量回显
blkid --help 输出全部参数(实测原样保留):
Usage:
blkid --label <label> | --uuid <uuid>
blkid [--cache-file <file>] [-ghlLv] [--output <format>] [--match-tag <tag>]
[--match-token <token>] [<dev> ...]
blkid -p [--match-tag <tag>] [--offset <offset>] [--size <size>]
[--output <format>] <dev> ...
blkid -i [--match-tag <tag>] [--output <format>] <dev> ...
Options:
-c, --cache-file <file> read from <file> instead of reading from the default
cache file (-c /dev/null means no cache)
-d, --no-encoding don't encode non-printing characters
-g, --garbage-collect garbage collect the blkid cache
-o, --output <format> output format; can be one of:
value, device, export or full; (default: full)
-k, --list-filesystems list all known filesystems/RAIDs and exit
-s, --match-tag <tag> show specified tag(s) (default show all tags)
-t, --match-token <token> find device with a specific token (NAME=value pair)
-l, --list-one look up only first device with token specified by -t
-L, --label <label> convert LABEL to device name
-U, --uuid <uuid> convert UUID to device name
Low-level probing options:
-p, --probe low-level superblocks probing (bypass cache)
-i, --info gather information about I/O limits
-H, --hint <value> set hint for probing function
-S, --size <size> overwrite device size
-O, --offset <offset> probe at the given offset
-u, --usages <list> filter by "usage" (e.g. -u filesystem,raid)
-n, --match-types <list> filter by filesystem type (e.g. -n vfat,ext3)
-D, --no-part-details don't print info from partition table
-h, --help display this help
-V, --version display version
Arguments:
<size> and <offset> arguments may be followed by the suffixes for
GiB, TiB, PiB, EiB, ZiB, and YiB (the "iB" is optional)
<dev> specify device(s) to probe (default: all devices)
For more details see blkid(8).
💡 说明:两处必须划重点——
-o支持 value/device/export/full 四种格式(默认 full);-p明确标注 bypass cache(绕过缓存直接探测),3.8 会实测它和缓存的区别。
2.3 版本确认
$ blkid --version
blkid from util-linux 2.37.2 (libblkid 2.37.2, 16-Aug-2021)
三、参数逐项实测
3.1 无参数:识别全部块设备
不带参数,blkid 扫描全部块设备并打印每个设备上的文件系统标识(输出节选(实测),中间 squashfs loop 行省略):
$ blkid
/dev/loop17: UUID="d3e329f0-64cb-4cd5-9fe9-19cc71b31e6d" BLOCK_SIZE="4096" TYPE="ext4"
/dev/loop1: TYPE="squashfs"
/dev/loop8: TYPE="squashfs"
/dev/sda2: UUID="7C90-153C" BLOCK_SIZE="512" TYPE="vfat" PARTLABEL="EFI System Partition" PARTUUID="6ca3987f-ad64-4985-8c36-4385be6dba05"
/dev/sda3: UUID="43e68207-7df4-4f66-933a-8a595cdde8c8" BLOCK_SIZE="4096" TYPE="ext4" PARTUUID="5045d491-ea71-40a0-9321-3079ec42852e"
/dev/sda1: PARTUUID="97472a4a-bf62-4520-9986-29ebca802f15"
三行真实磁盘分区信息量很大:sda2 是 EFI 分区(vfat,卷 UUID 形如 7C90-153C,带 PARTLABEL 与 PARTUUID);sda3 是数据分区(ext4);sda1 没有文件系统,所以只有分区表给的 PARTUUID。这正是文件系统 UUID 与分区 UUID 分层的直观体现。
3.2 指定设备查询
参数给设备路径,只探测该设备:
$ blkid /dev/loop17
/dev/loop17: UUID="d3e329f0-64cb-4cd5-9fe9-19cc71b31e6d" BLOCK_SIZE="4096" TYPE="ext4"
3.3 -o full:完整键值输出
-o full 是默认格式,输出与无参数指定设备时一致(帮助原文 default: full):
$ blkid -o full /dev/loop17
/dev/loop17: UUID="d3e329f0-64cb-4cd5-9fe9-19cc71b31e6d" BLOCK_SIZE="4096" TYPE="ext4"
3.4 -o value -s:脚本取值
-o value 只输出值本身,-s 指定要哪个标签——两者配合是脚本取值的标准姿势:
$ blkid -o value -s UUID /dev/loop17
d3e329f0-64cb-4cd5-9fe9-19cc71b31e6d
$ blkid -o value -s TYPE /dev/loop17
ext4
输出干净无键名、无引号,可直接 U=$(blkid -o value -s UUID /dev/loop17) 赋值给变量。
3.5 -s:字段过滤(保留键值形式)
-s 单独使用时保留 设备: KEY="value" 形式,只挑指定标签;可叠加多个 -s:
$ blkid -s UUID /dev/loop17
/dev/loop17: UUID="d3e329f0-64cb-4cd5-9fe9-19cc71b31e6d"
$ blkid -s TYPE /dev/loop17
/dev/loop17: TYPE="ext4"
$ blkid -s UUID -s TYPE /dev/loop17
/dev/loop17: UUID="d3e329f0-64cb-4cd5-9fe9-19cc71b31e6d" TYPE="ext4"
3.6 -o list:友好列表
-o list 换成人类友好表格,多出挂载点列(输出节选(实测),squashfs 行省略;长设备名换行显示为原样):
$ blkid -o list
device fs_type label mount point UUID
/dev/loop17
ext4 /mnt/ext4-demo d3e329f0-64cb-4cd5-9fe9-19cc71b31e6d
/dev/sda2 vfat (in use) 7C90-153C
/dev/sda3 ext4 /etc/hostname 43e68207-7df4-4f66-933a-8a595cdde8c8
/dev/sda1 (not mounted)
挂载点列直接回答"这个分区用没用":/mnt/ext4-demo 显示具体路径,busy 的系统分区显示 (in use),未挂载且无文件系统的 sda1 显示 (not mounted)。
3.7 用取到的 UUID 直接挂载
闭环验证:3.4 取到的 UUID 交给 mount,按 UUID 挂载(见 mount 篇 3.2 同款用法):
$ mkdir -p /mnt/by-uuid
$ mount UUID=d3e329f0-64cb-4cd5-9fe9-19cc71b31e6d /mnt/by-uuid
$ findmnt /mnt/by-uuid
TARGET SOURCE FSTYPE OPTIONS
/mnt/by-uuid /dev/loop17 ext4 rw,relatime
$ umount /mnt/by-uuid
findmnt 的 SOURCE 解析回 /dev/loop17——UUID 是定位方式,内核仍按设备记账。
3.8 未格式化设备、缓存旧值与不存在设备
这是 blkid 最值得实测的一个坑。把 /dev/loop17 从 ext4 映像上摘下,换成一张 8 MiB 的空白映像(未格式化),再看 blkid 报什么:
$ umount /mnt/ext4-demo
$ losetup -d /dev/loop17
$ dd if=/dev/zero of=/root/demo/img/raw.img bs=1M count=8
8+0 records in
8+0 records out
8388608 bytes (8.4 MB, 8.0 MiB) copied, 0.0393076 s, 213 MB/s
$ losetup -f --show /root/demo/img/raw.img
/dev/loop17
$ blkid /dev/loop17; echo exit=$?
/dev/loop17: UUID="d3e329f0-64cb-4cd5-9fe9-19cc71b31e6d" BLOCK_SIZE="4096" TYPE="ext4"
exit=0
$ blkid -o value -s UUID /dev/loop17; echo exit=$?
d3e329f0-64cb-4cd5-9fe9-19cc71b31e6d
exit=0
注意:设备上已经是空白映像,blkid 却仍报出 ext4 和 UUID——这正是 2.1 格式化时的旧值,来自 blkid 的结果缓存(Ubuntu 上位于 /run/blkid/blkid.tab):同一设备节点被复用而缓存未失效时,默认模式会返回缓存内容而非真实探测结果。用 -c /dev/null(禁用缓存)或 -p(低层探测,绕过缓存)穿透验证:
$ blkid -c /dev/null /dev/loop17; echo exit=$?
exit=2
$ blkid -p /dev/loop17; echo exit=$?
exit=2
$ blkid /dev/nonexistent; echo exit=$?
exit=2
$ losetup -d /dev/loop17
穿透后空设备无输出、退出码 2;不存在的设备同样空输出、退出码 2。
💡 说明:退出码语义实测为 0=有结果、2=无结果或设备不存在。换映像/重格式化之后,如果 blkid 的输出"不更新",先怀疑缓存,用
blkid -p /dev/loop17或blkid -c /dev/null拿真实值。
四、实战示例
实战一:写 fstab 前取 UUID
fstab 推荐用 UUID 定位设备,取值到挂载一气呵成(回显见 3.4 与 3.7):
blkid -o value -s UUID /dev/sda3 # 取 UUID
mount UUID=43e68207-7df4-4f66-933a-8a595cdde8c8 /mnt/data # 先手动挂载验证
# 确认无误后写入 /etc/fstab:UUID=43e68207-7df4-4f66-933a-8a595cdde8c8 /mnt/data ext4 defaults 0 2
mount -a # 验证 fstab 语法(见 mount 篇 3.7)
实战二:脚本判断设备是否已格式化
利用 -o value -s TYPE 的输出与退出码做条件判断:
T=$(blkid -o value -s TYPE /dev/loop17) # 无文件系统时 T 为空、退出码 2
[ -z "$T" ] && mkfs.ext4 -F /dev/loop17 # 空则格式化
实测依据见 3.8:空白设备上该命令无输出、exit=2。
五、注意事项与常见问题
Q1:blkid 报了一个"已经不存在"的 UUID?
这是缓存(3.8 实测复现):blkid 默认模式读缓存文件(/run/blkid/blkid.tab),设备节点被复用而缓存未失效时返回旧值。用 blkid -p /dev/loop17(低层探测绕缓存)或 blkid -c /dev/null /dev/loop17(本次禁用缓存)取真实值。
Q2:退出码有哪些? 实测:0=探测到结果;2=设备无文件系统或设备不存在(无输出)。脚本里用退出码判断比解析输出更稳。
Q3:取 UUID 用 blkid 还是 lsblk -f?
blkid 直接读设备超级块(可绕缓存),结果可靠;lsblk -f 的 UUID 列依赖 udev/libblkid 探测,在本环境实测为空(见 lsblk 篇 3.2)。取 UUID 写 fstab 一律推荐 blkid -o value -s UUID。
Q4:UUID、LABEL、PARTUUID、PARTLABEL 有什么区别? 见下表。文件系统层的 UUID/LABEL 随格式化产生,分区层的 PARTUUID/PARTLABEL 来自分区表——sda1 没有文件系统却仍有 PARTUUID(3.1 实测),就是分层的最直接证据。
四种设备标识对比
| 标识 | 所属层级 | 来源 | 特点 | 挂载用法 |
|---|---|---|---|---|
| UUID | 文件系统 | mkfs 时生成,重格式化才变 | 全局唯一,最常用 | mount UUID=<uuid> |
| LABEL | 文件系统 | 格式化时指定,可后期修改 | 可读性好,但有重名风险 | mount LABEL=<label> |
| PARTUUID | 分区 | GPT 分区表生成 | 与文件系统无关,改分区表才变 | mount PARTUUID=<uuid> |
| PARTLABEL | 分区 | GPT 分区名 | 默认如 "EFI System Partition" | mount PARTLABEL=<label> |
六、参考链接
- blkid(8) 手册:https://man7.org/linux/man-pages/man8/blkid.8.html
- libblkid 上游文档:https://github.com/util-linux/util-linux/tree/master/libblkid
- fstab(5) 手册:https://man7.org/linux/man-pages/man5/fstab.5.html
- util-linux 上游仓库:https://github.com/util-linux/util-linux