资讯动态

Appium iOS真机自动化报错xcodebuild code 65的完整排查与解决

发布时间:2026/10/18 13:14:27 来源:尧图企业网站定制
最近帮同事排查一个 iOS 真机自动化跑不起来的问题Appium 启动会话时卡了小半天日志翻到最后又是那个让人血压升高的 “xcodebuild failed with code 65”。说起来这个报错在 Appium 自动化测试里真的太常见了尤其是换了新电脑、升级了 Xcode或者第一次接真机的时候几乎每个搞 iOS 自动化的同学都会撞上它。如果你也是被 code 65 折磨过的人那这篇文章应该能帮你省下不少时间。很多朋友一看到 code 65 就懵了以为是某个具体的错误码跑去 Google 半天也没找到一致的答案。实际上它只是 xcodebuild 命令的通用退出码含义笼统说是“构建失败”真正的原因藏在它上面的那一大段编译日志里。今天我不打算只丢给你一两个“灵丹妙药”式的命令而是把 WebDriverAgent、xcodebuild、签名、版本匹配这些一起串起来讲清楚报错是怎么发生的再手把手带你把每一条路子都走通最后写成一个可以直接照着操作的排查清单。1. 先搞清楚code 65 背后到底藏了什么1.1 WebDriverAgent 在 Appium 里的角色Appium 本身不直接和 iOS 设备通信它走的是 XCUITest 这条系统级测试框架。WebDriverAgent简称 WDA是 Appium 在 iOS 上的一个“中转代理”本质上是一个跑在手机上的测试应用Appium 通过它来发送指令、执行点击、滑动、获取元素信息等等。所以在 Appium 真正开始跑脚本之前会先做一件事把 WDA 编译成一个可用于 XCUITest 的 Runner并且安装到你的真机或模拟器上。这个“编译”的动作就是调用 xcodebuild 完成的。只要这一步失败Appium 就直接报错测试压根没机会开始。code 65 就是这个编译步骤失败的退出码。1.2 code 65 不是错误本身而是“错误前的最后一声叹息”xcodebuild 在构建失败时会返回非零退出码code 65 就是其中一种通用退出码。它不像 HTTP 404 那样指代具体问题而是说“构建这个过程挂掉了”。真正有价值的线索全部在它前面那几十上百行的编译输出里。很多人一看到 code 65 就把日志丢给我但我一眼扫过去也是看不出个所以然来——因为那种贴法只贴了最后两行没有暴露真正的 error 行。正确做法是往回翻找 “error:” 前缀的日志。比如error: Signing for WebDriverAgentRunner requires a development team. error: No profiles for io.appium.WebDriverAgentRunner were found.这种才是罪魁祸首。所以第一步要养成的习惯就是看到 code 65别急着到处搜命令先把上面那段 error 找到。1.3 三类最常见的 Code 65 翻车现场根据我接触过的实战案例code 65 的根源大致可以归为三类第一类是证书和签名问题。真机测试必须有一个有效的开发者证书和对应的描述文件WebDriverAgentRunner 这个 Target 如果没有正确设置 Team或者 Bundle Identifier 没有权限xcodebuild 就会直接退出。第二类是版本不匹配问题。比如 Xcode 版本太新而 Appium 内置的 WDA 源码太旧或者反过来WDA 里依赖的某些框架在新 SDK 下编译不过去。第三类是环境和依赖问题。包括端口被占用、之前构建留下的 DerivedData 权限异常、命令行工具路径指向错误等。这类问题常被忽略但它们确实会报出 code 65而且表面上看起来和代码毫无关系。下面我就按这个分类一步步展开讲。2. 报错现场的分诊把日志当成案发现场2.1 从 Appium 日志里挖出真正的 error 行一般情况下Appium 启动 iOS 会话时的日志大致长这样[debug] [XCUITest] WebDriverAgent (wda) is not installed. Building... [debug] [XCUITest] Using WDA path: /usr/local/lib/node_modules/appium/node_modules/appium-webdriveragent [debug] [XCUITest] Running: xcodebuild -project WebDriverAgent.xcodeproj \ -scheme WebDriverAgentRunner -configuration Debug \ -destination id00008130-xxxx -allowProvisioningUpdates build ... [debug] [XCUITest] xcodebuild exited with code 65注意看日志里会先给出 WDA 的实际路径然后告诉你正在执行的 xcodebuild 命令。这两条信息很重要。后面真正报错的地方往往不是 “exited with code 65” 那一行而是它之前若干行里出现的第一个 “error:”。我建议你在遇到这个报错时直接把 Appium 的日志级别调到 debug或者干脆手动跑一遍 xcodebuild 命令用完整输出代替被 Appium 截断的日志。2.2 不同类型报错的日志指纹根据长时间的观察code 65 前面的典型 error 内容其实是有规律可循的。如果是签名问题日志里通常会包含 “requires a development team” 或 “No profiles for ... were found” 之类的字眼。如果是缺少某类描述文件会出现 “The operation couldnt be completed. Unable to launch” 或 “Code Signing is required”。如果是源码兼容问题你会看到类似 “Cannot synthesize weak property” 或者某些头文件找不到、某些 API 已废弃、甚至直接编译报红的提示。这些往往和 Xcode 版本、SDK 版本有关系。如果是环境类问题日志里可能没有任何明显 error只是在 “xcodebuild exited with code 65” 之前出现过 “Permission denied” 或者端口占用相关的 Warning。2.3 用 xcode-select 排查基础环境很多开发者机器上同时装了多个 Xcode可能是公开版和测试版并存或者是 Xcode.app 路径被改过。这种情况下xcodebuild 实际使用的并不是你“以为”的那个 Xcode命令行工具的路径一旦指向错误构建就会出各种莫名其妙的结果。先看一下当前选中的开发者目录xcode-select -p如果输出不是 /Applications/Xcode.app/Contents/Developer而是别的路径最好先切换回来sudo xcode-select -s /Applications/Xcode.app/Contents/Developer切换完之后再用xcodebuild -version确认版本是否和你预期一致。这一步做完了可以顺手把之前出错的构建残留清理一下cd ~/Library/Developer/Xcode/DerivedData rm -rf WebDriverAgent-*这个动作不会影响其他工程只是把 WDA 相关的中间编译产物删掉避免旧缓存干扰新构建。3. 逐个击破Code 65 的三大根因与手把手修复3.1 签名证书缺失真机必踩的坑3.1.1 为什么模拟器不报真机就报代码签名是 iOS 设备安装应用的一道硬性安全要求。模拟器上运行 WDA 不需要真实证书Appium 甚至可以加参数跳过签名直接跑所以很多同学“模拟器一切正常一连真机就 code 65”。真机环境下WDA 需要被安装到一个物理设备上系统会检查你的 Runner 是否有合法的开发者证书签名没有就是构建失败。3.1.2 用图形界面配置签名最稳妥的解决方式是直接打开 WDA 的工程文件在 Xcode 里手动勾选签名。先看 WDA 路径。不同安装方式的路径不同如果是 npm 全局安装的 Appium一般在 /usr/local/lib/node_modules/appium/node_modules/appium-webdriveragent如果用 Appium Desktop一般在 /Applications/Appium.app/Contents/Resources/app/node_modules/appium-webdriveragent如果用的是 Appium 2.x那么 WDA 大概率在 appium-xcuitest-driver 的 node_modules 里具体路径可以通过 Appium 日志里的 “Using WDA path” 查看确认路径后cd /path/to/appium-webdriveragent open WebDriverAgent.xcodeproj打开后按以下步骤配置左侧项目导航里选中 WebDriverAgent 这个 Project在 TARGETS 列表里选中 WebDriverAgentRunner切到 “Signing Capabilities” 页签勾上 “Automatically manage signing”在 “Team” 下拉框里选择你自己的开发者团队顺手看一下 Bundle Identifier如果默认的 io.appium.WebDriverAgentRunner 已经在你名下被用过或者和同事重复了就手动改成唯一的比如 io.appium.WebDriverAgentRunner.YourName3.1.3 命令行校验签名配置是否就位图形界面改完了可以用这个命令确认签名相关设置xcodebuild -project WebDriverAgent.xcodeproj -scheme WebDriverAgentRunner -showBuildSettings | grep -E CODE_SIGN|DEVELOPMENT_TEAM|PRODUCT_BUNDLE_IDENTIFIER这里你会看到 DEVELOPMENT_TEAM 是否被正确赋值以及 PRODUCT_BUNDLE_IDENTIFIER 是否已经是修改后的值。如果你在终端里跑了 Appium直接把 Team ID 写进环境变量里也是一个可选操作但我个人还是推荐用 Xcode 界面配好逻辑更直观。3.2 版本不匹配Xcode、iOS、WDA 之间的兼容性3.2.1 常见的版本冲突表现这类问题在某些时候特别隐蔽。日志里可能会看到某个文件报了很多编译错误或者干脆是 WebDriverAgent 的某个源码用了新版本 SDK 才有的 API导致编译不过。还有一种情况是 iOS 系统版本太新而旧版 WDA 没有适配也会编译失败。比如老版本 Appium 自带的 WDA 在 Xcode 14 上构建时我见过好几个环境都出现过 “target has a provision requirement” 或者复杂的链接错误。升级 Appium 版本通常能解决。3.2.2 手动替换成新版 WDA如果升级 Appium 不现实另一个选择是手动拉取新版 WDA 源码替换。git clone https://github.com/appium/WebDriverAgent.git然后删除旧 WDA 目录把新克隆的 WebDriverAgent 文件夹放到原路径并改名为 appium-webdriveragent。这样 Appium 在构建时会直接用新目录下的源码。不过有一点要注意新版 WDA 对 Node 版本和 Appium-xcuitest-driver 版本也是有要求的整体版本链尽量保持统一。我的习惯是先把 Appium 升到较新的稳定版然后看日志里实际使用的 WDA 路径再有针对性地决定要不要替换源码。3.2.3 用 usePrebuiltWDA 绕开现场构建如果 WebDriverAgent 一直构建失败又暂时不希望每次启动会话时都现场编一次可以考虑先手动构建好 WDA然后让 Appium 直接使用构建产物。Appium 的 capabilities 里有一个选项usePrebuiltWDA: true开启后Appium 不再执行 xcodebuild 构建这一步而是用已经生成的 WebDriverAgentRunner. app。这套方案尤其适合团队里统一了 Xcode 环境的情况。先把 WDA 构建好再把这个二进制产物放进指定目录省掉了大量重复编译时间也绕开了很多不确定因素。不过这个方案也有坑WDA 的构建产物和 iOS 版本是强相关的真机系统一旦升级旧的 Runner 可能没法正常运行这时还得重新构建。3.3 端口占用与 DerivedData 权限问题3.3.1 8100 端口被占用WDA 启动后会在真机上开启一个 HTTP 服务默认端口是 8100Appium 再通过这个端口和 WDA 通信。如果这个端口被其他进程占用Appium 连接 WDA 也会失败日志里的表现经常也是构建或启动异常。排查方法很简单lsof -i :8100看到有进程监听就先处理掉。如果是以前遗留的 wda 进程可以直接杀掉kill -9 进程ID3.3.2 DerivedData 权限异常在用 sudo 跑过 xcodebuild 的机器上DerivedData 目录经常会出现属主混乱。当前用户没有写权限构建时无法创建中间文件报的错也经常是 code 65。处理办法就是重新把目录所有权还给当前用户sudo chown -R $(whoami) ~/Library/Developer/Xcode/DerivedData顺便提一句尽量不要用 sudo 去跑 xcodebuild 或 Appium。一个是权限混乱很难追溯另一个是会把问题引到更难排查的方向去。4. 完整实操从零构建 WDA 并在 Appium 中跑通4.1 定位并打开 WebDriverAgent 工程我先按最常见的方式说一遍这套流程在 Appium 2.x 和 Appium 1.x 上大同小异。先找到 WDA 的实际路径最直接的办法就是看日志。Appium 启动时会打印 “Using WDA path”。还有一种办法是直接找find /usr/local/lib/node_modules -name WebDriverAgent.xcodeproj 2/dev/null找到之后进目录、打开工程cd /usr/local/lib/node_modules/appium/node_modules/appium-webdriveragent open WebDriverAgent.xcodeproj如果你用的是 Appium 2.x路径通常会在类似 appium-xcuitest-driver/build/lib 下的某个 node_modules 里。建议还是先跑一次 Appium看日志里的 WDA 路径最准确。4.2 Xcode 图形化配置签名打开工程后执行签名配置的完整操作在 TARGETS 里选中 WebDriverAgentRunner进入 Signing Capabilities 页面勾上自动管理签名选择 Team并且把 Bundle Identifier 改成你自己的唯一值。这一步必须确认不然后面 xcodebuild 照样报 code 65。这里补充一个很多人忽略的小知识点Xcode 的自动签名只能帮你生成和管理描述文件前提是你登录的开发者账号和当前设备的 UDID 都满足要求。如果你用的免费个人团队账号最多只能注册一定数量的设备真机 UDID 不在你的账号设备列表里时自动签名也会失败。4.3 命令行构建验证配置完签名后先在命令行手动构建一次。这一步其实是帮我们提前暴露问题免得每次都要通过 Appium 才能看到完整日志。先拿到真机的 UDID。最简单的办法是用xcrun xctrace list devices新版 Xcode 也可以用xcrun devicectl list devices或者你可以先用idevice_id -l如果装了 libimobiledevice。拿到 UDID 后手动执行xcodebuild \ -project WebDriverAgent.xcodeproj \ -scheme WebDriverAgentRunner \ -configuration Debug \ -destination id$UDID \ -allowProvisioningUpdates \ build如果这次构建成功日志最后会出现 “BUILD SUCCEEDED”。这时再回到 Appium 里启动会话大概率就不会再撞上 code 65 了。如果构建还是失败就回到第二章提到的“找 error 行”大法继续往下排查。值得注意的是手动构建和 Appium 构建用的是同一份工程和同一套签名一旦手动构建成功问题已经很接近真相了。4.4 回到 Appium 配置 Desired Capabilities构建问题解决后Appium 里的配置也值得顺一遍。我见过很多人明明 WDA 构建成功了但 capabilities 里漏了平台相关参数导致会话反复超时。这里给一份我常用的 iOS 真机配置示例{ platformName: iOS, platformVersion: 16.5, deviceName: iPhone 12, udid: 00008130-xxxxx, bundleId: com.example.yourApp, xcodeOrgId: YOUR_TEAM_ID, xcodeSigningId: iPhone Developer, automationName: XCUITest, wdaLocalPort: 8100 }几个字段分别解释一下udid必须填写真机的实际 UDID不能随便填设备名xcodeOrgId开发者 Team IDxcodeSigningId一般是 iPhone Developer表示用开发者证书签名wdaLocalPort本地和真机 WDA 服务通信的端口可自定义但不要和本机其他服务冲突如果你之前是照着网上旧教程写的使用了appium作为 automationName 之类的写法在新的 driver 下面大概率会出问题。这一步值得回头核对一下。5. 常见问题速查表与快捷处理把这几年来遇到过的 code 65 相关场景整理了一下做成一个速查表方便你以后直接定位。日志特征可能根因快速处理方式Signing for WebDriverAgentRunner requires a development team没有配置开发者 Team在 Xcode 里给 WebDriverAgentRunner 配置签名团队No profiles for io.appium.WebDriverAgentRunner描述文件缺失或 Bundle ID 无权限修改 Bundle Identifier 唯一位开启自动签名Code Signing is required真机强制要求签名确认 xcodeSigningId 配置为 iPhone Developerxcodebuild exited with code 65无其他显式 errorDerivedData 权限异常或缓存损坏删除 WebDriverAgent 相关 DerivedData 缓存修复目录权限8100 端口无法建立连接WDA 启动失败或被之前进程占用lsof -i :8100杀占用的进程后重试升级 Xcode 后突然出现编译错误WDA 版本太旧Xcode 不兼容升级 Appium 或手动替换新版 WDA 源码真机系统升级后 WDA 无法运行旧的 prebuilt WDA 不兼容新系统重新构建 WDA关闭 UsePrebuiltWDA6. 我的几点实操经验6.1 先修签名再谈其他在真机场景下code 65 里十有八九是签名问题。不管日志里显示什么先检查 Team 有没有选、Bundle ID 有没有改、手机 UDID 有没有在账号里这三件套确认完再去看别的。省得在一个错误方向上越走越远。6.2 手动 xcodebuild 是最好用的调试通道Appium 日志里虽然能看到 xcodebuild 的输出但被截断得厉害。我在踩坑的时候一定会把日志里那条 xcodebuild 命令复制出来在终端独立跑一遍。独立跑的好处是拿到完整的编译过程排查效率高很多而且不用担心 Appium 在那串一堆 debug 日志干扰视线。6.3 升级要整体升级不要只动一个组件曾经有个团队只把 WDA 换成了新版结果 Appium 里另一个模块还是老 API引发了奇奇怪怪的报错。iOS 自动化这套环境Appium、appium-xcuitest-driver、WDA、Xcode 四者之间是有版本联动关系的。稳妥的做法是锁定一套已知能工作的版本组合升级时一起升并且用 Docker 或者脚本固定住环境少给队友留“惊喜”。6.4 给真机开启开发者模式从 iOS 16 开始真机要想跑 XCTest 相关的东西必须到系统的“设置 - 隐私与安全性 - 开发者模式”里手动打开。这个步骤不做即使构建成功了WDA 也可能启动不了Appium 会一直卡在等待设备响应。遇到这种情况不要盯着 log 苦想看一下连接的手机屏幕弹窗点一下“打开”就解决了。最后再分享一个我个人的小习惯每次排查这类问题我都会先建一个 txt 文件把 Appium 报错的那段日志完整复制进去再把手动执行 xcodebuild 的输出追加在后面最后统一搜 “error”。因为真正有用的信息不会主动跳到你脸上但只要把两个输出放一起答案往往自己就浮出来了。希望你看了这篇之后以后再遇到 code 65能少走几趟弯路。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