我正在尝试使用 Qemu 模拟 Raspberry Pi (+OS)。我希望操作系统firstrun.sh
在启动时执行脚本来配置各种东西。
这就是我启动 qemu 的方式:
qemu-system-aarch64 \
-M raspi3b \
-cpu cortex-a53 \
-m 1G \
-kernel kernel8.img \
-dtb bcm2710-rpi-3-b-plus.dtb \
-drive "file=2023-05-03-raspios-bullseye-arm64-lite.img,format=raw,index=0,media=disk" \
-append "rw earlyprintk loglevel=8 console=ttyAMA0,115200 dwc_otg.lpm_enable=0 root=/dev/mmcblk0p2 rootdelay=1 systemd.run=/boot/firstrun.sh systemd.run_success_action=none debug systemd.unit=kernel-command-line.target" \
-usb \
-device usb-mouse \
-device usb-kbd \
-device usb-net,netdev=net0 \
-nographic \
-serial mon:stdio \
-netdev user,id=net0,hostfwd=tcp::7777-:22
但是,当配置 Qemu/内核来执行 systemd 脚本时systemd.run=/boot/firstrun.sh
,它会卡住并且无法继续启动。
最后打印的行是:
[ OK ] Finished Command from Kernel Command Line.
[ OK ] Reached target Command from Kernel Command Line
这是一个最小的首次运行脚本:
#!/bin/bash
set +e
echo "This is the firstrun script"
rm -f /boot/firstrun.sh
sed -i 's| systemd.run.*||g' /boot/cmdline.txt
exit 0
要完全重现,请执行以下步骤:
# Download image
wget https://downloads.raspberrypi.org/raspios_lite_arm64/images/raspios_lite_arm64-2023-05-03/2023-05-03-raspios-bullseye-arm64-lite.img.xz
xz --extract 2023-05-03-raspios-bullseye-arm64-lite.img.xz
# Setup image - extract kernel.img and copy firstrun script
mount_dir=/mnt/raspberrypi
free_loopdev="$(sudo losetup -f)"
sudo kpartx -a -v 2023-05-03-raspios-bullseye-arm64-lite.img
loop_mapper=/dev/mapper/$(basename "${free_loopdev}")
sudo mkdir -p "${mount_dir}"
sudo mount "${loop_mapper}p2" "${mount_dir}"
sudo mount "${loop_mapper}p1" "${mount_dir}/boot"
cp "${mount_dir}/boot/kernel8.img" .
cp "${mount_dir}/boot/bcm2710-rpi-3-b-plus.dtb" .
sudo cp firstrun.sh "${mount_dir}/boot"
# Run Qemu with Image
cmdline="rw earlyprintk loglevel=8 console=ttyAMA0,115200 dwc_otg.lpm_enable=0 root=/dev/mmcblk0p2 rootdelay=1 systemd.run=/boot/firstrun.sh systemd.run_success_action=none debug systemd.unit=kernel-command-line.target"
qemu-img resize -f raw "2023-05-03-raspios-bullseye-arm64-lite.img" 4G
qemu-system-aarch64 \
-M raspi3b \
-cpu cortex-a53 \
-m 1G \
-kernel kernel8.img \
-dtb bcm2710-rpi-3-b-plus.dtb \
-drive "file=2023-05-03-raspios-bullseye-arm64-lite.img,format=raw,index=0,media=disk" \
-append "${cmdline}" \
-usb \
-device usb-mouse \
-device usb-kbd \
-device usb-net,netdev=net0 \
-nographic \
-serial mon:stdio \
-netdev user,id=net0,hostfwd=tcp::7777-:22
如果我省略firstrun.sh
脚本,启动过程就可以正常工作。
为什么在执行 firstrun.sh 时引导进程不继续?
通过设置
systemd.run
,您是在隐式设置systemd.unit=kernel-command-line.target
(实际上,在您的命令行中您是在显式设置,但这不是必需的)。设置systemd.unit
实际上是在告诉 systemd,“执行此操作而不是执行正常引导”。这就是事情似乎“卡住”的原因——您的 firstrun 脚本正确执行,就 systemd 而言,不需要发生任何其他事情。
最简单的解决方案可能是结束你的
firstrun.sh
脚本:在您的首次运行脚本完成后,这将继续进行常规引导。
给出
firstrun.sh
这样的脚本:root
当系统完成启动时,我可以在控制台上成功登录。Ssh 在主机端口 7777 上处于活动状态。与您的问题无关,但您可以
kpartx
通过使用以下-P
参数来避免使用losetup
:你可以避免使用循环设备,
sudo
完全通过使用guestfish
来处理图像。我会做这样的事情来 (a) 创建原始图像的写时复制克隆,然后 (b) 配置它: