把 macOS 10 塞进 Ubuntu 24.04 LTS 的 KVM 环境里,这事一听就有点折腾,但我实际跑下来之后觉得,真正能把人劝退的其实不是命令,而是对原理的误解。很多人以为装虚拟机就是把 ISO 挂上去点启动,但 macOS 不是 Windows,它不会老老实实出现在 Linux 的 libvirt 列表里让你一键完成,你需要先搞清楚 KVM、QEMU、OpenCore、OVMF 这几个角色各干什么,还要接受“装完只是开端”这个事实。这篇内容就是一套比较完整的拓展记录,适合想用 Linux 宿主机跑 macOS 10 系列虚拟机的人,不管你是为了跑某个旧版软件、做渲染测试,还是折腾 UI 自动化,都能照着我这套流程少走一圈弯路。
我这里说的 macOS 10,指的不是具体某个小版本,而是以 10.15、10.14 这一批较老系统为代表。选择老版本不是因为它最好,而是因为很多生产链条里的软件只认老系统,或者你手里的机器性能不足以流畅跑新版本。后文所有步骤都按 Ubuntu 24.04 LTS 宿主来写,如果读者用的是 22.04 或者其他 Debian 系,原理一致,只是包名和路径需要微调。
1. 这个拓展项目到底解决了什么问题
1.1 为什么是 Ubuntu 24.04 LTS + KVM 这套组合
在实际工作中,同一个项目可能需要在 macOS、Windows、Linux 三个环境里做兼容性验证,但团队不可能为每个成员配一台实体 macOS 设备。用一台 Linux 服务器或工作站跑多个桌面虚拟机,是成本最低、复用性最高的方案。Ubuntu 24.04 LTS 本身对 KVM 的支持非常成熟,内核 6.8 自带的 KVM 模块几乎没有兼容性问题,整条链路从 OVMF 到 virtio 都有官方包维护。相比在 Docker 里折腾 macOS 容器,或者用模拟器硬啃 ARM 镜像,KVM 方案是唯一兼顾速度与完整度的选择。
有人会问:为什么不用 VirtualBox?VirtualBox 对新版 macOS 的 UEFI 支持一直不稳定,GPU 加速也基本谈不上。KVM 的优势在于直接复用了 Linux 内核的虚拟化模块,虚拟机里的 CPU 指令大部分是本机执行,损耗小得多。配合 QEMU 模拟出来的整套硬件,可以做到启动快、响应跟手、磁盘操作接近原生。
1.2 跑旧版 macOS 10 的真实应用场景
有人跑 macOS 10 是为了验证自家 Web 网站在 Safari 老版本下的表现,有人是为了跑某个已经停止更新但业务还依赖的桌面客户端,还有人是给 iOS 开发做 UI 自动化测试的辅助系统。老版本 macOS 对硬件要求低,虚拟化环境里更容易稳定复现,而且占用的磁盘和内存比新版小。我在实际操作中最常用到的是 macOS 10.15 环境,因为不少压测工具和签名脚本在新系统上已经被系统安全策略限制,只有旧系统还能正常跑。
这个项目定位是“拓展”,意思是首先你已经理解了虚拟机的基本操作,知道什么是 CPU 穿透、什么是 UEFI 固件、怎么管理磁盘镜像。在此基础上,我们才需要去处理 macOS 特有的三个问题:第一,macOS 只认特定的 SMBIOS 和 ACPI 信息;第二,macOS 的安装流程不像 Linux 发行版那样接受通用启动器;第三,macOS 默认不带 virtio 驱动,所以网卡、磁盘控制器要选它能认得的型号。把这三点打通,虚拟机基本能成一个日常可用的环境。
2. 动手前先自检:硬件、BIOS 与宿主机准备
2.1 硬件底线与虚拟化开启检查
开始之前先看宿主机条件。CPU 必须有硬件虚拟化扩展,Intel 平台是 VT-x,AMD 平台是 SVM。大多数近十年的桌面 CPU 都支持,问题往往出在主板的默认设置上。BIOS 里的 Intel VT-d 或 AMD IOMMU 如果没开,后期做显卡直通时会碰壁;如果只是跑纯软件模拟显示,那只需要开 VT-x 或 SVM 就够了。
可以用下面这条命令快速检查 CPU 支持情况:
grep -E -c '(vmx|svm)' /proc/cpuinfo输出数字大于等于 1 说明 CPU 有虚拟化标志。如果输出是 0,可能需要进 BIOS 打开相关选项,有些主板在默认状态会关掉虚拟化。开机时按 Del 或 F2 进入设置界面,一般能在 CPU Configuration 或 Advanced 页面找到Intel Virtualization Technology或SVM Mode,设成 Enabled 保存重启。这一步不做后面一切免谈。
内存建议至少 16GB,因为 macOS 虚拟机本身给 8GB 体验才正常,宿主机还得剩一部分给系统和文件缓存。磁盘方面,如果打算长期保留这个环境,并且经常跑构建任务,最好准备 256GB 以上的空闲空间。虽然磁盘镜像是 qcow2 动态增长,但装上系统、常用软件、缓存之后,60GB 镜像用掉一半以上是很正常的事。
2.2 安装 qemu、ovmf 和其他工具
Ubuntu 24.04 的软件源里已经打包好了虚拟化相关的全套工具,不需要从源码编译。执行下面命令:
sudo apt update sudo apt install qemu-system-x86 qemu-utils ovmf mtoolsqemu-system-x86负责运行 x86 虚拟机,qemu-utils提供磁盘镜像制作和转换命令,ovmf是 UEFI 固件,没有它 macOS 根本没法启动。mtools主要是方便操作 FAT 格式镜像,个别工作流里会用到。安装完成后验证 OVMF 固件路径:
ls /usr/share/OVMF/正常应该能看到OVMF_CODE_4M.fd和OVMF_VARS_4M.fd。这两个文件分别代表 UEFI 代码和 UEFI 变量存储,前者只读,后者需要为每个虚拟机复制一份单独使用。就这么个小细节,我见过不少人忽略,直接在原始 VARS 文件上写配置,结果启动一次就把全局固件写坏了。
libvirt 和 virt-manager 也可以顺手装,它们不是必须,但能在排查阶段帮你看 CPU 拓扑、PCI 设备直通和存储池状态。不过不要把 virt-manager 当成主操作入口,macOS 虚拟机还是用命令行启动脚本更可控,因为很多运行参数在图形界面里会绕弯。
3. 理解这几个关键角色,调起参数才有底
3.1 KVM 和 QEMU 的分工
KVM 是内核模块,负责在硬件层面做 CPU 和内存的虚拟化;QEMU 是用户态软件,负责模拟设备,比如磁盘、网卡、USB 控制器、显示输出。两者配合时,CPU 指令基本跑到本机硬件上,但硬盘和网络读写仍然要经过 QEMU 的设备模型。这有点像开连锁店:KVM 是物业,提供场地和水电;QEMU 是店长,负责把所有员工和设备安排到位。
对 macOS 来说,CPU 穿透的可靠性直接决定安装过程会不会莫名其妙报错。启动参数里的-cpu host意思是把宿主机的 CPU 特性尽数暴露给虚拟机,这样性能最好,但也把宿主机 CPU 的新特性带进去了。macOS 10 系列对某些新指令集并不了解,尤其是 AVX-512 这类,反而可能触发随机崩溃。所以比较稳妥的做法是-cpu host再补一组 hv 开头的 Hyper-V 同步参数,告诉 macOS 它自己是跑在虚拟机里,时钟源和中断处理就不容易乱。
3.2 OpenCore 在整套方案里的位置
OpenCore 本来是为实体安装 macOS 设计的引导环境,但在虚拟机里它同样能解决一个大问题:让 macOS 认为自己运行在被支持的硬件上。它会在启动早期注入 SMBIOS 数据、ACPI 补丁和内核参数,拦截掉那些版本不符、品牌不符、特征不符的报错。
你可以把 OpenCore 理解为给 macOS 发了一张“临时通行证”,但它不负责破解任何系统功能,它只是把软件需要的设备信息伪装成 macOS 能接受的样子。在 QEMU 里我们通过把 OpenCore 作为 EFI 启动项放入 OVMF 环境,开机进入选择界面后,再从遗留的恢复分区或安装器镜像继续引导。
处理 OpenCore 配置时最关键的几个点分别是机型标识、启动参数、补丁注入和引导顺序。纯命令行方式不需要自己编译 EFI 文件,可以直接使用社区维护的 OpenCore 镜像,把它放在一个 FAT 格式的小镜像里,再作为第一块硬盘让 QEMU 引导。只要引导镜像里的 config 文件没问题,剩下的系统安装就跟普通 macOS 流程没有区别。
3.3 芯片组、显示和存储控制器的选型逻辑
QEMU 提供了多种芯片组可选,-machine q35在 macOS 虚拟化里几乎是标配。q35 芯片组支持 PCIe、支持更现代的 ACPI 表,对 macOS 10.14 及以后版本的兼容性比 i440fx 好得多。i440fx 虽然更简单,但很多新 macOS 版本对 ACPI 表要求更严格,会出现卡在安装进度条半路的情况。
显示设备方面,macOS 没有为 QEMU 的 virtio-gpu 提供驱动,最保险的是-vga std,它模拟的是一块标准 VGA 显卡,macOS 自带驱动能识别,虽然分辨率不高,但足够完成整个安装流程。后面想要高分辨率或硬件加速,就得走 PCIE 显卡直通,这个放在第 5 节细说。存储控制器则不要用 virtio-blk,虽然它性能好,但 macOS 默认不认识,安装阶段会直接提示找不到磁盘。用 Q35 芯片组默认的 AHCI 控制器,或者用-drive if=ide这种传统挂载方式,反而能让安装器立刻识别到盘。
4. 完整实操:从磁盘镜像到 macOS 安装完成
4.1 准备目录、OVMF 副本和磁盘镜像
我习惯给每个虚拟机单独建一个目录,比如~/vm/macos10,避免多个虚拟机的变量文件互相污染。在该目录下先建好磁盘镜像和固件副本:
mkdir -p ~/vm/macos10 cd ~/vm/macos10 cp /usr/share/OVMF/OVMF_VARS_4M.fd ./OVMF_VARS.fd qemu-img create -f qcow2 macos_disk.qcow2 80G80G 的 qcow2 文件刚创建时只有几百 KB,它会在使用的过程中逐渐膨胀,所以不用担心一开始就占满磁盘。建议把镜像大小定得稍微宽松一点,因为 macOS 装完系统加常见开发工具很容易超过 40GB,后期扩容虽然也能做,但操作起来比刚开始就建大要麻烦。
安装介质这里需要单独说明。我使用的是恢复模式镜像,它本身不包含完整系统,而是通过网络恢复组件拉取安装器。在 QEMU 里把这个恢复镜像挂到 USB 或 SATA 接口,OpenCore 会在启动菜单里识别到对应的恢复卷。如果你拿到的是完整的安装镜像,也可以直接挂成光驱,步骤会更直观。整个安装过程的介质合法性需要你自己把控,我这边不做任何来源推荐,只讲技术流程。
4.2 写一条能用的 QEMU 启动脚本
这应该是整篇内容里最容易被抄错的部分。QEMU 参数顺序并不特别严格,但每个参数的取值会直接决定虚拟机能不能亮屏、能不能进安装器。我贴一下我这边实际在用的启动脚本,参数已经减到最少,适合第一次跑通:
#!/bin/bash cd ~/vm/macos10 qemu-system-x86_64 \ -machine q35,accel=kvm \ -cpu host,hv_relaxed,hv_spinlocks=0xffff,hv_vapic,hv_time \ -smp 4,sockets=1,cores=4,threads=1 \ -m 8192 \ -drive if=pflash,format=raw,readonly=on,file=/usr/share/OVMF/OVMF_CODE_4M.fd \ -drive if=pflash,format=raw,file=./OVMF_VARS.fd \ -device qemu-xhci,id=usb \ -device usb-kbd \ -device usb-mouse \ -netdev user,id=net0 \ -device e1000e,netdev=net0 \ -hda macos_disk.qcow2 \ -vga std \ -display gtk这里的-smp 4表示 4 核,-m 8192表示 8GB 内存。需要注意的是,如果宿主机内存只有 16GB,开 8GB 给虚拟机还同时跑一堆容器,会明显卡顿。实际测试时可以先给 4GB,安装完成后需要跑构建任务再加回去。
-netdev user,id=net0是 QEMU 用户态网络,等于虚拟机通过宿主机的用户态协议栈上网,不需要额外建网桥。配合e1000e这个网卡模型,是 macOS 兼容性和易用性之间比较平衡的选择。
4.3 首次启动与安装器阶段
命令行运行启动脚本后,窗口里会先出现 OVMF 的 TianoCore 界面,然后跳转到 OpenCore 菜单。如果配置正确,你会看到 macOS 安装器或恢复分区的选项,选择后系统开始拉取安装资源。从这一秒开始,基本就跟在实体机装 macOS 一样了。
进入安装器界面后,先在菜单栏打开“磁盘工具”,把 QEMU 提供的那块虚拟盘抹掉。格式选择 APFS,命名随意。抹完以后关掉磁盘工具,回到安装主界面选择目标磁盘开始安装。这里最容易出现的坑是磁盘工具里看不到虚拟盘,原因基本是启动脚本里用了 virtio-blk 而不是默认的 IDE 或 AHCI 控制器,换一种磁盘挂载方式就能解决。
安装过程会经历两到三次自动重启,每次重启你都会看到 OpenCore 菜单,有时候需要手动再次选择磁盘才能继续。中间如果卡在“剩余约 X 分钟”很长时间,不要急着杀掉进程,macOS 安装脚本经常会出现进度条不走但在后台搬运文件的情况。我等过最久的一次是 30 分钟没动静,最后发现只是网络恢复镜像下载慢,等它自己完成后跳出重启界面反而一切正常。
4.4 安装完成后的系统配置
第一次进入桌面,系统会要求设置区域、键盘、网络、账户。这些用鼠标键盘操作即可,因为没有实体 GPU 直通,画面会有一点拖影感,但整体能接受。网络在默认的 user 网络模式下是可以直接访问外网的,不需要额外设置 DNS。
建议在进入桌面后第一时间把系统时区设为 UTC 或上海时区,并关闭自动设置时间。虚拟机的时钟会因为挂起、恢复和 CPU 频率变化产生漂移,macOS 对时间漂移比 Windows 敏感,时间不对会导致很多签名验证和证书检查失败。手动校时命令加上 NTP 服务,能明显减少重启后时钟错乱的问题。
随后可以打开软件更新,把系统提到该 macOS 10 分支的最后一个大版本。对于兼容性测试来说,装到最新补丁版本更贴近生产环境。不过提醒一句,不要尝试跨太大版本升级,比如直接从 10.13 跳到 10.15,在虚拟机里跨版本升级的成功率会低很多,容易出现内核扩展不兼容和网络驱动丢失。
5. 装完只是开始:驱动、网络与虚拟机优化
5.1 显卡与显示体验的取舍
默认-vga std模式,macOS 能识别出显卡,但显存只有 16MB 左右,画面分辨率上不去,看文字还好,跑图形界面和视频会明显卡顿。如果只是做命令行测试或跑自动化脚本,这个状态完全够用。
想要高分辨率,有两个路线。第一,给 QEMU 的 VGA 设备增加显存:
-device VGA,vgamem_mb=64这条路只能稍微缓解分辨率限制,不能实现硬件加速。第二,用 VFIO 把一个真实 PCIe 显卡直通给虚拟机,macOS 会直接加载对应显卡驱动,获得接近实机的图形性能。直通需要主板开启 IOMMU,还要确认显卡的 PCIe 中断分组是独立的,不然会报中断重映射错误。
直通对于老显卡尤其好使,不少旧款显卡在 macOS 10 下有原生驱动,反而比新显卡更容易配置。我的一位同事在直通某入门级 N 卡后,把虚拟机当渲染服务器用了很长一段时间。但他的主板在 BIOS 里开了 Above 4G Decoding 才解决了显存超过 4GB 时无法映射的问题,这个细节很多人不知道。
5.2 网络适配与文件传输的现实选择
e1000e 网络模型是 macOS 自带驱动的,安装完就能上网。速度上限大概能跑到几百 Mbps,日常下载更新和传输文件都够。如果追求更高带宽,可以研究 vmxnet3 模型,它在 macOS 10.15 的高版本有驱动支持,但不是默认内置,需要额外注入。
最常用文件传输方式不是共享文件夹,而是直接在 macOS 里开启文件共享,再通过宿主机访问 SMB。QEMU 的 user 网络模式下,虚拟机与宿主机之间有 10.0.2.2 这个虚拟地址可以互通,macOS 的 Finder 里可以直接连接到宿主机的共享目录。这个方法绕过了 QEMU 对共享文件支持不完善的缺点,也不用装任何客户端。
如果你需要像 VMware 一样无缝拖拽文件,那基本只能靠第三方工具,或者把目录同步做成脚本。我的建议是别在无缝体验上花太多时间,KVM 虚拟机更适合把它当成一台独立电脑来用,设计思路和桌面级虚拟机软件很不一样。
5.3 快照、磁盘扩容与性能参数
qcow2 天然支持快照,这是 KVM 方案相比实体机的最大优势。在虚拟机关机状态下执行:
qemu-img snapshot -c clean-install macos_disk.qcow2之后如果系统被测试脚本搞坏,可以直接回滚到这个干净的安装状态:
qemu-img snapshot -a clean-install macos_disk.qcow2维护快照比复制整个镜像文件高效得多,它只记录差异数据。不过要注意,快照越多,每次写入磁盘时的开销越大,所以保留两三个关键时间点就够,定期清理旧快照。
磁盘扩容的常规做法是先用qemu-img resize扩大镜像文件,再到 macOS 里用磁盘工具调整分区大小。整个过程有风险,官方建议还是先打一个快照再操作。性能方面,如果宿主机 CPU 支持超线程,把虚拟机的线程总数设为物理核数的一半到四分之三比较合理,给宿主机留一点余量,避免因为把核吃满而导致整个系统无响应。
6. 踩坑记录与排查速查表
6.1 启动即崩溃的两类经典问题
第一类问题是启动脚本执行后黑屏,连 OVMF 界面都不出现。常见原因有两个:一是-cpu host在个别 AMD 平台上缺少必要的 CPU 标志,方案是改成-cpu host,+ssse3,+sse4.2;二是 OVMF 的 VARS 文件被写坏,重新从/usr/share/OVMF/复制一个干净的副本再启动。
第二类问题是能进入 OpenCore,但选择 macOS 安装器后重启回菜单,形成死循环。这通常出现在安装第二阶段,原因是 ACPI 表里的某些字段与玩具版固件不匹配。思路不是去改系统文件,而是调整 QEMU 启动参数,比如在-machine q35后面加上smm=on,或者在 OpenCore 配置里加上更完整的补丁。
还有一个特别隐蔽的坑是宿主机开启了 Secure Boot,导致 OVMF 找不到任何可引导设备。Ubuntu 默认安装时一般开启 Secure Boot,它会阻止加载未签名的 EFI 引导内容。解决办法是临时进 BIOS 关闭 Secure Boot,或者用带签名的 OpenCore 引导镜像。
6.2 常见问题速查表
| 现象 | 可能原因 | 解决办法 |
|---|---|---|
| 安装器看不到磁盘 | 使用了 virtio-blk 或 scsi 控制器 | 改用默认 IDE / AHCI 挂载方式 |
| 白屏或花屏 | 显存不足 / 非标准 VGA | 使用-vga std并设置vgamem_mb=64 |
| 反复重启不进入安装器 | ACPI 或 SMM 配置不当 | 加上smm=on并确认 OVMF 较新 |
| 时钟越跑越慢 | 虚拟机时钟同步失效 | 手动开启 NTP 并安排宿主机时间同步 |
| 宿主机网络正常但虚拟机上不了网 | e1000e 驱动未加载 | 确认启动脚本没有误用 virtio-net |
| 安装进度条长时间不动 | 网络恢复镜像下载慢 | 不要立刻杀进程,观察 QEMU 窗口状态 |
| 系统启动后很卡 | CPU 核数/内存不足 | 提高-smp和-m,同时给宿主机留余量 |
这个表是我实际操作中积累下来的,不能覆盖所有情况,但是能解决八成“第一次跑”会遇到的挫折。每一条背后都对应一整个排查过程,如果你卡在某一步,先回头确认自己的启动脚本是否和上面的对照过,九成问题出在参数选型上,而不是硬件不行。
6.3 避坑心得:别盲目追求最新参数
网上流传的启动脚本不一定适配 Ubuntu 24.04 自带的 QEMU 版本。我看到过一个常见操作是把 OpenCore 配置里的 CPU 频率同步参数全部打开,结果在老版本 macOS 10 上频繁死机。原理很简单,macOS 10 系列的调度器不认识某些新虚拟化特性,过多的 hv 参数反而触发内核恐慌。所以我在生产环境里只保留hv_relaxed、hv_spinlocks、hv_vapic、hv_time这四个基础参数,其余一律不加。
另外,很多人喜欢在命令行里加-enable-kvm,但这里的 QEMU 包已经默认支持,真在启动脚本里写其实是多余的。我保留这个参数习惯的原因只是为了在启动时快速确认 KVM 加速是否被启用,如果当前用户没有 kvm 组权限,它会在终端里明确报错。如果明明加了这个标志却提示不能访问/dev/kvm,记得把用户加入 kvm 组:
sudo usermod -aG kvm $USER改完重新登录生效,这条不处理,后面无论怎么调配置都是白搭。
跑通整套安装之后,这个虚拟机就可以作为长期测试环境了。我个人体会是,最省心的用法是把它当独立工作站,定期做快照,把所有实验性操作都放在快照里。遇到不可恢复的问题就回滚,而不是从头再安装一遍。macOS 虚拟化在 KVM 上确实比 Windows 多绕几个弯,但一旦跑顺,你收获的不只是能运行的虚拟机,还有一套你亲手调通的硬件虚拟化能力。这层底子,迁移到其他实验系统时同样受用。