在 Linux 下使用 QEMU/KVM 优雅运行与自动化测试 Windows 虚拟机
在跨平台底层开发(如网络透明代理、Wintun 虚拟网卡、文件系统或驱动开发)过程中,常常需要在 Linux 宿主机上对 Windows 平台做持续构建、测试与端到端验证。
传统的桌面虚拟化工具(如 VMware Workstation、VirtualBox)存在以下痛点:
- 开销过大:默认 Windows 10/11 开机动辄占用 3.5GB+ 内存,后台大量的遥测与 Defender 扫描吃满 CPU 与磁盘 I/O。
- 难以自动化:依赖 GUI 手动点击,难以与 Linux 终端开发流或 CI/CD 脚本无缝串联。
- 环境污染:测试过程可能会修改系统注册表、驱动、路由表,一旦崩溃需要反复手动快照恢复。
本文总结了一套极简、轻量、无感远程控制的工程实践方案。
一、镜像选型:避免深坑,拥抱轻量
在测试底层系统/网络功能时,切勿盲目选用社区过度阉割版(如 Tiny10/Tiny11),它们常常移除了必要的数字证书链、NDIS 驱动子系统或 Winsock 高级 API,导致难以排查究竟是代码 Bug 还是系统被剪坏。
- 推荐首选:Windows 10 IoT Enterprise LTSC 2021
- 微软官方长期支持版本(10 年支持)。
- 原生极度纯净:无 Cortana、无应用商店垃圾、无 Edge 捆绑推送、无 Xbox 服务。
- 网络与驱动栈完整:100% 完整支持 VirtIO、Wintun、IP Helper API、Winsock。
- 开机内存仅约 1.2GB ~ 1.4GB,干净安装仅占 9.4GB 磁盘空间。
二、QEMU/KVM 极简启动与安装配置
使用 libvirt 与 virt-install 工具快速初始化一台开箱即用的测试虚拟机。
1. 准备工作
下载官方镜像以及 Red Hat 官方发布的 Windows VirtIO 驱动光盘:
# VirtIO 官方驱动光盘(包含网卡、SCSI 磁盘控制器、Balloon 内存气球驱动和 Guest Agent)
wget https://fedorapeople.org/groups/virt/virtio-win/direct-downloads/stable-virtio/virtio-win.iso
2. 一键创建虚拟机配置
重点配置:
- 磁盘总线:采用
virtio总线(性能远超 IDE/SATA 模拟)。 - 通信通道:挂载名为
org.qemu.guest_agent.0的虚拟串口,这是宿主机静默控制虚拟机的核心桥梁。
virt-install \
--connect qemu:///system \
--name win10-ltsc \
--memory 4096 \
--vcpus 4 \
--os-variant win10 \
--cdrom /path/to/en-us_windows_10_iot_enterprise_ltsc_2021_x64_dvd.iso \
--disk /path/to/virtio-win.iso,device=cdrom,bus=sata \
--disk size=25,format=qcow2,bus=virtio \
--network network=default,model=virtio \
--graphics spice,listen=127.0.0.1 \
--channel spicevmc,target_type=virtio,name=com.redhat.spice.0 \
--channel unix,target_type=virtio,name=org.qemu.guest_agent.0 \
--noautoconsole
3. 安装过程加载 VirtIO 磁盘驱动
在 Windows 安装界面的“选择安装驱动器”步骤中,因使用了 VirtIO 总线,需手动加载驱动:
- 点击 Load driver -> Browse。
- 选中挂载的光驱:
virtio-win->viostor->w10->amd64。 - 点击确定,即可识别出 25GB 的 VirtIO 虚拟硬盘并继续安装。
三、系统内装机后优化:极致减负与激活
进入桌面后,打开光驱 virtio-win:
- 进入
guest-agent目录,双击安装qemu-ga-x86_64.msi(启动宿主机控制通道)。 - 安装完成后,即可彻底关闭图形窗口,剩下的所有优化全部由宿主机在终端一条命令完成!
1. 永久激活系统(HWID 数字权利)
通过开源标准激活工具执行数字权利永久授权:
irm https://get.activated.win | iex
(选择 1 即可一键完成数字许可证永久激活)
2. 榨干系统性能:禁用 Defender 扫描与耗能后台服务
Windows Defender 对本地编译、写日志和频繁创建进程有明显的锁与扫描开销。通过系统管理命令彻底关闭非必要的后台服务:
# 1. 关闭 Defender 实时监控与样本上报 (提高 I/O 与进程创建效率 30% 以上)
Set-MpPreference -DisableRealtimeMonitoring $true -ErrorAction SilentlyContinue
Set-MpPreference -DisableBehaviorMonitoring $true -ErrorAction SilentlyContinue
Set-MpPreference -DisableBlockAtFirstSeen $true -ErrorAction SilentlyContinue
Set-MpPreference -DisableIOAVProtection $true -ErrorAction SilentlyContinue
Set-MpPreference -DisableScriptScanning $true -ErrorAction SilentlyContinue
Set-MpPreference -SubmitSamplesConsent 2 -ErrorAction SilentlyContinue
# 2. 停用并禁用无用的后台耗能服务
$services = @("wuauserv", "WSearch", "SysMain", "DiagTrack", "Spooler", "MapsBroker")
foreach ($s in $services) {
Stop-Service -Name $s -Force -ErrorAction SilentlyContinue
Set-Service -Name $s -StartupType Disabled -ErrorAction SilentlyContinue
}
经过优化后,虚拟机日常开机空闲内存维持在 1.36 GB,CPU 占用率稳定在 0%。
四、全自动化控制利器:基于 QEMU Guest Agent 的无感脚本执行
在 Linux 下测试 Windows 程序,无需配置繁琐的 SSH 服务或暴露 RDP 端口。通过 QEMU 的内置通道,可以直接下发 PowerShell 指令并取回输出。
编写宿主机控制脚本 scripts/win_exec.py:
#!/usr/bin/env python3
import subprocess
import json
import base64
import time
import sys
import os
DEFAULT_VM = os.environ.get("VM", "win10-ltsc")
def qemu_agent(cmd_dict, vm=None):
if vm is None:
vm = DEFAULT_VM
cmd = ["virsh", "-c", "qemu:///system", "qemu-agent-command", vm, json.dumps(cmd_dict)]
p = subprocess.run(cmd, capture_output=True, text=True)
if p.returncode != 0:
raise RuntimeError(f"virsh error: {p.stderr.strip()}")
return json.loads(p.stdout)
def run_powershell(ps_command, timeout=30):
# 使用 UTF-16LE + Base64 编码,避免特殊字符转义错误
encoded = base64.b64encode(ps_command.encode('utf-16le')).decode('ascii')
payload = {
"execute": "guest-exec",
"arguments": {
"path": "powershell.exe",
"arg": ["-NoProfile", "-NonInteractive", "-EncodedCommand", encoded],
"capture-output": True
}
}
res = qemu_agent(payload)
pid = res.get("return", {}).get("pid")
if not pid:
raise RuntimeError(f"Failed to exec: {res}")
# 轮询进程执行状态
start_time = time.time()
while time.time() - start_time < timeout:
status = qemu_agent({"execute": "guest-exec-status", "arguments": {"pid": pid}})
ret = status.get("return", {})
if ret.get("exited", False):
exitcode = ret.get("exitcode", 0)
out = base64.b64decode(ret.get("out-data", "")).decode("utf-8", errors="replace")
err = base64.b64decode(ret.get("err-data", "")).decode("utf-8", errors="replace")
return exitcode, out, err
time.sleep(0.5)
raise TimeoutError("Execution timed out")
if __name__ == "__main__":
if len(sys.argv) < 2:
print("Usage: win_exec.py '<powershell command>'")
sys.exit(1)
cmd_str = sys.argv[1]
code, out, err = run_powershell(cmd_str)
if out:
print(out, end="")
if err:
print(f"STDERR: {err}", file=sys.stderr, end="")
sys.exit(code)
使用方式:
# 检查虚拟机进程
python3 scripts/win_exec.py 'Get-Process'
# 检查内存与系统版本
python3 scripts/win_exec.py 'Get-CimInstance Win32_OperatingSystem | Select-Object TotalVisibleMemorySize, FreePhysicalMemory'
# 下发测试用例并验证返回码
python3 scripts/win_exec.py 'curl.exe -I https://www.google.com'
五、高效测试的“终极姿态”:QCOW2 差分快照秒级还原
进行网络底层修改、驱动安装或破坏性测试时,最优雅的实践是写时复制(Copy-on-Write)差分盘:
制作基础盘(Golden Image): 将已安装好 VirtIO 驱动、Guest Agent、优化完的镜像固化:
virsh shutdown win10-ltsc # 标记为只读基础盘 chmod 444 /var/lib/libvirt/images/win10-ltsc-golden.qcow2为每次测试生成秒级派生盘:
qemu-img create -f qcow2 -b /var/lib/libvirt/images/win10-ltsc-golden.qcow2 \ -F qcow2 /tmp/win10-ephemeral-test.qcow2测试完毕即丢弃: 无论系统内部注册表、驱动、路由被修改成什么样,直接删除
/tmp/win10-ephemeral-test.qcow2。永远不需要费时费力执行“卸载”或“逆向清理”,从源头上保障 100% 幂等与纯净!