2. 磁盘设备识别与命名

在 RHEL 存储与文件系统管理中,一切操作都从“找到正确的块设备”开始。Linux 把块设备抽象为 /dev 下的设备节点,但不同总线、不同驱动、不同虚拟化平台下,内核给出的命名规则并不相同。理解 /dev/sdX、/dev/nvmeXnY、/dev/vdX 三类命名的来源,是避免“误格式化系统盘”“挂错盘”等事故的第一道防线。

三类命名规则的本质差异

/dev/sdX 来自 SCSI 子系统,包括 SATA、SAS、USB 存储以及多数硬件 RAID 逻辑盘。命名格式为 sd + 字母 + 可选分区号,例如 /dev/sda、/dev/sdb、/dev/sda1。字母按内核探测到设备的先后顺序分配,顺序本身不稳定:新增一块盘、更换插槽、调整 BIOS 启动顺序,都可能导致 sda 与 sdb 互换。

/dev/nvmeXnY 来自 NVMe 驱动,格式为 nvme + 控制器编号 + n + 命名空间编号,例如 /dev/nvme0n1 表示第 0 个控制器的第 1 个命名空间。分区在其后追加 p 与分区号,如 /dev/nvme0n1p1。注意 NVMe 分区用 p 分隔,而 sd/vd 直接拼接数字,这是最容易写错的地方。

/dev/vdX 来自 virtio-blk 驱动,常见于 KVM/QEMU 虚拟机,格式为 vd + 字母,如 /dev/vda、/dev/vdb。它同样按探测顺序分配字母,因此也存在顺序漂移问题。三类命名都遵循“设备节点 + 分区后缀”的结构,但前缀和分区分隔符不同,脚本中若硬编码 /dev/sda1,迁移到 NVMe 机器上必然失败。

三类块设备命名规则与信息采集链路 SCSI / SATA / SAS sd 驱动 NVMe 控制器 nvme 驱动 virtio-blk vd 驱动 /dev/sdX sda, sdb, sda1 分区直接拼数字 /dev/nvmeXnY nvme0n1, nvme0n1p1 分区用 p 分隔 /dev/vdX vda, vdb, vda1 分区直接拼数字 lsblk 树形结构 / 挂载点 blkid UUID / TYPE / LABEL udevadm 属性 / 链路 / 事件 持久化命名:/dev/disk/by-uuid/ · /dev/disk/by-label/ · /dev/disk/by-id/ · /dev/disk/by-path/ fstab 与脚本应引用持久化路径,而非 sdX / vdX 顺序名

lsblk:先看清拓扑再动手

lsblk 是最先应该执行的命令,它以树形展示块设备、分区、挂载点和容量。默认输出不含文件系统类型,加上 -f 可显示 FSTYPE、UUID、LABEL、MOUNTPOINT:

[root@rhel ~]# lsblk -f
NAME        FSTYPE LABEL UUID                                 MOUNTPOINT
sda
├─sda1      xfs    boot  3f2a1c8e-...                         /boot
└─sda2      LVM2_member   8b7d4e21-...
  ├─rhel-root xfs         a1c9f0d3-...                         /
  └─rhel-swap swap        5e2b7a44-...                         [SWAP]
nvme0n1
└─nvme0n1p1 xfs    data  9d4c1b77-...                         /data
vda
└─vda1      xfs           c7e3a912-...                         /

从输出可以读出关键信息:sda2 是 LVM 物理卷,其上是 rhel-root 逻辑卷;nvme0n1p1 是独立 XFS 分区;vda1 是虚拟机系统盘。若只想看某块盘,可用 lsblk /dev/nvme0n1;若需要脚本解析,用 lsblk -P -o NAME,SIZE,TYPE,MOUNTPOINT 输出 KEY="value" 格式更稳妥。

blkid:拿到 UUID 与文件系统类型

