如何让macOS Launch Agent持续运行直至请求服务的客户端进程关闭?
解答
你提到的“条件字典”就是KeepAlive对应的字典类型配置项——默认你用的是布尔值true,但实际上KeepAlive可以接收一个字典,通过里面的键值对定义launchd保持作业活跃的条件。结合你的需求(服务随客户端进程关闭而终止),最佳实现是服务端跟踪活跃连接数,无连接时主动退出,配合launchd的KeepAlive字典配置避免不必要的重启。
具体实现步骤
1. 修改服务端代理类,跟踪活跃连接
在ServiceDelegate中维护连接计数,监听连接失效事件,当最后一个连接断开时主动退出进程:
class ServiceDelegate: NSObject, NSXPCListenerDelegate { private var activeConnections = 0 private let connectionQueue = DispatchQueue(label: "com.name.connectionQueue") // 线程安全队列 func listener(_ listener: NSXPCListener, shouldAcceptNewConnection newConnection: NSXPCConnection) -> Bool { let exportedObject = MyXPC() newConnection.exportedInterface = NSXPCInterface(with: MyXPCProtocol.self) newConnection.exportedObject = exportedObject // 监听连接断开事件 newConnection.invalidationHandler = { [weak self] in self?.connectionQueue.async { guard let self = self else { return } self.activeConnections -= 1 // 无活跃连接时退出进程 if self.activeConnections == 0 { exit(0) } } } newConnection.resume() // 增加连接计数 connectionQueue.async { self.activeConnections += 1 } return true } }
2. 修改Launch Agent的plist配置
将原来的<key>KeepAlive</key><true/>替换为字典配置,设置SuccessfulExit为false——这意味着launchd只会在服务进程异常退出(非0退出码)时重启它,正常退出(0退出码)则不会重启:
<key>KeepAlive</key> <dict> <key>SuccessfulExit</key> <false/> </dict>
工作流程说明
- 客户端发起XPC连接时,launchd会自动启动服务进程(如果未运行)。
- 服务进程每接收一个连接,计数加1;连接断开时计数减1。
- 当最后一个客户端连接断开,服务进程主动调用
exit(0)正常退出。 - launchd检测到服务进程正常退出,不会重启它,完全符合你“服务随客户端关闭而终止”的需求。
这种方式既利用了launchd的管理能力,又通过服务端的连接跟踪保证了生命周期的精准控制,是XPC服务的标准实践方案。
内容的提问来源于stack exchange,提问作者chemFour
相关产品推荐
相关产品推荐

