Udev通过设备唯一属性(如ID_SERIAL)创建稳定软链接替代易变的/dev/sdX。需用udevadm获取设备属性、编写规则、重载并测试,或直接使用系统自建的/dev/disk/by-id/链接。

为什么 sdX 名字每次插拔都会变
Linux 内核按探测顺序给 SCSI/SATA/USB 磁盘分配 sdX(如 sdb、sdc),同一块盘插在不同 USB 口、或系统启动时 USB 设备初始化顺序稍有差异,就可能从 sdb 变成 sdc。依赖 /dev/sdX 写脚本或挂载配置,十次有八次会出错。
Udev 是用户空间设备管理器,在内核发现新设备后,根据规则生成稳定的符号链接。关键不是“改名”,而是“建一个永不变化的软链”,指向当前实际的设备节点。
怎么写一条可靠的 Udev 规则匹配某块外接磁盘
不能靠 sdX 名字匹配,得用设备自身不变的属性:比如序列号(ID_SERIAL_SHORT)、厂商+型号+序列组合(ID_SERIAL)、或 WWN(对 NVMe/USB-attached SSD 更稳)。先插上目标盘,运行:
udevadm info --name=/dev/sdb --query=property | grep -E "ID_SERIAL|ID_MODEL|ID_VENDOR"
你会看到类似:
ID_SERIAL=Western_Digital_My_Book_2023_ABC123456789
这条 ID_SERIAL 就是唯一指纹。把它写进规则:
Zynq‑7000 / Zynq UltraScale+ 硬件调试技能。适用于 Xilinx Zynq(Cortex‑A9/A53 + FPGA)Linux 环境,调试 I2C、I2S、UART、GPIO 等外设。包括设备树配置、内核驱动、用户空间调试工具、交叉编译和常见问题排查,支持 PetaLinux 开发。
- 规则文件放
/etc/udev/rules.d/99-my-usb-disk.rules(数字越小优先级越高,99-确保靠后生效) - 内容必须用
SUBSYSTEM=="block"限定只匹配块设备,加SYMLINK+="disk-mybook"创建固定链接 - 完整一行示例:
SUBSYSTEM=="block", ATTRS{idVendor}=="1058", ATTRS{idProduct}=="25a3", ENV{ID_SERIAL}=="Western_Digital_My_Book_2023_ABC123456789", SYMLINK+="disk-mybook" -
ATTRS{idVendor}和ATTRS{idProduct}是 USB 厂商/产品 ID,可进一步缩小范围,避免同型号其他盘误匹配
规则写完不生效?常见卡点在哪
Udev 规则不是写完就自动加载的。最常漏的三步:
- 文件权限必须是
0644(sudo chmod 0644 /etc/udev/rules.d/99-my-usb-disk.rules),否则 udevd 直接忽略 - 规则语法错误会导致整条规则静默失效——用
sudo udevadm test /sys/class/block/sdb查看是否命中、有没有报错(注意路径要写/sys/...,不是/dev/...) - 测试时别只拔插,先手动触发重载:
sudo udevadm control --reload-rules && sudo udevadm trigger --subsystem-match=block;如果设备已在线,还得加--action=add或直接sudo udevadm trigger /sys/class/block/sdb
另外,SYMLINK+= 创建的是 /dev/disk-mybook,不是目录。如果想挂载,直接用 /dev/disk-mybook 当设备名即可,和 /dev/sdb1 用法完全一样(前提是分区存在)。
要不要用 /dev/disk/by-id/ 替代自定义规则
Linux 默认就生成了 /dev/disk/by-id/ 下一堆链接,比如 usb-Western_Digital_My_Book_2023_ABC123456789-0:0。它本质也是 udev 规则(/usr/lib/udev/rules.d/60-persistent-storage.rules)生成的,已经覆盖绝大多数 USB/ATA 设备。
所以除非你有强需求(比如名字太长、含特殊字符、或需要统一前缀如 disk-),否则直接用 /dev/disk/by-id/usb-... 最省事。验证方式:ls -l /dev/disk/by-id/ | grep -i western。它的稳定性不输自定义规则,且无需维护。
真正容易被忽略的是:某些廉价 USB 转接盒不透传序列号,ID_SERIAL 为空或恒为 000000000000000000000000。这时只能退回到 ATTRS{bInterfaceClass}=="08" + ATTRS{bInterfaceSubClass}=="06" 这类 USB 协议层匹配,但可靠性大幅下降——同一转接盒插两块盘,就彻底分不清了。

















