为什么不能用UUID指定我的根fs?


29

我的系统在GRUB 2配置中对此进行了启动:

linux   /bzImage root=/dev/sda2 init=/usr/lib/systemd/systemd ro

但是,如果我替换/dev/sda2为相应的UUID:

linux   /bzImage root=UUID=666c2eee-193d-42db-a490-4c444342bd4e init=/usr/lib/systemd/systemd ro

然后在启动过程中失败:

kernel panic - not syncing: VFS: unable to mount root fs on unknown-block(0,0)

UUID似乎是正确的:

# blkid
/dev/sda1: UUID="97ac3744-39de-4d6d-9a81-e3a3ea08a8bb" TYPE="ext2" 
/dev/sda2: UUID="666c2eee-193d-42db-a490-4c444342bd4e" TYPE="ext4" 

为什么不起作用?是因为我没有使用initramfs吗?

这是具有内核3.10.7的x86_64 Gentoo Linux。我在使用MBR分区表,在上sda使用GUID分区表sdb


unknown-block(0,0)在我看来就像GRUB设备。我的猜测是GRUB由于某种原因无法使用该UUID。
13年

@strugee,我认为GRUB根本不会尝试解释内核命令行。(GRUB正在从中加载内核sda1。我没有显示配置的那部分。)
cjm

我倾向于同意。但是,该设备看起来像GRUB设备而不是UNIX设备,这很奇怪。
13年

@Gilles,问题不关GRUB。恰好是我正在使用的引导程序。这是一个Linux内核问题。
cjm 2013年

这也不是关于内核的问题-这是关于的问题init
mikeserv

Answers:


22

只是澄清UUID是内核识别硬盘驱动器的唯一可靠方法。有两种类型:UUID(存储在文件系统中,在启动时对内核不可用)和PARTUUID(存储在分区表中,在启动时为IS)。所以你必须使用

root=PARTUUID=SSSSSSSS-PP

作为/dev/sd??可以与设备改变插入/拔出。

不要忘记将您从中得到的十六进制数字大写SSSSSSSS-PPblkid

更容易使用

root=LABEL=
root=UUID=

仅适用于initramfs可获取这些标识符的。

因此,如果您使用非空initramfs,则可以同时拥有这三个!空无一物initramfs,你只有PARTUUID


介意解释谁在使用boot =参数呢?我只是将这一行用于没有initrd的Archlinuxarm安装,并且在这里我无法使用boot = LABEL或boot = UUID。
ineiti

1
您是对的-我已将启动问题更正为root,抱歉!希望现在更有意义。
ineiti 2014年

1
我的理解(在archlinuxarm的论坛上待了一天)是在Archlinuxarm上没有initrd(或initramfs,但kernel.org/doc/Documentation/kernel-parameters.txt称为initrd)。在Ubuntu等上,我确实提供了指向initrd的指针,但是(据我的理解)不是在Archlinuxarm上。
ineiti 2014年

1
关于没有initrd的Archlinuxarm讨论:archlinuxarm.org/forum/viewtopic.php?
f=

1
试试这个链接。还有这个。也许一个。initramfs 不是 initramfs映像-通常是压缩的归档文件,其中包含cpio内核/在启动时解压缩到的归档文件。initramfs是一个文件系统-它始终是第一个/挂载的内核,从那里开始调用init。您可以将内容编译到内核中或在引导时解压缩它们-这是两个选项。
mikeserv

16

从UUID启动必须传递的参数是PARTUUID。应该是这样root=PARTUUID=666c2eee-193d-42db-a490-4c444342bd4e

该文档说明了为什么返回unknown-block(0,0)

kernel-parameters.txt

    root = [KNL]根文件系统
            请参阅init / do_mounts.c中的name_to_dev_t注释。

init / do_mounts.c

/ *
 *将名称转换为设备编号。我们接受以下变体:
 *
 * 1)设备编号以十六进制表示
 * 2)/ dev / nfs代表Root_NFS(0xff)
 * 3)/ dev / <disk_name>代表磁盘的设备号
 * 4)/ dev / <磁盘名称> <十进制>代表设备号
 *分区的*-磁盘的设备号加上分区号
 * 5)/ dev / <磁盘名称> p <十进制>-与上面相同,形式为
 *当分区磁盘的磁盘名称以数字结尾时使用。
 * 6)PARTUUID = 00112233-4455-6677-8899-AABBCCDDEEFF代表
 *分区表提供的分区的唯一ID。
 * UUID可以是EFI / GPT UUID,也可以是MSDOS
 *使用SSSSSSSS-PP格式进行分区,其中SSSSSSSS为零,
 *填充了32位“ NT磁盘签名”和PP的十六进制表示
 *是从1开始的分区号的零填充十六进制表示。
 * 7)PARTUUID = <UUID> / PARTNROFF = <int>选择与之相关的分区
 *具有已知唯一ID的分区。
 *
 *如果名称不属于上述类别,则返回(0,0)。
 * block_class用于检查某些东西是否是磁盘名称。如果磁盘
 *名称包含斜杠,设备名称已将其替换为
 刘海。
 * /

最后的最后一位表示,如果无法理解该值,则返回(0,0),因此出现错误。


1
这只是部分正确。分区UUID与文件系统的UUID完全不同,因此PARTUUID=666c2eee-193d-42db-a490-4c444342bd4e不起作用。但是,我可以使用PARTUUID=SSSSSSSS-02(其中SSSSSSSS是错误消息之前显示的NT磁盘签名)。
cjm

6
因此,我想真正的答案是内核root=UUID仅支持内核root=PARTUUID。如果要使用文件系统UUID,我想您需要一个可以通过UUID处理挂载文件系统的initramfs。
cjm

@cjm我的grub靴子很开心root=UUID
terdon

3
@terdon,我敢打赌你有一个initramfs或initrd。(它可以链接到您的内核中,而不是作为一个单独的文件。)
cjm

4

这是一个有5年历史的线程。但是,恕我直言,仍然没有完全回答。缺少一个小例子。这里是:

在此示例中:

/dev/sda3 = /
/dev/sda2 = swap

...使用GPT分区。使用MBR(DOS分区),PARTUUID较短,但是过程相同...

使用blkid获​​取PARTUUID:

blkid -s PARTUUID -o value /dev/sda3 # root
77fd7830-faa2-4e99-a48b-337ad9eded28
blkid -s PARTUUID -o value /dev/sda2 # swap
5b63167a-6fd2-4e72-948c-90832372956c

/boot/grub/grub.cfg:

search --no-floppy --part-uuid --set=root 77fd7830-faa2-4e99-a48b-337ad9eded28

menuentry "GNU/Linux, KERNEL 4.12.7-lfs-8.1" {
  linux /boot/vmlinuz-4.12.7-lfs-8.1 root=PARTUUID=77fd7830-faa2-4e99-a48b-337ad9eded28 net.ifnames=0 ipv6.disable=1 ro rootwait rootfstype=ext4
}

/ etc / fstab /:

PARTUUID=77fd7830-faa2-4e99-a48b-337ad9eded28 / ext4 noatime,nodiratime,errors=remount-ro 0 1
PARTUUID=5b63167a-6fd2-4e72-948c-90832372956c swap swap pri=1 0 0

这对于lfs8.1(kernel 4.12.7)来说是众所周知的,但是我认为它也应该适用于大多数其他内核(旧的和较新的...)

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.