执行无人值守安装后,生成的 VirtualBox 映像无法启动,并出现以下错误:
[0.630571] Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,0)
[0.630822] CPU: 0 PID: 1 Comm: swapper/0 Not tainted 5.4.0-33-generic #37-Ubuntu
[0.631039] Hardware name: innotek GmbH VirtualBox/VirtualBox, BIOS VirtualBox 12/01/2006
[0.631271] Call Trace:
[0.631374] dump_stack+0x6d/0x93a
[0.631494] panic+0x101/0x2e3
[0.631609] mount_block_root+0x23f/0xZ2e8
[0.631744] mount_root+0x38/0x3a
[0.631863] prepare_namespace+O0x13f/0x194
[0.632000] kernel_init_freeable+0x231/0x255
[0.632144] ? rest_init+0xb0/0xbO
[0.632264] kernel_init+Oxe/0x100
[0.632384] ret_from_fork+0x35/0x40
[0.632540] Kernel Offset: Oxd800000 from OxffffffffB81000000 (relocation range: 0xffffffff80000000-0xffffffffbfffffff)
[0.632832] ---[ end Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,0) ]---
用于运行安装的脚本如下:
#!/bin/bash
MACHINENAME=machine-name
MACHINEPATH=/Some/Path
cd $MACHINEPATH
# Download debian.iso
if [ ! -f ./ubuntu.iso ]; then
wget http://cdimage.ubuntu.com/ubuntu-legacy-server/releases/20.04/release/ubuntu-20.04-legacy-server-amd64.iso -O ubuntu\
.iso
fi
#Create VM
VBoxManage createvm --name $MACHINENAME --ostype "Ubuntu_64" --register --basefolder $MACHINEPATH
#Set memory and network
VBoxManage modifyvm $MACHINENAME --ioapic on
VBoxManage modifyvm $MACHINENAME --memory 2048 --vram 128
VBoxManage modifyvm $MACHINENAME --nic1 nat
#Create Disk and connect Debian Iso
VBoxManage createhd --filename $MACHINEPATH/$MACHINENAME/$MACHINENAME_DISK.vdi --size 80000 --format VD\
I
VBoxManage storagectl $MACHINENAME --name "SATA Controller" --add sata --controller IntelAhci
VBoxManage storageattach $MACHINENAME --storagectl "SATA Controller" --port 0 --device 0 --type hdd --medium $MACHINEPATH/$MACHINENAME/$MACHINENAME_DISK.vdi
VBoxManage storagectl $MACHINENAME --name "IDE Controller" --add ide --controller PIIX4
VBoxManage storageattach $MACHINENAME --storagectl "IDE Controller" --port 1 --device 0 --type dvddrive --medium `pwd`/ubuntu\
.iso
VBoxManage modifyvm $MACHINENAME --boot1 dvd --boot2 disk --boot3 none --boot4 none
VBoxManage modifyvm $MACHINENAME --audio none
PASSWORD=`uuidgen`
VBoxManage unattended install $MACHINENAME --user=machineuser --password=$PASSWORD --country=NO --time-zone=UTC --hostname=$MACHINENAME.example.com --iso=ubuntu.iso --install-additions --start-vm=gui
#Start the VM
VBoxHeadless --startvm $MACHINENAME
使用旧内核(linux-5.4.0-26)启动生成的映像工作正常。
答案1
您需要在 late-command 中修补内核。对于 20.04,我使用自动安装而不是 Debian 安装程序,它不会出现此问题。
- 拦截配置文件
--auxiliary-base-path
VBoxManage unattended install {name} --user={config['mcs']['user']} --password={config['mcs']['pwd']} \
--auxiliary-base-path {aux}/ \
--install-additions --iso={download} --country=SG --post-install-template={cfg} --script-template={cfg}
- 在 late 命令中修补最新内核
# Custom Commands
#d-i preseed/late_command string cp /cdrom/vboxpostinstall.sh /target/root/vboxpostinstall.sh \
# && chmod +x /target/root/vboxpostinstall.sh \
# && /bin/sh /root/vboxpostinstall.sh --need-target-bash --preseed-late-command
d-i preseed/late_command string \
echo 'mcs ALL=(ALL) NOPASSWD: ALL' > /target/etc/sudoers.d/mcs ; \
in-target chmod 440 /etc/sudoers.d/mcs ; \
in-target update-initramfs -c -k @@kernal@@ ; \
in-target update-grub ; \
in-target apt-get install -y avahi-daemon avahi-autoipd ; \
in-target apt-get -y install build-essential linux-headers-$(uname -r) ; \
in-target /bin/bash /media/cdrom/vboxadditions/VBoxLinuxAdditions.run --nox11 ; \
in-target /bin/bash -c "udevadm constrol --reload-rules" ; \
in-target /bin/bash -c "udevadm trigger" ; \
in-target usermod -a -G vboxsf "mcs" ; \
in-target apt-get install -y openssh-server
- 查找并修补内核的示例代码
# kernal version keeps changing.... substitute it in...
def preseed(aux, buildkey, config, alog):
version = re.search("([0-9]{2}\.[0-9]{2})", config["ubuntu"][buildkey]["dl"])[0]
if StrictVersion(version) < StrictVersion("20.04"):
kurl = {
"19.10":"https://packages.ubuntu.com/eoan-updates/linux-image-generic"
}
with open(f"{aux}/preseed.cfg") as f: cfg = f.read()
resp = requests.get(kurl[version])
soup = BeautifulSoup(resp.content.decode(), "html.parser")
# pick out the dotted version number from h1 tag
rawv = re.search("([0-9,.]+)", soup.h1.contents[0])[0]
# 5.3.0-51-generic
v = re.findall("([0-9]+)", rawv)
kernal = f"{v[0]}.{v[1]}.{v[2]}-{v[3]}-generic"
alog.info(f"fix preseed {kernal}")
cfg = re.sub("\@\@kernal\@\@", kernal, cfg)
with open(f"{aux}/preseed.cfg", "w") as f: f.write(cfg)