OpenCore Legacy Patcher 如何修补运行中的 macOS 系统
发布时间:2026/9/9 14:54:57 作者:尧图编辑部 阅读量:1,286

OpenCore Legacy Patcher 如何修补运行中的 macOS 系统【免费下载链接】OpenCore-Legacy-PatcherExperience macOS just like before项目地址: https://gitcode.com/GitHub_Trending/op/OpenCore-Legacy-PatcherOpenCore Legacy Patcher 的 Root Patch系统补丁是该项目里最精细的部分它修改的不是 U 盘或某个分区而是当前正在运行的 macOS 的只读根卷。仓库里的 PATCHEXPLAIN.md 偏向解释补丁包含什么本文换一个视角带你从源码层面过一遍修补流水线的实际执行路径重点拆两个容易踩坑的节点不同 macOS 版本下怎么挂载只读根卷、为什么拷贝完 kext 之后还必须重建内核缓存。目标是让你对照日志就能在机器上验证每一个环节。全景一次修补流程怎么跑先看全局。入口是 sys_patch.py 里PatchSysVolume的start_patch()事件顺序是HardwarePatchsetDetection探测硬件GPU、无线网卡、USB 1.1 控制器等决定套用哪些补丁集挂载PatcherSupportPkg存放补丁素材的 disk image把根卷挂载到/System/Volumes/Update/mnt1_run_sanity_checks()比对挂载卷里SystemVersion.plist的ProductBuildVersion与当前运行系统不一致就报错退出——那意味着 OTA 更新正在进行中_execute_patchset()按补丁集字典删除旧文件、拷贝新 kext、执行必要的 shell 命令_rebuild_root_volume()重建内核缓存 →仅 Catalinakcditto更新 preboot 内核缓存 →仅 Mojave 及更老重建 dyld shared cachebless创建新的 APFS 快照卸载卷。关键点是整个过程发生在运行中系统的旁边。系统自己是从旧的 sealed 快照启动的补丁器改的是快照背后的 live volume新快照要下次启动才生效。这和往 EFI 分区写文件是完全不同的量级。挂载只读根卷为什么按 macOS 版本分三个分支mount.py 的RootVolumeMount._mount_root_volume()按 XNU 主版本号分支简化后的逻辑是if self.xnu_major os_data.os_data.catalina.value: return / # Catalina 之前根卷可写 if self.xnu_major os_data.os_data.catalina.value: # Catalina把只读根卷重新挂载为可写 subprocess_wrapper.run_as_root([/sbin/mount, -uw, /]) return / # Big Sur 及更新把源卷挂到系统自己的挂载点 subprocess_wrapper.run_as_root([/sbin/mount, -o, nobrowse, -t, apfs, f/dev/{self.root_volume_identifier}, /System/Volumes/Update/mnt1])Catalina 之前/本身就是可写的第一支直接返回Catalina 引入只读根卷需要mount -uw /重新以读写方式挂载Big Sur 起系统从 sealed APFS 快照如/dev/disk3s1s1启动快照不可修改只能把快照背后的源卷挂出来。设备号由_fetch_root_volume_identifier()解析diskutil info -plist /的DeviceIdentifier得到若确认是快照就直接截掉末尾两位。为什么偏偏选/System/Volumes/Update/mnt1这个挂载点因为 Apple 自己的更新机制就把源卷挂在这里。OCLP 复用同一个挂载点等于和系统自身的快照管理行为对齐避免两边争抢同一个卷。拷完 kext 还不够重建内核缓存Catalina 起内核不再直接从磁盘加载 kext而是加载/System/Library/KernelCollections/里的 prelinked 内核缓存。只把 kext 拷进挂载卷的话它们只是躺在磁盘上的文件。rebuild.py 的RebuildKernelCache._rebuild_method()负责按版本分流Big Sur 及更新走kmutilLion 到 Catalina 走 prelinked 流程更早走mkext。Big Sur 及更新的kmutil参数在 boot_system.py 里拼装节选args [/usr/bin/kmutil] if self.detected_os os_data.os_data.ventura: args.append(create) args.append(--allow-missing-kdk) else: args.append(install) args.append(--volume-root) args.append(self.mount_location) args.append(--update-all)这里有个讲究Ventura 起用create --allow-missing-kdkBig Sur/Monterey 用install。sys_patch.py 头部注释见上文引用解释了原因——Ventura 起 Apple 移除了部分盘上二进制kmutil依赖 Kernel Debug KitKDK参与重建。所以修补流程的 preflight 里有_merge_kdk_with_root()这一步没有 KDK 就先下载再合并进挂载的根卷。补丁日志里出现下载 KDK不是可选项而是重建缓存的硬前提。如果补丁集往/Library/Extensions放 kext大多数老 GPU 补丁集都会Ventura 起还需要 auxiliary kernel collection。这里有个比较野的设计决策Apple 没有公开重建 auxiliary KC 的入口于是 auxiliary.py 的_force_auxiliary_usage()先用kmutil create --new aux构建新的辅助缓存然后killall syspolicyd kernelmanagerd再删掉/private/var/db/SystemPolicyConfiguration/下的KextPolicy、KextPolicy-shm、KextPolicy-wal三个文件——策略数据库没了系统就不得不按新缓存重新建立策略。本质上是逼着 Apple 的代码走首次构建路径而不是去改 Apple 的代码。APFS 快照既是提交点也是回滚点前面所有步骤都只是改草稿真正提交的一步是新建快照。snapshot.py 的create_snapshot()args [/usr/sbin/bless] if platform.machine() arm64 or self._rosetta_status() is True: args [--mount, self.mount_path, --create-snapshot] else: args [--folder, f{self.mount_path}/System/Library/CoreServices, --bootefi, --create-snapshot]Intel 与 Apple Silicon 的bless参数不同后者在非系统卷上不能直接--create-snapshot只能走--folder --bootefi的路子。快照创建成功后系统下次启动才会加载打过补丁的内容。回滚方向同样是快照语义unpatch 入口start_unpatch()调_unpatch_root_vol()第一步就是revert_snapshot()即bless --mount ... --bootefi --last-sealed-snapshot把启动指回上一个 sealed 快照之后才清理 SkyLight 插件、non-Metal 强制偏好和残留的辅助缓存。为什么不逐文件恢复因为补丁改动的文件清单无法穷举哪些是新增、哪些是覆盖、哪些 kext 被删而快照回滚是系统级原子操作Apple 的更新机制自己也依赖它。sys_patch.py 头部注释里还有一条值得记住的坑Big Sur 下原始快照会在两三次启动内被系统丢弃回滚不可靠Monterey 起系统会保留原始快照回滚才稳定。OTA 更新之后怎么自动补补丁系统补丁不是永久生效的每次 OTA 更新都会重新 seal 系统快照补丁内容被新快照覆盖掉。所以_patch_root_vol()在_execute_patchset()跑完后若为 GUI 版且系统是 Big Sur 及更新会调 install.py 的install_auto_patcher_launch_agent()写入一组 launch services服务类型职责...auto-patch.plistLaunchAgent登录后检查并重新打补丁...macos-update.plistLaunchDaemon监测 macOS 更新...os-caching.plistLaunchDaemon缓存 KDK / MetallibSupportPkg...rsr-monitor.plistLaunchDaemon监测 cryptex清理 GPU 伴侣包其中 os-caching 和 rsr-monitor 只在满足条件时才安装写入前还会对本地与系统内已有副本做 sha256 比对一致就跳过保证幂等。另有个文档没明说的细节源码方式运行launcher_script is not None时会直接跳过 launch agent 安装——因为守护进程的 plist 写死了特定 app 路径源码运行的构建没有这个路径写进去只会得到一堆死掉的守护进程。PROCESS.md 从用户视角说了同一件事如果关掉后台进程每次更新后就得手动打开应用重新打补丁KDK 也要手动下载。这就是官方强烈建议保持后台进程开启的原因。 怎么验证系统补丁生效补丁流程结束后机器上有三件事可以查看收据cat /System/Library/CoreServices/OpenCore-Legacy-Patcher.plist。这个 plist 由_write_patchset()在补丁完成后写入记录了补丁集名称、使用的 KDK 版本和 commit 信息看快照数量diskutil apfs listSnapshots /打完补丁后快照数应比之前多一个看内核缓存的重建时间stat -f %Sm /System/Library/KernelCollections/SystemKernelExtensions.kc应接近补丁完成时间。想验证重复打补丁会被拒绝可以直接看detect.py里HardwarePatchsetValidation枚举已打补丁后再跑修补会命中REPATCHING_NOT_SUPPORTEDroot volume dirty已安装的补丁版本和当前代码版本不一致则报 Installed patches are from different commit。所以正确的升级姿势是先 unpatch 再 patch而不是叠补丁。⚠️ 避坑提示打完补丁后不要再手动改动系统卷内容快照 seal 会变成 Broken校验会直接报 System volume is tainted, unpatching is requiredVentura 及更新在 OTA 之后必须先下载对应构建的 KDK 才能重新修补看到后台进程在下载 pkg 时别中断auxiliary KC 构建后系统偏好弹出的授权提示可以先忽略但建议之后在系统设置 → 隐私与安全性里允许否则部分 kext 可能被卡住快照回滚在 Monterey 起才可靠Big Sur 上动手前自己留一份备份若bless报 Cant use last-sealed-snapshot or create-snapshot on non system volume那是 APFS 卷本身建得不干净的已知 bug按日志提示做 clean install。【免费下载链接】OpenCore-Legacy-PatcherExperience macOS just like before项目地址: https://gitcode.com/GitHub_Trending/op/OpenCore-Legacy-Patcher创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考