blkid 直接读取块设备上的超级块信息,输出 UUID、TYPE、LABEL、PARTUUID。它需要 root 权限才能读取全部设备:

[root@rhel ~]# blkid /dev/nvme0n1p1
/dev/nvme0n1p1: UUID="9d4c1b77-2e5a-4f01-9c3d-6a8b1e2f7d40" TYPE="xfs" LABEL="data"

[root@rhel ~]# blkid -s UUID -o value /dev/nvme0n1p1
9d4c1b77-2e5a-4f01-9c3d-6a8b1e2f7d40

UUID 在文件系统创建时生成,只要不重新格式化就保持不变,因此是 fstab 中最可靠的引用方式。LABEL 可人为设置(xfs_admin -L 或 e2label),便于人类识别,但需保证唯一性。注意:blkid 对未格式化的裸设备不会输出 UUID,此时应先确认是否真的要创建文件系统。

udevadm:追溯设备属性与稳定链路

udevadm info 用于查询 udev 数据库中某设备的属性,是排查“为什么这块盘没有生成 by-id 链接”的关键工具:

[root@rhel ~]# udevadm info --query=all --name=/dev/nvme0n1p1
P: /devices/pci0000:00/0000:00:04.0/nvme/nvme0/nvme0n1/nvme0n1p1
N: nvme0n1p1
S: disk/by-uuid/9d4c1b77-2e5a-4f01-9c3d-6a8b1e2f7d40
S: disk/by-partuuid/3a7f2c10-01
E: ID_FS_TYPE=xfs
E: ID_FS_UUID=9d4c1b77-2e5a-4f01-9c3d-6a8b1e2f7d40
E: ID_SERIAL=INTEL_SSDPEKKW256G8_BTNH12345678

其中 P 是设备在 sysfs 中的路径,N 是内核设备名,S 是 udev 创建的符号链接,E 是环境属性。ID_SERIAL 来自硬件序列号,是 by-id 链接的命名依据。若某块盘没有 by-id 链接,通常说明该设备未上报稳定序列号,此时应改用 by-path 或 UUID。

另一个常用命令是 udevadm monitor --udev --property,在插拔设备时实时打印 udev 事件与属性,适合验证新盘是否被正确识别。而 udevadm trigger 可强制重新触发规则,用于修复链接缺失。

持久化命名实践

内核顺序名(sda/vda)不可靠,持久化命名目录位于 /dev/disk/ 下,常见四类:

  • by-uuid/:按文件系统 UUID,最稳定,推荐用于 fstab。
  • by-label/:按文件系统标签,可读性好,需保证唯一。
  • by-id/:按设备序列号或 WWN,适合整盘引用(如 LVM、裸设备)。
  • by-path/:按物理路径(PCI 插槽),适合固定硬件的服务器。

实际写 fstab 时,应使用 UUID 而非设备名。例如把 /dev/nvme0n1p1 挂到 /data:

# 错误写法:顺序变化后可能挂错盘
/dev/nvme0n1p1  /data  xfs  defaults  0 0

# 正确写法:使用 UUID
UUID=9d4c1b77-2e5a-4f01-9c3d-6a8b1e2f7d40  /data  xfs  defaults  0 0

验证方式:执行 mount -a 无报错,再用 findmnt /data 确认挂载来源为 /dev/disk/by-uuid/...。若需在脚本中引用整盘,可用 /dev/disk/by-id/ 下的链接,例如 /dev/disk/by-id/nvme-INTEL_SSDPEKKW256G8_BTNH12345678。

判断依据速记:lsblk -f 看拓扑与挂载,blkid 取 UUID/TYPE,udevadm info 查属性与链接来源;fstab 一律用 UUID 或 LABEL,脚本引用整盘用 by-id,固定槽位用 by-path。
对未确认的盘执行 mkfs 或 wipefs 前,务必先用 lsblk -f 与 blkid 双重确认设备名、容量、现有文件系统和挂载点,避免误伤系统盘或已有数据盘。