You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 22:45:38