macOS 13 Ventura下Electron自动更新退出重启后不安装求助
环境
- Electron:25.x(已测试)
- electron-builder / electron-updater:测试版本为electron-builder 23.x / electron-updater(版本可能有差异)
- macOS:13.x Ventura
主进程/更新器配置代码
const { app } = require('electron'); const { autoUpdater } = require('electron-updater'); autoUpdater.autoDownload = true; autoUpdater.autoInstallOnAppQuit = true; // 仅在打包后检查更新 if (app.isPackaged) { autoUpdater.checkForUpdates(); } autoUpdater.on('update-available', () => { console.log('发现可用更新'); }); autoUpdater.on('update-downloaded', () => { console.log('更新已下载,将在退出时安装'); // 此处刻意不调用quitAndInstall(),期望退出应用时自动安装 }); autoUpdater.on('error', (err) => { console.error('更新器错误:', err); });
构建/发布配置(关键)
- 为macOS生成两种产物:
.dmg(用于首次安装)和.zip(供electron-updater自动安装使用)。 latest-mac.yml已上传至版本资源,指向.zip的下载地址。
package.json配置片段:
"build": { "mac": { "target": ["dmg", "zip"] } }
复现步骤
- 构建包含
.dmg、.zip及latest-mac.yml的版本包,上传至GitHub Releases。 - 在macOS Ventura系统通过
.dmg安装应用。 - 发布新版本(版本号递增),确保
.zip已上传至版本资源。 - 启动应用→
autoUpdater下载更新(可看到update-downloaded日志)。 - 退出并重启应用。
预期结果:新版本完成安装并启动。
实际结果:应用重启后仍为旧版本,更新未生效。
已排查项
- 已确认
update-downloaded事件触发,更新文件已保存至用户缓存目录(如~/Library/Caches/<AppName>/updates/)。 - 已验证版本资源中存在
.zip和latest-mac.yml。 - 已确认检查更新时应用处于打包状态(非开发模式)。
求助问题
- 需要添加哪些额外配置、代码或构建步骤,才能让下载后的
.zip在macOS Ventura系统中于应用退出时完成安装? - 应捕获哪些特定日志(如ShipIt、Squirrel.Mac)或签名/公证痕迹,以排查安装失败原因?
- macOS Ventura的安全变更或Squirrel.Mac的行为是否会阻止
quitAndInstall()/退出时自动安装?若会,有哪些明确症状或日志可佐证?
解答
问题1:额外配置、代码或构建步骤
- 主动触发安装逻辑
虽然设置了autoInstallOnAppQuit = true,但部分场景下Electron自动触发可能失效。可在应用before-quit事件中主动调用安装方法,确保更新执行:
app.on('before-quit', (event) => { if (autoUpdater.isUpdateDownloaded()) { event.preventDefault(); autoUpdater.quitAndInstall(false, true); } });
第二个参数设为true会强制关闭所有窗口并执行安装,需先判断是否有已下载的更新,避免每次退出都触发。
- 完善签名与公证
macOS Ventura对应用签名要求严格,更新包(.zip)必须和主应用使用相同开发者ID签名,且完成Apple公证。在electron-builder配置中补充签名参数:
"build": { "mac": { "target": ["dmg", "zip"], "hardenedRuntime": true, "gatekeeperAssess": false, "entitlements": "entitlements.plist", "entitlementsInherit": "entitlements.plist" }, "afterSign": "scripts/notarize.js" }
编写notarize.js脚本完成公证流程,确保更新包通过系统安全校验。
- 校验缓存目录权限
确认应用对~/Library/Caches/<AppName>/updates/目录有读写权限。若启用沙箱,需在entitlements.plist中添加对应文件访问权限,比如com.apple.security.files.downloads.read-write。
问题2:排查所需日志与痕迹
ShipIt日志
Squirrel.Mac的更新工具ShipIt会生成日志,路径为~/Library/Logs/<AppName>/ShipIt.log,里面记录安装过程中的错误(如权限不足、签名验证失败等)。系统控制台日志
打开系统「控制台」应用,搜索Squirrel或应用名称,查看系统层面的安全拦截提示,比如Gatekeeper阻止安装的日志。公证验证命令
用以下命令验证应用是否通过公证:
spctl -a -v /Applications/<AppName>.app
返回accepted则公证通过,否则会输出具体失败原因。
- electron-updater调试日志
开启调试模式记录详细流程:
require('electron-log').transports.file.level = 'debug'; autoUpdater.logger = require('electron-log');
日志会保存到~/Library/Logs/<AppName>/main.log,可查看更新全流程的细节。
问题3:macOS Ventura安全变更的影响
是的,Ventura的安全变更会影响自动更新:
强化Gatekeeper校验
未公证的更新包会被直接拦截,系统日志会出现"Squirrel" cannot be opened because the developer cannot be verified类提示,ShipIt日志中也会有签名验证失败记录。沙箱权限限制
若应用启用沙箱,默认无权限修改/Applications目录下的文件。需在entitlements.plist中添加com.apple.security.files.user-selected.read-write权限,确保更新工具能替换应用文件。后台进程启动限制
Ventura对后台进程启动管控更严格,ShipIt作为更新辅助进程可能无法正常启动,此时ShipIt日志会出现进程启动失败的错误,系统日志中会有killed by sandbox相关记录。
内容的提问来源于stack exchange,提问作者Dhilip Kumar

