我有一个来自 x86-64 机器的安装硬盘映像,openSUSE
但我无法再访问该映像。我正在尝试使用此原始磁盘启动quemu
。如果我使用例如qemu-system-x86_64 -m 4096 -curses -hda srv.sda -enable-kvm
或启动虚拟机qemu-system-x86_64 -m 4096 -curses -drive id=disk,file=srv.sda,if=none,format=raw -device ahci,id=ahci -device ide-drive,drive=disk,bus=ahci.0 -enable-kvm
,那么我最终会进入 GRUB 2.02 shell,在其中我可以使用以下命令指定 Linux 内核和初始 ramdisk:
grub> linux (hd0,msdos1)/boot/vmlinuz
grub> initrd (hd0,msdos1)/boot/initrd
grub> boot
这将启动引导过程,该过程始终在此结束:
[ 0.234732] NET: Registered protocol family 10
[ 0.235188] lo: Disabled Privacy Extensions
[ 0.235592] lib80211: common routines for IEEE802.11 drivers
[ 0.236014] registered taskstats version 1
[ 0.236439] Magic number: 1:617:774
[ 0.236774] mem zero: hash matches
[ 0.237151] rtc_cmos 00:01: setting system clock to 2021-04-22 07:46:24 UTC (
1619077584)
[ 0.237802] Freeing unused kernel memory: 896k freed
[ 0.238330] Write protecting the kernel read-only data: 10240k
[ 0.238762] Freeing unused kernel memory: 1616k freed
[ 0.239578] Freeing unused kernel memory: 748k freed
doing fast boot
Creating device nodes with udev
[ 0.255337] udev: starting version 157
mount: devpts already mounted or /dev/pts busy
mount: according to mtab, devpts is already mounted on /dev/pts
Boot logging started on /dev/char/../tty1(/dev/console) at Thu Apr 22 10:46:24 2
021
resume device not found (ignoring)
Waiting for device /dev/sda1 to appear: [ 1.072809] input: ImExPS/2 Generic E
xplorer Mouse as /devices/platform/i8042/serio1/input/input1
..............................Could not find /dev/sda1.
Want me to fall back to /dev/sda1? (Y/n)
我能否以某种方式修改磁盘设置,qemu
使磁盘的第一个也是唯一一个分区可用于 Linux?例如,看起来 GRUB 能够访问它,因为它成功读取了/boot/vmlinuz
和/boot/initrd
。
编辑1:重新创建初始 ramdisk 并包含ata_piix
内核模块后qemu-system-x86_64
,启动过程如下:
[ 0.244118] rtc_cmos 00:01: setting system clock to 2021-04-27 15:31:52 UTC (
1619537512)
[ 0.244762] Freeing unused kernel memory: 896k freed
[ 0.245284] Write protecting the kernel read-only data: 10240k
[ 0.245716] Freeing unused kernel memory: 1616k freed
[ 0.246529] Freeing unused kernel memory: 748k freed
doing fast boot
[ 0.266568] SCSI subsystem initialized
[ 0.267653] megasas: 00.00.04.17.1-rc1 Thu. Oct. 29, 11:41:51 PST 2009
[ 0.278467] scsi0 : ata_piix
[ 0.278833] scsi1 : ata_piix
[ 0.279164] ata1: PATA max MWDMA2 cmd 0x1f0 ctl 0x3f6 bmdma 0xc060 irq 14
[ 0.279562] ata2: PATA max MWDMA2 cmd 0x170 ctl 0x376 bmdma 0xc068 irq 15
Creating device nodes with udev
[ 0.444780] udev: starting version 157
mount: devpts already mounted or /dev/pts busy
mount: according to mtab, devpts is already mounted on /dev/pts
Boot logging started on /dev/char/../tty1(/dev/console) at Tue Apr 27 18:31:52 2
021
resume device not found (ignoring)
Waiting for device /dev/sda1 to appear: [ 1.080811] input: ImExPS/2 Generic E
xplorer Mouse as /devices/platform/i8042/serio1/input/input1
..............................Could not find /dev/sda1.
Want me to fall back to sda1? (Y/n)
如上所示,该ata_piix
模块似乎已加载,但/dev/sda1
仍未找到。
编辑2:我修改了/etc/fstab
in环境,将其替换为chroot
,重新生成了初始 ramdisk,并尝试通过在 GRUB shell 中指定 Linux 内核和初始 ramdisk 来引导该系统:/dev/sda1 / reiserfs acl,user_xattr 1 1
UUID=dafc3c3a-1469-44b1-b85c-deb904aac291 / reiserfs acl,user_xattr 1 1
grub> linux (hd0,msdos1)/boot/vmlinuz root=UUID=dafc3c3a-1469-44b1-b85c-deb904aac291
grub> initrd (hd0,msdos1)/boot/initrd
grub> boot
不幸的是,系统没有启动。我还将添加mkinitrd
输出:
# mkinitrd -v -k vmlinuz-2.6.34.10-0.6-default -i initrd-2.6.34.10-0.6-default -d /
Kernel image: /boot/vmlinuz-2.6.34.10-0.6-default
Initrd image: /boot/initrd-2.6.34.10-0.6-default
[MODULES] 02-start.sh: reiserfs thermal megaraid_sas ata_piix ata_generic processor fan
[MODULES] 02-start.sh:
[MODULES] 03-rtc.sh: rtc_cmos
[MODULES] 03-storage.sh: reiserfs
[MODULES] 11-usb.sh: usbcore
[MODULES] 11-usb.sh: ohci_hcd
[MODULES] 11-usb.sh: uhci-hcd
[MODULES] 11-usb.sh: ehci_hcd
[MODULES] 11-usb.sh: usbhid
[MODULES] 'modinfo -k "2.6.34.10-0.6-default" -F supported' returned with an error.
Kernel Modules: reiserfs thermal_sys thermal scsi_mod megaraid_sas libata ata_piix ata_generic processor fan usbcore pcmcia_core pcmcia mmc_core ssb ohci-hcd ehci-
hcd uhci-hcd usbhid
[MOUNT] Root: /
Features: usb resume.userspace resume.kernel
Bootsplash: openSUSE (640x480)
Shared libs: /lib/udev/collect_lvm is a script
/lib/udev/findkeyboards is a script
/lib/udev/idedma.sh is a script
/lib/udev/iwlwifi-led.sh is a script
/lib/udev/keyboard-force-release.sh is a script
/lib/udev/kpartx_id is a script
/lib/udev/udev-add-printer is a script
/lib/udev/write_cd_rules is a script
/lib/udev/write_net_rules is a script
/lib/mkinitrd/bin/ipconfig.sh is a script
/sbin/ifup is a script
/lib/mkinitrd/bin/ipconfig.sh is a script
/lib/mkinitrd/bin/linuxrc is a script
/usr/bin/on_ac_power is a script
lib64/ld-2.11.2.so lib64/libacl.so.1.1.0 lib64/libattr.so.1.1.0 lib64/libblkid.so.1.1.0 lib64/libcap.so.2.16 lib64/libcom_err.so.2.1 lib64/libcrypto.so.1.0.0 lib64
/libc-2.11.2.so lib64/libdevmapper.so.1.02 lib64/libdl-2.11.2.so lib64/libgcrypt.so.11.5.2 lib64/libgpg-error.so.0.5.0 lib64/libkeyutils-1.3.so lib64/liblzo2.so.2.
0.0 lib64/libm-2.11.2.so lib64/libncurses.so.5.7 lib64/libpcre.so.0.0.1 lib64/libpthread-2.11.2.so lib64/libreadline.so.6.1 lib64/libresolv-2.11.2.so lib64/librt-2
.11.2.so lib64/libselinux.so.1 lib64/libsepol.so.1 lib64/libssl.so.1.0.0 lib64/libudev.so.0.8.2 lib64/libutil-2.11.2.so lib64/libuuid.so.1.3.0 lib64/libz.so.1.2.3
usr/lib64/libatasmart.so.4.0.3 usr/lib64/libcups.so.2 usr/lib64/libdal-0.3.so.0.0.0 usr/lib64/libdirect-1.2.so.9.0.0 usr/lib64/libdirectfb-1.2.so.9.0.0 usr/lib64/l
ibfusion-1.2.so.9.0.0 usr/lib64/libglib-2.0.so.0.2400.1 usr/lib64/libgssapi_krb5.so.2.2 usr/lib64/libk5crypto.so.3.1 usr/lib64/libkrb5.so.3.3 usr/lib64/libkrb5supp
ort.so.0.1 usr/lib64/libparted.so.0.0.1 usr/lib64/libreiserfs-0.3.so.0.0.0 usr/lib64/libsplashycnf.so.1.0.0 usr/lib64/libsplashy.so.1.0.0 usr/lib64/libusb-0.1.so.4
.4.4 usr/lib64/libusb-1.0.so.0.0.0 lib64/libnss_dns-2.11.2.so lib64/libnss_dns.so.2 lib64/libnss_files-2.11.2.so lib64/libnss_files.so.2 lib64/libgcc_s.so.1
37516 blocks
Perl-Bootloader: 2021-05-03 18:57:38 ERROR: UDEVMAPPING: dmdev /dev/dm-0 doesn't have defined DM_NAME in udev
#
DM_NAME
中的变量存在错误udev
,但另一方面,会创建新的初始 ramdisk 文件,例如,添加ata_piix
明确有效的 .我还尝试过使用不同的根设备(选项-d
)。mkinitrd
sda1
答案1
我的第一个猜测是原始系统中的存储控制器与 qemu 提供的存储控制器不同,因此 initrd 文件不包含运行虚拟存储控制器的正确模块。
默认的存储控制器qemu-system-x86_64
似乎不是AHCI,而是经典的Intel PIIX3 IDE控制器。它需要ata_piix
内核模块,而在任何使用 AHCI 作为最低基线的相当现代的物理系统的 initrd 中,内核模块都是不必要的。
因此,内核根本无法看到磁盘,引导过程也无法从 initrd 转换到真正的根文件系统。
GRUB 可以很好地识别磁盘,因为它使用 BIOS 例程来访问磁盘...并且由于 BIOS 是由 qemu 提供的,因此 BIOS 显然具有完全正确的例程来完成这项工作。
如果您可以访问虚拟机的命令提示符,请尝试以下命令:
dmesg | grep -e piix -e ahci -e " sd"
它应该显示与磁盘检测相关的任何消息:如果没有显示任何内容,则未检测到您的(虚拟)存储控制器,这使得无法检测虚拟磁盘。
要修复它,您可能必须访问常规系统中的磁盘映像:(如果/dev/loop0
系统已在使用该磁盘映像,请改用免费循环设备)
losetup -P /dev/loop0 srv.sda
然后安装/dev/loop0p1
到常规系统中合适的临时位置:
mkdir /mnt/opensuse
mount /dev/loop0p1 /mnt/opensuse
将必要的虚拟文件系统和 chroot 添加到磁盘映像的文件系统中,类似于从实时 Linux 介质引导物理系统时可能执行的操作:
mount --rbind /dev /mnt/opensuse/dev
mount --bind /proc /mnt/opensuse/proc
mount --bind /sys /mnt/opensuse/sys
chroot /mnt/opensuse
现在您应该能够在磁盘映像中重新创建 initrd/initramfs 文件。您没有在映像上指定 OpenSUSE 系统的版本,但经典命令可能是要使用的工具 - 或者它实际上可能是新版本可能使用的mkinitrd
任何新工具(也许?)的兼容性别名。dracut
无论使用哪个工具在该版本的 OpenSUSE 中创建 initrd 文件,该工具很可能有一个选项来强制将特定内核模块包含在 initrd 中。阅读该工具的手册页以找到该选项,并使用它创建一个ata_piix
包含该模块的新 initrd。 (为了安全起见,请先将原始 initrd 文件移到一边。)
一旦您initrd
在/boot
映像的正确位置成功创建了一个新文件,就exit
可以脱离 chroot 环境,umount
执行之前执行的所有安装操作,并使用losetup -d /dev/loop0
.现在您可以尝试再次启动映像,希望能够成功。
答案2
通过重新创建 initrd 文件mkinitrd
是正确的做法,只是应该在尽可能接近最终目标操作系统将使用的系统上完成。这是因为mkinitrd
它在内核和系统上执行了大量的自动检测跑步从,特别是关于可供 initrd 文件使用的内核模块。您已经从主机操作系统重新创建了 initrd 文件,这显然与您的旧机器有很大不同,因此mkinitrd
构建了一个不完整/不一致的 initrd。
在这些情况下,最好的方法通常是从原始分布的安装 CD/DVD/ISO,因为这些通常有一个“救援模式”,在这些情况下可以派上用场,从那里重新创建 initrd 文件。在你的情况下,目标操作系统似乎是 openSuSE 11.3,所以你可以获取其 ISOqemu
,使用您希望目标操作系统调整到的任何虚拟系统(-hda
或者-device ahci
甚至是一些 SCSI/SAS,如果您愿意的话)启动它,选择“救援系统”选项,该选项可从该系统的第一个启动菜单中找到ISO,登录root
并从那里运行:
~# mount /dev/sda1 /mnt
~# cd /mnt
/mnt# mount --rbind /dev dev && mount --make-rslave dev
/mnt# mount -t proc proc proc
/mnt# mount -t sysfs sysfs sys
/mnt# chroot .
<chrooted># mkinitrd
...
<chrooted># exit
/mnt# umount dev/pts dev/shm dev proc sys
/mnt# cd ..
/# umount mnt
重新创建 initrd 文件。
使用在真实目标系统上运行的真实原始内核(来自 openSuSE 11.3 的内核)启动后qemu
,一个没有任何选项的简单内核mkinitrd
应该可以正常工作。
当然,在上述操作之后,您将使用相同的虚拟系统但没有 ISO 映像poweroff
重新运行。qemu
就像您尝试过的那样,完全有可能从完全不同的操作系统重新创建 initrd 文件,但随后需要准确地知道全部这必需的驱动程序,以便覆盖 . 执行的(不可避免的)不完整/不一致的自动检测mkinitrd
。
在您的情况下,我发现您重新创建的 initrd 文件缺少提供磁盘设备sd_mod
实际上所需的驱动程序。/dev/sd*
它没有被复制可能是因为你的主持人操作系统(您在其上重新创建 initrd 文件)没有该驱动程序作为sd_mod.ko
可加载模块,而是将其编译到内核映像本身中。这是很有可能的,因为该模块现在已经成为默认模块,而 10 年前根本不是默认模块,就像它的 IDE 对应模块 ( ide-disk.ko
) 直到大约 15 年前才成为默认模块(即编译)一样,而现在它常常被完全忽略。
因此,您可能只需重复在主机操作系统上执行的相同操作,同时还指定sd_mod
以及ata_piix
,并且您可能已准备就绪。然而,在这种情况下,例如,如果原始安装 CD/DVD/ISO 不可用,更安全的替代方案是mkinitrd -A
从主机操作系统上的 chroot 环境内部运行,因为该参数指示mkinitrd
简单地包含所有可能的驱动程序。当然,这需要 initrd 文件所在的文件系统有更多的磁盘空间,但是一旦启动到目标操作系统的磁盘,您最终可以使用简单的(即无参数)重新创建 initrd,mkinitrd
它会重建精简的 initrd 文件对于新的硬件系统。
答案3
根据我发表的 UUID 评论。
假设您有权访问磁盘(磁盘/映像),您可以按照 @telcoM 上面给出的说明将其安装在主机上。从那里你可以跑去blkid
获取UUID
然后您可以更新/etc/fstab
磁盘映像。我认为它有一条看起来像这样的线
/dev/sda1 / ext4 defaults 1 1
注释掉该行并将其替换/dev/sda1
为UUID=###
例如
UUID=aaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa / ext4 defaults 1 1
如果可能的话,在 grub linux 线上做类似的事情
grub> linux (hd0,msdos1)/boot/vmlinuz root=UUID=###