serial-port - QEMU 串行标准输出在 archlinux 客户机上发散
问题描述
我正在尝试在 QEMU 中引导一些新下载的 ISO 的安装自动化。我创建了一个干净的 img 来安装并启动 QEMU,如下所示:
$ qemu-img create -f qcow2 out/main.img 15G
$ qemu-system-x86_64
-m 8G \
-serial stdio \
-cdrom out/linux.iso \
-drive file=out/main.img,if=virtio \
-netdev user,id=net0 \
-device e1000,netdev=net0
我可以看到 Arch 启动了。起初,显示器和终端是同步的,但在 GRUB 启动屏幕之后它们很快就不同了。
我不确定我缺少什么来让它工作。我看到有些人建议添加-append "root=/dev/sda console=ttyS0"
到您的 QEMU 参数中,但是(据我所知)虽然它需要您从 ISO 中提取内核和 initram(这应该很容易安装和复制/粘贴正确的文件)但它也希望您已经安装了系统/dev/sda
(这是我试图引导的)。
此时我不知道接下来要搜索什么,如何在当前终端中获取完整的终端会话,而不仅仅是在我的显示器中?
解决方案
在这种情况下,就像@Peter Maydell评论的那样;这不是 QEMU 问题。QEMU 正在做它应该做的事,但 Arch 不得不被告知使用串行控制台作为它的主要通信方式。
如何做到这一点的两个示例
通过控制台 bash
pipe_dir="$(mktemp -d)"
mkfifo "${pipe_dir}/pipe.in" "${pipe_dir}/pipe.out"
function cleanup {
rm -rfv "${pipe_dir}"
}
trap cleanup EXIT
qemu-system-x86_64 \
-m 8G \
-display none \
-serial stdio \
-drive file=./out/linux.iso,index=0,media=cdrom \
-drive file=./out/main.img,if=virtio &
sleep 2s
printf "\t" > "${pipe_dir}/pipe.in"
sleep 2s
printf " console=ttyS0,115200" > "${pipe_dir}/pipe.in"
sleep 2s
echo > "${pipe_dir}/pipe.in"
# Whatever other interactions you want go here...
wait
期望通过控制台
set timeout -1
spawn qemu-system-x86_64 \
-m 8G \
-display none \
-serial stdio \
-drive file=./out/linux.iso,index=0,media=cdrom \
-drive file=./out/main.img,if=virtio
sleep 1
send \t
sleep 1
send " console=ttyS0,115200"
sleep 1
send \n
理论上这应该没问题,但实际上我仍然很难与控制台交互并发送字符以正确登录。我确信我的用户错误可能比没有更多。
一个更好的解决方案(再次与 Arch 而不是 QEMU 的上下文相关)是使用包含我的 SSH 公钥的 cloud-init 脚本。与 VM 的交互稳定、可靠且易于重现。
使用 cloud-init/ssh 进行 bash
$ touch ./out/meta-data
$ cat > ./out/user-data <<EOF
#cloud-config
users:
- name: root
ssh_authorized_keys:
- $(cat ${HOME}/.ssh/id_ed25519.pub)
EOF
$ xorriso -as genisoimage -output ./out/cloud-init.iso \
-volid CIDATA -joliet -rock ./out/meta-data ./out/user-data
$ qemu-system-x86_64 \
-m 8G \
-drive file=./out/linux.iso,index=0,media=cdrom \
-drive file=./out/cloud-init.iso,index=1,media=cdrom \
-drive file=./out/main.img,if=virtio \
-net user,hostfwd=tcp::10022-:22 \
-net nic &
$ function qemu-ssh {
ssh -q -o ConnectTimeout=5 -o StrictHostKeyChecking=no -o "UserKnownHostsFile /dev/null" -p 10022 root@localhost ${@}
}
$ printf 'Waiting for SSH to go live (this will take a while)...'
$ until qemu-ssh exit; do
printf '.'
done
# This convenience function starts an interactive
# session when supplied with no additional arguments
# but your automation can go here
$ qemu-ssh
推荐阅读
- azure - 如何限制服务原则访问 ADLS Gen2 中的特定文件夹?
- firebase - 将 ghostscript 与 firebase 云功能一起使用时产生 EACCES 错误
- javascript - 减少数组以从左到右删除重复的 matchId 条目
- jenkins - Jenkins Pipeline 作业以获取另一个 jenkins 作业构建状态
- python - 将键映射到字典熊猫中的多个值
- wordpress - 使用 Wordpress 本机类 VS 使用 AWS Lambda 调整图像大小
- react-native - 更改 FlatList 的 numColumns 将方向变为水平
- php - Laravel 7 验证是否支持验证 Authorization 标头中的值?
- bash - 匹配 CSV 的第 1 列,然后检查第 2 列是否匹配
- c# - 为什么我不能让这个 Microsoft Store 代码片段工作?