QEMU 串行标准输出在 archlinux 客户机上发散

Posted

技术标签:

【中文标题】QEMU 串行标准输出在 archlinux 客户机上发散【英文标题】:QEMU serial std output diverges on archlinux guest 【发布时间】:2021-11-03 06:20:13 【问题描述】:

我正在尝试在 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 上安装了系统(这是我试图引导的)。

此时我不知道接下来要搜索什么,如何在当前终端中获取完整的终端会话,而不仅仅是在我的显示器中?

【问题讨论】:

这是一个 archlinux 问题,而不是 QEMU 问题,我认为——如果你知道它们,你可能想要添加一些相关标签。您需要了解如何让 archlinux 安装程序在串行端口上运行(如果您在真实硬件上运行安装程序,这将与您执行此操作的方式相同)。 【参考方案1】:

在这种情况下,就像@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 的交互稳定、可靠且易于重现。

bash 与 cloud-init/ssh
$ 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 

【讨论】:

以上是关于QEMU 串行标准输出在 archlinux 客户机上发散的主要内容,如果未能解决你的问题,请参考以下文章

怎么有aarch64的ubuntu呢

ArchLinux 下文件描述符

Linux 上的串行通信连接

裸金属树莓派2:为QEMU仿真生成SD卡图像

[c]解析类RFC2217协议

串行化