无需硬件访问(例如在 chroot 中)来更新 grub2?

无需硬件访问(例如在 chroot 中)来更新 grub2?

我正在编写一个脚本,它获取主 KVM 映像、将其转换为 VDI、对其进行一些更改并提供下载。

我需要更新一些新创建的映像的内核启动参数。通常,人们会编辑 /etc/default/grub 中的 GRUB_CMDLINE_LINUX_DEFAULT 设置,然后运行 ​​update-grub。当然,我只能在 chroot 中执行此操作,但会失败:“/usr/sbin/grub-probe:错误:找不到 / 的设备(/dev 是否​​已安装?)。”

将正在运行的系统上的 /dev 绑定挂载到 chroot 中允许 update-grub 运行,但会导致 grub.cfg 损坏(从映像的角度来看是错误的根设备)。

如果我仅使用 sed 添加我需要的内核参数,它将启动映像,但后续运行 update-grub(从现在正在运行的映像内部)将会导致麻烦。

所以我当前的解决方案是:

  1. 编辑 /etc/default/grub 中的参数
  2. 将 /dev 绑定到 chroot
  3. 在 chroot 中运行 update-grub
  4. 使用 sed 修复 /boot/grub/grub.cfg 中的错误设备节点

请告诉我有更好的方法。

答案1

正确的答案是将 /dev 挂载到 chroot,并使用 $CHROOT/boot/grub/device.map 文件告诉 grub (hd0)(从图像的角度来看)实际上是您已“分区”的环回文件(然后使用 kpartx 等挂载到您的 chroot 中)。

# generate grub configs and install it to the generated blockdev
chroot $MR update-grub 2> /dev/null
chroot $MR grub-mkconfig -o /boot/grub/grub.cfg 2> /dev/null
cat > $MR/boot/grub/device.map <<EOF
(hd0)   ${LOOPDEV}
EOF
chroot $MR grub-install ${LOOPDEV} 2> /dev/null

在将 grub 安装到 loopdev 的“mbr”之后,您应该 rm device.map 文件,因为一旦实际启动,从映像的角度来看它将不再准确。

我有一个脚本,可以为 ubuntu 13.10 saucy x64 构建完整的 qcow2 映像:

https://github.com/sneak/kvm-ubuntu-imagebuilder/blob/master/buildimage.sh#L211

祝你好运。

答案2

请注意,该答案假设您的磁盘已分区。

sneak 的答案适用于运行 grub 1.99 的 Debian wheezy,但不适用于 grub2。您需要使用 UUID(如受到推崇的由 grub 开发人员创建)来引用设备/分区。
问题在于:kpartx(用于映射分区的工具)不会在 中创建符号链接/dev/disk/by-uuid,grub 会使用该符号链接来验证在生成配置时是否可以使用检测到的 UUID,因此它会返回到设备路径。要纠正这个问题,只需自己对设备进行符号链接即可(ln -s /dev/sdX /dev/disk/by-uuid/$(blkid -s UUID -o value /dev/sdX))。

我希望这能对你有所帮助,如果没有,那么也许其他人也会像我一样偶然发现这个问题,因为弄清楚这一点花了相当长一段时间。

相关内容