QEMU 虚拟化完全指南 / 09 - QEMU Guest Agent
09 - QEMU Guest Agent
掌握 QEMU Guest Agent(QGA)的安装、配置与使用,实现宿主机与虚拟机之间的自动化通信与管理。
9.1 Guest Agent 概述
QEMU Guest Agent(qemu-ga) 是运行在虚拟机内部的守护进程,通过 virtio 串口通道与宿主机上的 QEMU 进程通信,实现宿主机对虚拟机的管理操作。
Guest Agent 通信架构:
┌─────────────────────────────────────────────┐
│ 宿主机 (Host) │
│ │
│ QEMU Process │
│ ┌───────────────────────┐ │
│ │ virtio-serial 通道 │◄── QMP 命令 │
│ └───────────┬───────────┘ │
│ │ (virtio) │
├───────────────┼─────────────────────────────┤
│ │ (虚拟机内) │
│ ┌───────────┴───────────┐ │
│ │ qemu-ga (Guest Agent)│ │
│ │ 监听 virtio 串口 │ │
│ └───────────────────────┘ │
│ 虚拟机 (Guest) │
└─────────────────────────────────────────────┘
功能清单
| 功能 | 说明 | Linux | Windows |
|---|---|---|---|
| 文件系统冻结 | fsfreeze,保证快照一致性 | ✅ | ✅ (VSS) |
| 文件系统解冻 | fsthaw | ✅ | ✅ |
| 获取文件系统信息 | guest-get-fsinfo | ✅ | ✅ |
| 获取主机名 | guest-get-host-name | ✅ | ✅ |
| 获取 OS 信息 | guest-get-osinfo | ✅ | ✅ |
| 获取网络信息 | guest-network-get-interfaces | ✅ | ✅ |
| 获取时间 | guest-get-time | ✅ | ✅ |
| 设置时间 | guest-set-time | ✅ | ✅ |
| 执行命令 | guest-exec / guest-exec-status | ✅ | ✅ |
| 文件读写 | guest-file-open/read/write/close | ✅ | ✅ |
| 用户管理 | guest-*/passwd | ✅ | ❌ |
| 挂起/休眠 | guest-suspend-ram/disk/hybrid | ✅ | ✅ |
| 获取内存块信息 | guest-get-memory-blocks | ✅ | ❌ |
9.2 在 Linux 虚拟机中安装
Debian / Ubuntu
# 安装
sudo apt install qemu-guest-agent
# 启动并启用
sudo systemctl enable --now qemu-guest-agent
# 查看状态
sudo systemctl status qemu-guest-agent
Fedora / CentOS / RHEL
# 安装
sudo dnf install qemu-guest-agent
# 启动并启用
sudo systemctl enable --now qemu-guest-agent
Arch Linux
# 安装
sudo pacman -S qemu-guest-agent
# 启动
sudo systemctl enable --now qemu-guest-agent
cloud-init 自动安装
# user-data
#cloud-config
packages:
- qemu-guest-agent
runcmd:
- systemctl enable qemu-guest-agent
- systemctl start qemu-guest-agent
9.3 在 Windows 虚拟机中安装
下载 virtio-win 驱动
# 在宿主机下载 virtio-win ISO
wget https://fedorapeople.org/groups/virt/virtio-win/direct-downloads/stable-virtio/virtio-win.iso
# 在虚拟机中挂载
# 如果是 libvirt 管理的虚拟机
virsh attach-disk windows-vm /path/to/virtio-win.iso hdc --type cdrom --mode readonly
Windows 中安装
- 打开虚拟机的光驱,找到
guest-agent/qemu-ga-x86_64.msi - 双击运行安装
- 安装完成后,服务
QEMU Guest Agent会自动启动
# PowerShell 中检查服务状态
Get-Service QEMU-GA
# 如果服务未启动
Start-Service QEMU-GA
Set-Service QEMU-GA -StartupType Automatic
9.4 QEMU 配置 Guest Agent 通道
使用命令行
qemu-system-x86_64 \
-enable-kvm -cpu host -m 4G \
-drive file=vm.qcow2,format=qcow2 \
-chardev socket,path=/tmp/qga.sock,server=on,wait=off,id=qga0 \
-device virtio-serial \
-device virtserialport,chardev=qga0,name=org.qemu.guest_agent.0
使用 libvirt XML
<domain type='kvm'>
...
<devices>
<!-- virtio 串口设备 -->
<controller type='virtio-serial' index='0'/>
<!-- Guest Agent 通道 -->
<channel type='unix'>
<source mode='bind' path='/var/lib/libvirt/qemu/ubuntu-vm.agent'/>
<target type='virtio' name='org.qemu.guest_agent.0'/>
<address type='virtio-serial' controller='0' bus='0' port='1'/>
</channel>
</devices>
</domain>
# 更新虚拟机配置
virsh define ubuntu-vm.xml
virsh shutdown ubuntu-vm
virsh start ubuntu-vm
9.5 通过 QMP 使用 Guest Agent
基本交互
# 连接到 QMP socket
# 方式 1: 使用 socat
echo '{"execute":"qmp_capabilities"}' | socat - UNIX-CONNECT:/var/lib/libvirt/qemu/ubuntu-vm.monitor
# 方式 2: 使用 virsh qemu-agent-command
virsh qemu-agent-command ubuntu-vm '{"execute":"guest-info"}'
常用命令
# 获取客户机信息
virsh qemu-agent-command ubuntu-vm '{"execute":"guest-info"}'
# 获取主机名
virsh qemu-agent-command ubuntu-vm '{"execute":"guest-get-host-name"}'
# 获取操作系统信息
virsh qemu-agent-command ubuntu-vm '{"execute":"guest-get-osinfo"}'
# 获取网络接口信息
virsh qemu-agent-command ubuntu-vm '{"execute":"guest-network-get-interfaces"}'
# 获取时间
virsh qemu-agent-command ubuntu-vm '{"execute":"guest-get-time"}'
# 设置时间(同步到宿主机时钟)
virsh qemu-agent-command ubuntu-vm '{"execute":"guest-set-time"}'
# 获取文件系统信息
virsh qemu-agent-command ubuntu-vm '{"execute":"guest-get-fsinfo"}'
9.6 文件系统冻结(fsfreeze)
冻结与解冻
# 冻结文件系统(确保快照一致性)
virsh qemu-agent-command ubuntu-vm '{"execute":"guest-fsfreeze-freeze"}'
# 查看冻结状态
virsh qemu-agent-command ubuntu-vm '{"execute":"guest-fsfreeze-status"}'
# 解冻文件系统
virsh qemu-agent-command ubuntu-vm '{"execute":"guest-fsfreeze-thaw"}'
快照前自动冻结
#!/bin/bash
# snapshot-with-freeze.sh
VM_NAME="ubuntu-vm"
SNAP_NAME="consistent-snap-$(date +%Y%m%d)"
# 1. 冻结文件系统
echo "冻结文件系统..."
virsh qemu-agent-command ${VM_NAME} '{"execute":"guest-fsfreeze-freeze"}' --timeout 30
# 2. 创建快照
echo "创建快照..."
virsh snapshot-create-as ${VM_NAME} ${SNAP_NAME} --atomic
# 3. 解冻文件系统
echo "解冻文件系统..."
virsh qemu-agent-command ${VM_NAME} '{"execute":"guest-fsfreeze-thaw"}' --timeout 30
echo "一致性快照创建完成: ${SNAP_NAME}"
9.7 远程命令执行
在虚拟机中执行命令
# 执行命令(异步)
result=$(virsh qemu-agent-command ubuntu-vm \
'{"execute":"guest-exec","arguments":{"path":"/bin/hostname","arg":[],"capture-output":true}}')
# 获取进程 PID
pid=$(echo $result | jq -r '.return.pid')
# 获取执行结果
virsh qemu-agent-command ubuntu-vm \
"{\"execute\":\"guest-exec-status\",\"arguments\":{\"pid\":${pid}}}"
实用命令示例
# 获取磁盘使用情况
virsh qemu-agent-command ubuntu-vm \
'{"execute":"guest-exec","arguments":{"path":"/bin/df","arg":["-h"],"capture-output":true}}'
# 获取系统负载
virsh qemu-agent-command ubuntu-vm \
'{"execute":"guest-exec","arguments":{"path":"/usr/bin/uptime","capture-output":true}}'
# 获取进程列表
virsh qemu-agent-command ubuntu-vm \
'{"execute":"guest-exec","arguments":{"path":"/bin/ps","arg":["aux"],"capture-output":true}}'
# 更新系统(谨慎使用)
virsh qemu-agent-command ubuntu-vm \
'{"execute":"guest-exec","arguments":{"path":"/usr/bin/apt","arg":["update"],"capture-output":true}}'
9.8 文件操作
读取文件
# 打开文件
result=$(virsh qemu-agent-command ubuntu-vm \
'{"execute":"guest-file-open","arguments":{"path":"/etc/hostname","mode":"r"}}')
fd=$(echo $result | jq -r '.return')
# 读取内容
virsh qemu-agent-command ubuntu-vm \
"{\"execute\":\"guest-file-read\",\"arguments\":{\"handle\":${fd},\"count\":1024}}"
# 关闭文件
virsh qemu-agent-command ubuntu-vm \
"{\"execute\":\"guest-file-close\",\"arguments\":{\"handle\":${fd}}}"
写入文件
# 打开文件(写入模式)
result=$(virsh qemu-agent-command ubuntu-vm \
'{"execute":"guest-file-open","arguments":{"path":"/tmp/test.txt","mode":"w+"}}')
fd=$(echo $result | jq -r '.return')
# 写入内容(base64 编码)
content=$(echo -n "Hello from host" | base64)
virsh qemu-agent-command ubuntu-vm \
"{\"execute\":\"guest-file-write\",\"arguments\":{\"handle\":${fd},\"buf-b64\":\"${content}\"}}"
# 关闭文件
virsh qemu-agent-command ubuntu-vm \
"{\"execute\":\"guest-file-close\",\"arguments\":{\"handle\":${fd}}}"
9.9 VSS(Volume Shadow Copy Service)- Windows
Windows 虚拟机使用 VSS 实现文件系统冻结的一致性:
VSS 工作原理
Windows VSS 冻结流程:
1. qemu-ga 发送冻结请求
2. VSS 通知所有 VSS Writer 应用程序
3. 应用程序完成内存数据刷盘
4. VSS 创建卷影副本
5. qemu-ga 返回冻结成功
6. 宿主机创建快照
7. qemu-ga 发送解冻请求
8. VSS 释放卷影副本
验证 VSS 支持
# 在 Windows 虚拟机中
vssadmin list writers
9.10 自动化运维脚本
批量管理脚本
#!/bin/bash
# qga-batch-ops.sh - 批量通过 Guest Agent 管理虚拟机
VM_LIST="vm1 vm2 vm3 vm4"
COMMAND="$1"
for VM in ${VM_LIST}; do
echo "=== ${VM} ==="
case "${COMMAND}" in
info)
virsh qemu-agent-command ${VM} '{"execute":"guest-get-host-name"}' 2>/dev/null
;;
network)
virsh qemu-agent-command ${VM} '{"execute":"guest-network-get-interfaces"}' 2>/dev/null
;;
update)
virsh qemu-agent-command ${VM} \
'{"execute":"guest-exec","arguments":{"path":"/usr/bin/apt","arg":["update"],"capture-output":true}}' 2>/dev/null
;;
reboot)
virsh qemu-agent-command ${VM} \
'{"execute":"guest-exec","arguments":{"path":"/sbin/reboot","arg":[]}}' 2>/dev/null
;;
*)
echo "用法: $0 {info|network|update|reboot}"
exit 1
;;
esac
echo ""
done
9.11 故障排查
| 问题 | 原因 | 解决方案 |
|---|---|---|
| Agent 无响应 | 服务未启动 | 检查 systemctl status qemu-guest-agent |
| 通道未建立 | XML 中未配置 channel | 添加 virtio-serial 和 channel 定义 |
| 命令超时 | 虚拟机负载过高 | 增加 –timeout 参数 |
| 冻结失败 | 文件系统正在使用 | 确认没有大文件写入操作 |
| Windows 安装失败 | virtio 驱动版本不匹配 | 使用与 QEMU 版本匹配的 virtio-win |
# 检查通道是否建立
virsh domiflist ubuntu-vm
virsh dumpxml ubuntu-vm | grep -A5 channel
# 测试 Agent 通信
virsh qemu-agent-command ubuntu-vm '{"execute":"guest-ping"}'
# 查看 Agent 日志
# Linux
journalctl -u qemu-guest-agent
要点回顾
| 要点 | 核心内容 |
|---|---|
| Guest Agent | 宿主机通过 virtio 串口与虚拟机内部通信 |
| fsfreeze | 冻结文件系统确保快照一致性 |
| guest-exec | 在虚拟机内远程执行命令 |
| 文件操作 | 可以读写虚拟机内的文件 |
| VSS | Windows 使用 VSS 实现一致性快照 |
注意事项
安全风险: guest-exec 允许在虚拟机内执行任意命令,应限制 QMP socket 的访问权限。
Agent 版本: Guest Agent 版本应与 QEMU 版本匹配,否则可能出现命令不支持的问题。
通道名称: Guest Agent 通道名称必须是
org.qemu.guest_agent.0,否则无法正常工作。
扩展阅读
下一步
→ 10 - 设备直通:学习 VFIO、PCI/GPU/NVMe/USB 设备直通配置。