持久块设备命名
本文介绍如何为您的块设备使用持久化名称。这得益于udev的引入,并且相对于基于总线的命名方式具有一些优势。如果您的机器有多个驱动器共享一个命名方案,则添加其相应设备节点的顺序是任意的。这可能会导致块设备名称(例如 /dev/sda
和 /dev/sdb
,/dev/nvme0n1
和 /dev/nvme1n1
,/dev/mmcblk0
和 /dev/mmcblk1
)在每次启动时切换,最终导致系统无法启动、内核崩溃或块设备消失。持久命名解决了这些问题。
- 持久命名具有本文范围之外的限制。例如,虽然 mkinitcpio 可能支持一种方法,但 systemd 可能会对其在启动期间可以处理的命名施加自己的限制(例如 FS#42884)。
- 本文与 LVM 逻辑卷无关,因为
/dev/VolumeGroupName/LogicalVolumeName
设备路径是持久的。
持久命名方法
有不同的方案提供由 udev 管理的持久命名。
60-persistent-storage.rules
默认提供四种:by-label、by-uuid、by-id 和 by-path。对于具有 GUID 分区表 (GPT) 的磁盘,还有两种额外的方案——by-partlabel 和 by-partuuid。99-systemd.rules
为与 GPT 分区自动挂载 兼容的设置提供 gpt-auto。
/dev/disk/
中的目录是动态创建和销毁的,具体取决于其中是否有设备。
以下部分描述了不同的持久命名方法是什么以及如何使用它们。
可以使用 lsblk 命令以图形方式查看第一个持久方案
$ lsblk -f
NAME FSTYPE LABEL UUID MOUNTPOINT sda ├─sda1 vfat CBB6-24F2 /boot ├─sda2 ext4 Arch Linux 0a3407de-014b-458b-b5c1-848e92a327a3 / ├─sda3 ext4 Data b411dc99-f0a0-4c87-9e05-184977be8539 /home └─sda4 swap f9fe0b69-a280-415d-a03a-a32752370dee [SWAP] mmcblk0 └─mmcblk0p1 vfat F4CA-5D75
对于使用 GPT 的用户,请改用 blkid
命令。后者对于脚本来说更方便,但更难阅读。
# blkid
/dev/sda1: UUID="CBB6-24F2" TYPE="vfat" PARTLABEL="EFI system partition" PARTUUID="d0d0d110-0a71-4ed6-936a-304969ea36af" /dev/sda2: LABEL="Arch Linux" UUID="0a3407de-014b-458b-b5c1-848e92a327a3" TYPE="ext4" PARTLABEL="GNU/Linux" PARTUUID="98a81274-10f7-40db-872a-03df048df366" /dev/sda3: LABEL="Data" UUID="b411dc99-f0a0-4c87-9e05-184977be8539" TYPE="ext4" PARTLABEL="Home" PARTUUID="7280201c-fc5d-40f2-a9b2-466611d3d49e" /dev/sda4: UUID="f9fe0b69-a280-415d-a03a-a32752370dee" TYPE="swap" PARTLABEL="Swap" PARTUUID="039b6c1c-7553-4455-9537-1befbc9fbc5b" /dev/mmcblk0: PTUUID="0003e1e5" PTTYPE="dos" /dev/mmcblk0p1: UUID="F4CA-5D75" TYPE="vfat" PARTUUID="0003e1e5-01"
by-label
几乎每个文件系统类型都可以有一个标签。所有具有标签的卷都列在 /dev/disk/by-label
目录中。
$ ls -l /dev/disk/by-label/
total 0 lrwxrwxrwx 1 root root 10 May 27 23:31 Data -> ../../sda3 lrwxrwxrwx 1 root root 10 May 27 23:31 Arch\x20Linux -> ../../sda2
大多数文件系统都支持在文件系统创建时设置标签,请参阅相关 mkfs.*
工具的 手册页。对于某些文件系统,也可以更改标签。以下是更改常见文件系统标签的一些方法
- btrfs
btrfs filesystem label /dev/XXX "新标签"
(如果设备已挂载,请使用设备的挂载点)使用 btrfs-progs- crypto_LUKS (仅限 LUKS2)
cryptsetup config --label="新标签" /dev/XXX
使用 cryptsetup- exfat
tune.exfat -L "新标签" /dev/XXX
使用 exfatprogsexfatlabel /dev/XXX "新标签"
使用 exfatprogs 或 exfat-utils- ext2/3/4
e2label /dev/XXX "新标签"
使用 e2fsprogs- fat/vfat
fatlabel /dev/XXX "新标签"
使用 dosfstoolsmlabel -i /dev/XXX ::"新标签"
使用 mtools- jfs
jfs_tune -L "新标签" /dev/XXX
使用 jfsutils- ntfs
ntfslabel /dev/XXX "新标签"
使用 ntfs-3g- reiserfs
reiserfstune -l "新标签" /dev/XXX
使用 reiserfsprogsAUR- swap
swaplabel -L "新标签" /dev/XXX
使用 util-linux- udf
udflabel /dev/XXX "新标签"
使用 udftools- xfs
xfs_admin -L "新标签" /dev/XXX
(如果设备已挂载,请使用设备的挂载点)使用 xfsprogs
可以使用 lsblk 获取设备的标签
$ lsblk -dno LABEL /dev/sda2
Arch Linux
或使用 blkid
# blkid -s LABEL -o value /dev/sda2
Arch Linux
- 标签必须是明确的,以防止任何可能的冲突。
- 标签最多可以包含 16 个字符。
- 由于标签是文件系统的属性,因此不适合持久地寻址单个 RAID 设备。
- 当使用 dm-crypt 加密容器时,容器内部文件系统的标签在容器锁定/加密时不可用。
by-uuid
UUID 是一种为每个文件系统提供唯一标识符的机制。这些标识符由文件系统实用程序(例如 mkfs.*
)在设备格式化时生成,并且设计为不太可能发生冲突。所有 GNU/Linux 文件系统(包括原始加密设备的交换分区和 LUKS 标头)都支持 UUID。FAT、exFAT 和 NTFS 文件系统不支持 UUID,但仍以较短的 UID(唯一标识符)列在 /dev/disk/by-uuid/
中
$ ls -l /dev/disk/by-uuid/
total 0 lrwxrwxrwx 1 root root 10 May 27 23:31 0a3407de-014b-458b-b5c1-848e92a327a3 -> ../../sda2 lrwxrwxrwx 1 root root 10 May 27 23:31 b411dc99-f0a0-4c87-9e05-184977be8539 -> ../../sda3 lrwxrwxrwx 1 root root 10 May 27 23:31 CBB6-24F2 -> ../../sda1 lrwxrwxrwx 1 root root 10 May 27 23:31 f9fe0b69-a280-415d-a03a-a32752370dee -> ../../sda4 lrwxrwxrwx 1 root root 10 May 27 23:31 F4CA-5D75 -> ../../mmcblk0p1
可以使用 lsblk 获取设备的 UUID
$ lsblk -dno UUID /dev/sda1
CBB6-24F2
或使用 blkid
# blkid -s UUID -o value /dev/sda1
CBB6-24F2
使用 UUID 方法的优点是,与标签相比,名称冲突发生的可能性要小得多。此外,它在文件系统创建时自动生成。例如,即使设备插入到另一个系统(可能具有相同标签的设备),它也将保持唯一。
缺点是 UUID 使长代码行难以阅读,并且会破坏许多配置文件(例如 fstab 或 crypttab)中的格式。此外,每次重新格式化卷时,都会生成新的 UUID,并且必须手动调整配置文件。
by-id 和 by-path
by-id
根据硬件序列号创建唯一名称,by-path
根据最短物理路径(根据 sysfs)。两者都包含指示它们所属子系统的字符串(即 by-path
的 pci-
和 by-id
的 ata-
),因此它们链接到控制设备的硬件。这意味着不同级别的持久性:当设备插入控制器的不同端口时,by-path
已经会发生变化;当设备插入到受另一个子系统约束的硬件控制器的端口时,by-id
会发生变化。[1] 因此,两者都不适合实现对硬件更改具有容忍度的持久命名。
但是,两者都提供了重要的信息,可以在大型硬件基础设施中找到特定设备。例如,如果您不手动分配持久标签(by-label
或 by-partlabel
)并保留硬件端口使用情况的目录,则可以使用 by-id
和 by-path
来查找特定设备。[2] [3]
by-id
和by-path
链接只能被认为是磁盘的持久链接,而不是分区。分区将通过它们在分区表中的编号来引用,如果重新排序分区,则该编号可能会更改。- 如果从系统中添加或删除 PCIe 设备,或者系统固件 未确定性地枚举它们,则 NVMe 设备的
/dev/disk/by-path/pci-*
路径可能会更改。 - 没有命名空间标识符 (NSID) 的 NVMe 设备
by-id
链接已过时。请改用硬件序列号后带有命名空间标识符的链接(例如,第一个命名空间的_1
或第一个命名空间上第一个分区的_1-part1
)。
$ ls -l /dev/disk/by-id/
total 0 lrwxrwxrwx 1 root root 10 May 27 23:31 ata-WDC_WD2500BEVT-22ZCT0_WD-WXE908VF0470 -> ../../sda lrwxrwxrwx 1 root root 10 May 27 23:31 ata-WDC_WD2500BEVT-22ZCT0_WD-WXE908VF0470-part1 -> ../../sda1 lrwxrwxrwx 1 root root 10 May 27 23:31 ata-WDC_WD2500BEVT-22ZCT0_WD-WXE908VF0470-part2 -> ../../sda2 lrwxrwxrwx 1 root root 10 May 27 23:31 ata-WDC_WD2500BEVT-22ZCT0_WD-WXE908VF0470-part3 -> ../../sda3 lrwxrwxrwx 1 root root 10 May 27 23:31 ata-WDC_WD2500BEVT-22ZCT0_WD-WXE908VF0470-part4 -> ../../sda4 lrwxrwxrwx 1 root root 10 May 27 23:31 mmc-SD32G_0x0040006d -> ../../mmcblk0 lrwxrwxrwx 1 root root 10 May 27 23:31 mmc-SD32G_0x0040006d-part1 -> ../../mmcblk0p1 lrwxrwxrwx 1 root root 13 May 27 23:31 nvme-Samsung_SSD_970_EVO_Plus_2TB_S4J4NJ0N704064T -> ../../nvme1n1 lrwxrwxrwx 1 root root 15 May 27 23:31 nvme-Samsung_SSD_970_EVO_Plus_2TB_S4J4NJ0N704064T-part1 -> ../../nvme1n1p1 lrwxrwxrwx 1 root root 15 May 27 23:31 nvme-Samsung_SSD_970_EVO_Plus_2TB_S4J4NJ0N704064T-part2 -> ../../nvme1n1p2 lrwxrwxrwx 1 root root 13 May 27 23:31 nvme-Samsung_SSD_970_EVO_Plus_2TB_S4J4NJ0N704064T_1 -> ../../nvme1n1 lrwxrwxrwx 1 root root 15 May 27 23:31 nvme-Samsung_SSD_970_EVO_Plus_2TB_S4J4NJ0N704064T_1-part1 -> ../../nvme1n1p1 lrwxrwxrwx 1 root root 15 May 27 23:31 nvme-Samsung_SSD_970_EVO_Plus_2TB_S4J4NJ0N704064T_1-part2 -> ../../nvme1n1p2 lrwxrwxrwx 1 root root 13 May 27 23:31 nvme-WDS100T1X0E-00AFY0_21455A801268 -> ../../nvme0n1 lrwxrwxrwx 1 root root 15 May 27 23:31 nvme-WDS100T1X0E-00AFY0_21455A801268-part1 -> ../../nvme0n1p1 lrwxrwxrwx 1 root root 15 May 27 23:31 nvme-WDS100T1X0E-00AFY0_21455A801268-part2 -> ../../nvme0n1p2 lrwxrwxrwx 1 root root 13 May 27 23:31 nvme-WDS100T1X0E-00AFY0_21455A801268_1 -> ../../nvme0n1 lrwxrwxrwx 1 root root 15 May 27 23:31 nvme-WDS100T1X0E-00AFY0_21455A801268_1-part1 -> ../../nvme0n1p1 lrwxrwxrwx 1 root root 15 May 27 23:31 nvme-WDS100T1X0E-00AFY0_21455A801268_2-part2 -> ../../nvme0n1p2 lrwxrwxrwx 1 root root 13 May 27 23:31 nvme-eui.002538570142d716 -> ../../nvme1n1 lrwxrwxrwx 1 root root 15 May 27 23:31 nvme-eui.002538570142d716-part1 -> ../../nvme1n1p1 lrwxrwxrwx 1 root root 15 May 27 23:31 nvme-eui.002538570142d716-part2 -> ../../nvme1n1p2 lrwxrwxrwx 1 root root 13 May 27 23:31 nvme-eui.e8238fa6bf530001001b448b4566aa1a -> ../../nvme0n1 lrwxrwxrwx 1 root root 15 May 27 23:31 nvme-eui.e8238fa6bf530001001b448b4566aa1a-part1 -> ../../nvme0n1p1 lrwxrwxrwx 1 root root 15 May 27 23:31 nvme-eui.e8238fa6bf530001001b448b4566aa1a-part2 -> ../../nvme0n1p2 lrwxrwxrwx 1 root root 10 May 27 23:31 wwn-0x60015ee0000b237f -> ../../sda lrwxrwxrwx 1 root root 10 May 27 23:31 wwn-0x60015ee0000b237f-part1 -> ../../sda1 lrwxrwxrwx 1 root root 10 May 27 23:31 wwn-0x60015ee0000b237f-part2 -> ../../sda2 lrwxrwxrwx 1 root root 10 May 27 23:31 wwn-0x60015ee0000b237f-part3 -> ../../sda3 lrwxrwxrwx 1 root root 10 May 27 23:31 wwn-0x60015ee0000b237f-part4 -> ../../sda4
$ ls -l /dev/disk/by-path/
total 0 lrwxrwxrwx 1 root root 10 May 27 23:31 pci-0000:00:1f.2-ata-1 -> ../../sda lrwxrwxrwx 1 root root 10 May 27 23:31 pci-0000:00:1f.2-ata-1-part1 -> ../../sda1 lrwxrwxrwx 1 root root 10 May 27 23:31 pci-0000:00:1f.2-ata-1-part2 -> ../../sda2 lrwxrwxrwx 1 root root 10 May 27 23:31 pci-0000:00:1f.2-ata-1-part3 -> ../../sda3 lrwxrwxrwx 1 root root 10 May 27 23:31 pci-0000:00:1f.2-ata-1-part4 -> ../../sda4 lrwxrwxrwx 1 root root 13 May 27 23:31 pci-0000:01:00.0-nvme-1 -> ../../nvme0n1 lrwxrwxrwx 1 root root 15 May 27 23:31 pci-0000:01:00.0-nvme-1-part1 -> ../../nvme0n1p1 lrwxrwxrwx 1 root root 15 May 27 23:31 pci-0000:01:00.0-nvme-1-part2 -> ../../nvme0n1p2 lrwxrwxrwx 1 root root 13 May 27 23:31 pci-0000:04:00.0-nvme-1 -> ../../nvme1n1 lrwxrwxrwx 1 root root 15 May 27 23:31 pci-0000:04:00.0-nvme-1-part1 -> ../../nvme1n1p1 lrwxrwxrwx 1 root root 15 May 27 23:31 pci-0000:04:00.0-nvme-1-part2 -> ../../nvme1n1p2 lrwxrwxrwx 1 root root 10 May 27 23:31 pci-0000:07:00.0-platform-rtsx_pci_sdmmc.0 -> ../../mmcblk0 lrwxrwxrwx 1 root root 10 May 27 23:31 pci-0000:07:00.0-platform-rtsx_pci_sdmmc.0-part1 -> ../../mmcblk0p1
全球通用名称
by-id
还创建支持全球通用名称 (WWN) 的存储设备的链接。与其他 by-id
链接不同,WWN 是完全持久的,并且不会根据使用的子系统而更改。
SATA 和 SAS 设备具有 wwn-
前缀,而 NVMe 设备使用 不同的 WWN 格式,并以 nvme-eui.
为前缀。[4]
$ ls -l /dev/disk/by-id/{wwn-,nvme-eui.}*
lrwxrwxrwx 1 root root 13 May 27 23:31 nvme-eui.002538570142d716 -> ../../nvme1n1 lrwxrwxrwx 1 root root 15 May 27 23:31 nvme-eui.002538570142d716-part1 -> ../../nvme1n1p1 lrwxrwxrwx 1 root root 15 May 27 23:31 nvme-eui.002538570142d716-part2 -> ../../nvme1n1p2 lrwxrwxrwx 1 root root 13 May 27 23:31 nvme-eui.e8238fa6bf530001001b448b4566aa1a -> ../../nvme0n1 lrwxrwxrwx 1 root root 15 May 27 23:31 nvme-eui.e8238fa6bf530001001b448b4566aa1a-part1 -> ../../nvme0n1p1 lrwxrwxrwx 1 root root 15 May 27 23:31 nvme-eui.e8238fa6bf530001001b448b4566aa1a-part2 -> ../../nvme0n1p2 lrwxrwxrwx 1 root root 10 May 27 23:31 wwn-0x60015ee0000b237f -> ../../sda lrwxrwxrwx 1 root root 10 May 27 23:31 wwn-0x60015ee0000b237f-part1 -> ../../sda1 lrwxrwxrwx 1 root root 10 May 27 23:31 wwn-0x60015ee0000b237f-part2 -> ../../sda2 lrwxrwxrwx 1 root root 10 May 27 23:31 wwn-0x60015ee0000b237f-part3 -> ../../sda3 lrwxrwxrwx 1 root root 10 May 27 23:31 wwn-0x60015ee0000b237f-part4 -> ../../sda4
by-partlabel
GPT 分区标签可以在 GPT 磁盘的分区条目的标头中定义。
此方法与 文件系统标签 非常相似,不同之处在于,如果更改分区上的文件系统,分区标签不会受到影响。
所有具有分区标签的分区都列在 /dev/disk/by-partlabel
目录中。
$ ls -l /dev/disk/by-partlabel/
total 0 lrwxrwxrwx 1 root root 10 May 27 23:31 EFI\x20system\x20partition -> ../../sda1 lrwxrwxrwx 1 root root 10 May 27 23:31 GNU\x2fLinux -> ../../sda2 lrwxrwxrwx 1 root root 10 May 27 23:31 Home -> ../../sda3 lrwxrwxrwx 1 root root 10 May 27 23:31 Swap -> ../../sda4
可以使用 lsblk 获取设备的分区标签
$ lsblk -dno PARTLABEL /dev/sda1
EFI system partition
或使用 blkid
# blkid -s PARTLABEL -o value /dev/sda1
EFI system partition
by-partuuid
与 GPT 分区标签 类似,GPT 分区 UUID 在 GPT 磁盘的分区条目中定义。
MBR 不支持分区 UUID,但 Linux[5] 和使用 libblkid[6] 的软件(例如 udev[7])能够为 MBR 分区生成伪 PARTUUID。格式为 SSSSSSSS-PP
,其中 SSSSSSSS
是零填充的 32 位 MBR 磁盘签名,PP
是十六进制形式的零填充分区号。与 GPT 分区的常规 PARTUUID 不同,如果分区号更改,MBR 的伪 PARTUUID 可能会更改。
动态目录与其他方法类似,并且像 文件系统 UUID 一样,使用 UUID 比标签更受青睐。
$ ls -l /dev/disk/by-partuuid/
total 0 lrwxrwxrwx 1 root root 10 May 27 23:31 0003e1e5-01 -> ../../mmcblk0p1 lrwxrwxrwx 1 root root 10 May 27 23:31 039b6c1c-7553-4455-9537-1befbc9fbc5b -> ../../sda4 lrwxrwxrwx 1 root root 10 May 27 23:31 7280201c-fc5d-40f2-a9b2-466611d3d49e -> ../../sda3 lrwxrwxrwx 1 root root 10 May 27 23:31 98a81274-10f7-40db-872a-03df048df366 -> ../../sda2 lrwxrwxrwx 1 root root 10 May 27 23:31 d0d0d110-0a71-4ed6-936a-304969ea36af -> ../../sda1
可以使用 lsblk 获取设备的分区 UUID
$ lsblk -dno PARTUUID /dev/sda1
d0d0d110-0a71-4ed6-936a-304969ea36af
或使用 blkid
# blkid -s PARTUUID -o value /dev/sda1
d0d0d110-0a71-4ed6-936a-304969ea36af
gpt-auto
如果满足 systemd-gpt-auto-generator 的所有先决条件,udev 将创建一个指向根卷块设备的 /dev/gpt-auto-root
符号链接。如果根分区使用 LUKS 加密,则 /dev/gpt-auto-root
将指向解锁/映射的卷,而 /dev/gpt-auto-root-luks
将指向加密的分区。
$ ls -l /dev/gpt-auto-*
lrwxrwxrwx 1 root root 10 May 27 23:31 /dev/gpt-auto-root -> dm-0 lrwxrwxrwx 1 root root 10 May 27 23:31 /dev/gpt-auto-root-luks -> nvme1n1p2
使用持久命名
有各种应用程序可以使用持久命名进行配置。以下是如何配置它们的一些示例。
fstab
请参阅主文章:fstab#识别文件系统。
内核参数
要在内核参数中使用持久名称,必须满足以下先决条件。在遵循安装指南的标准安装中,这两个先决条件都已满足
- 您正在使用包含 udev 的 initramfs 镜像。
- 对于 mkinitcpio,在
/etc/mkinitcpio.conf
中启用udev
或systemd
钩子
根文件系统的位置由内核命令行上的参数 root
给出。内核命令行从引导加载程序配置,请参阅内核参数#引导加载程序配置。要更改为持久设备命名,只需更改指定块设备的参数,例如 root
和 resume
,同时保持其他参数不变。支持各种命名方案
持久设备命名使用标签和 LABEL=
格式,在本例中,Arch Linux
是根文件系统的标签。
root="LABEL=Arch Linux"
持久设备命名使用 UUID 和 UUID=
格式,在本例中,0a3407de-014b-458b-b5c1-848e92a327a3
是根文件系统的 UUID。
root=UUID=0a3407de-014b-458b-b5c1-848e92a327a3
持久设备命名使用磁盘 ID 和 /dev
路径格式,在本例中,wwn-0x60015ee0000b237f-part2
是根分区的 ID。
root=/dev/disk/by-id/wwn-0x60015ee0000b237f-part2
持久设备命名使用 GPT 分区 UUID 和 PARTUUID=
格式,在本例中,98a81274-10f7-40db-872a-03df048df366
是根分区的 PARTUUID。
root=PARTUUID=98a81274-10f7-40db-872a-03df048df366
持久设备命名使用 GPT 分区标签 和 PARTLABEL=
格式,在本例中,GNU/Linux
是根分区的 PARTLABEL。
root="PARTLABEL=GNU/Linux"
当使用 GPT 分区自动挂载 时,可以完全省略 root=
参数。如果需要显式配置,请使用
root=gpt-auto