mirror of
https://github.com/shadowsocks/ShadowsocksX-NG.git
synced 2026-11-03 17:43:44 +00:00
fix(agent): write absolute ProgramArguments path before SMAppService registration
SMAppService does not reliably resolve relative ProgramArguments paths for launchd (launchd reports inferred program + partial import and rejects spawn with EX_CONFIG). Rewrite the plist's ProgramArguments[0] to the wrapper's absolute path just before register().
This commit is contained in:
@@ -9,9 +9,11 @@ protocol LaunchAgentControlling {
|
||||
func unregister() throws
|
||||
}
|
||||
|
||||
/// 生产实现:plist 必须位于 app bundle `Contents/Library/LaunchAgents/`,
|
||||
/// ProgramArguments 为 Contents/ 相对路径(launchd 按注册 app 的 Contents/
|
||||
/// 解析)。
|
||||
/// 生产实现:注册时从 bundle 内模板 plist 生成带绝对 ProgramArguments 的
|
||||
/// 临时 plist,写入 `Contents/Library/LaunchAgents/` 后交给 SMAppService。
|
||||
/// SMAppService 对相对路径的 `ProgramArguments` 解析不可靠(launchd 显示
|
||||
/// `inferred program` + `partial import` 并以 EX_CONFIG 拒绝 spawn),
|
||||
/// 因此注册前把 wrapper 可执行文件的绝对路径写入 plist。
|
||||
struct SMAppLaunchAgentService: LaunchAgentControlling {
|
||||
static let plistName = "com.qiuyuzhou.ShadowsocksX-NG2.agent.plist"
|
||||
|
||||
@@ -33,10 +35,35 @@ struct SMAppLaunchAgentService: LaunchAgentControlling {
|
||||
}
|
||||
|
||||
func register() throws {
|
||||
try rewritePlistWithAbsoluteProgramPath()
|
||||
try service.register()
|
||||
}
|
||||
|
||||
func unregister() throws {
|
||||
try service.unregister()
|
||||
}
|
||||
|
||||
/// 把 bundle 内 plist 的 ProgramArguments[0] 重写为 wrapper 的绝对路径。
|
||||
/// 只在注册前调用;卸载不要求还原。
|
||||
private func rewritePlistWithAbsoluteProgramPath() throws {
|
||||
let bundle = Bundle.main.bundleURL
|
||||
let plistURL = bundle.appendingPathComponent(
|
||||
"Contents/Library/LaunchAgents/\(Self.plistName)")
|
||||
let agentURL = bundle.appendingPathComponent("Contents/MacOS/ShadowsocksX-NG2Agent")
|
||||
guard
|
||||
let data = try? Data(contentsOf: plistURL),
|
||||
var plist = try? PropertyListSerialization.propertyList(from: data, format: nil)
|
||||
as? [String: Any]
|
||||
else {
|
||||
throw LaunchAgentPlistError.unreadable
|
||||
}
|
||||
plist["ProgramArguments"] = [agentURL.path]
|
||||
let updated = try PropertyListSerialization.data(
|
||||
fromPropertyList: plist, format: .xml, options: 0)
|
||||
try updated.write(to: plistURL, options: .atomic)
|
||||
}
|
||||
}
|
||||
|
||||
enum LaunchAgentPlistError: Error, Equatable {
|
||||
case unreadable
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user