Appium触发SessionNotCreated异常时无法终止Node进程的解决咨询
解决iOS Safari并行自动化中Appium SessionNotCreated异常与进程泄漏问题
核心问题分析
随机出现的SessionNotCreated异常本质是多设备并行时WebDriverAgent(WDA)资源竞争、Appium会话管理漏洞导致;进程无法终止是因为异常触发时未正确回收Appium子进程(Node启动的实例与测试进程的父子进程关联未被正确处理)。
针对性解决方案
1. 精准回收单实例进程,避免脚本整体终止
- 给每台设备分配独立的Appium实例:启动时指定唯一端口(如
--port 4723 + 设备索引)、独立WDA端口(--webdriveragent-port 8100 + 设备索引),同时记录每个实例的PID。 - 捕获
SessionNotCreated异常时,通过PID直接杀死对应Appium子进程(而非端口):import os import signal import time # 假设维护了device_id -> appium_pid的映射字典 appium_pid = device_pid_map[failed_device_id] try: os.kill(appium_pid, signal.SIGTERM) # 先尝试优雅终止 time.sleep(2) # 检查进程是否仍存在,不存在则跳过 if os.path.exists(f"/proc/{appium_pid}"): os.kill(appium_pid, signal.SIGKILL) # 强制终止 except OSError: pass # 进程已终止则忽略 - 此方法仅终止异常设备对应的Appium实例,不会影响其他并行测试进程。
2. 优化Appium启动配置,从根源减少会话创建失败
- 启动Appium时添加
--session-override参数,强制覆盖无效残留会话,避免资源占用。 - 设置
--command-timeout 300(5分钟),超时自动回收无响应的会话与进程。 - 配置iOS Safari的Desired Capabilities,重置会话状态:
{ "platformName": "iOS", "deviceName": "XXX", "browserName": "Safari", "safariClearSession": true, "safariInitialUrl": "about:blank", "wdaLaunchTimeout": 120000, "wdaConnectionTimeout": 120000 } - 增加WDA的启动与连接超时时间,避免因设备性能差异导致的会话创建超时。
3. 改用Appium Grid统一管理并行测试
- 搭建Hub-Node架构:Hub作为调度中心,每台iOS设备对应一个Grid Node,由Hub负责会话分配与进程管理。
- 配置Node时,通过
node-config.json指定独立端口、WDA端口及设备唯一标识:{ "capabilities": [ { "browserName": "Safari", "platformName": "iOS", "deviceName": "Device-1", "udid": "XXX", "maxInstances": 1 } ], "configuration": { "nodePort": 4723, "webdriveragentPort": 8100, "cleanUpCycle": 2000, "timeout": 30000 } } - 当
SessionNotCreated异常发生时,Grid会自动标记该Node为不可用,回收对应资源,无需手动处理进程。
4. 异常退避重试+WDA资源前置清理
- 捕获异常后,先清理当前设备的WDA进程,再重试会话创建(最多3次指数退避):
- 模拟器:
xcrun simctl terminate booted com.facebook.WebDriverAgentRunner - 真机:
ideviceinstaller -u <udid> -U com.facebook.WebDriverAgentRunner
- 模拟器:
- 重试失败后再重启对应Appium实例,而非直接重启全部实例,减少对其他测试的影响。
5. 定时清理僵尸进程
- 编写独立脚本,定时扫描系统中无父进程的Appium/WDA僵尸进程:
# 查找父进程已退出的Appium进程并杀死 ps aux | grep appium | awk '{print $2, $3}' | while read pid ppid; do if ! ps -p $ppid > /dev/null; then kill -9 $pid fi done - 将脚本作为测试框架的前置/后置钩子,每次测试套件运行前后执行,避免内存持续占用。
内容的提问来源于stack exchange,提问作者Prashant Jeet Singh
相关产品推荐
相关产品推荐

