MacOS自启动程序网络权限问题小记

记录MacOS上遇到的一个小问题

起因需要监控家里的MacOS电量,对低电量进行Hook,进入低电量后,执行shell命令,通知我。

让AI帮我写了以下脚本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
// LowPowerHook.swift
import Foundation

// 自定义日志输出函数,强制刷新缓冲区
func log(_ message: String) {
print(message)
fflush(stdout) // 核心修复点:强制写入磁盘
}

class PowerObserver {
init() {
// 监听低电量模式变化通知
NotificationCenter.default.addObserver(
self,
selector: #selector(powerStateChanged),
name: .NSProcessInfoPowerStateDidChange,
object: nil
)
}

@objc func powerStateChanged() {
let isLowPower = ProcessInfo.processInfo.isLowPowerModeEnabled

if isLowPower {
log("[\(Date())] 检测到:低电量模式已开启")
executeCommand(command: "COMMAND") // 替换为你的命令
} else {
log("[\(Date())] 检测到:低电量模式已关闭")
// 如果关闭时也想执行命令,可以加在这里
}
}

func executeCommand(command: String) {
let task = Process()
task.launchPath = "/bin/sh"
task.arguments = ["-c", command]

do {
try task.run()
} catch {
print("命令执行失败: \(error)")
}
}
}

let observer = PowerObserver()
log("正在监听 macOS 低电量模式变化...")

// 保持程序运行
RunLoop.main.run()

编译命令:

1
$ swiftc LowPowerHook.swift -o LowPowerHook

然后编写plist,让其自启,plist内容如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.mycustom.lowpowerhook</string>

<key>ProgramArguments</key>
<array>
<string>/xxx/powerMonitor/LowPowerHook</string>
</array>

<key>RunAtLoad</key>
<true/>

<key>KeepAlive</key>
<true/>

<key>StandardOutPath</key>
<string>/xxx/powerMonitor/Logs/LowPowerHook.log</string>
<key>StandardErrorPath</key>
<string>/xxx/powerMonitor/Logs/LowPowerHook-error.log</string>
</dict>
</plist>

放在以下目录:~/Library/LaunchAgents/com.mycustom.lowpowerhook.plist

启动命令:launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/com.mycustom.lowpowerhook.plist
卸载命令:launchctl bootout gui/$(id -u) ~/Library/LaunchAgents/com.mycustom.lowpowerhook.plist

但是遇到了一个网络问题,因为我执行的命令需要出网,错误如下所示:

1
2
$ tail -f Logs/LowPowerHook-error.log
ssh: connect to host 192.168.1.1 port 22: No route to host

但是如果我直接在终端启动LowPowerHook程序,却不会出现该错误。经过研究发现,launchctl控制的自启动程序需要获取LocalNetwork权限才能出网,iTerm已经有权限了,所以直接运行没问题。但是在设置界面中LocalNetwork权限界面无法进行添加或删除。

在这阶段卡了好久,相关的资料也特别少,在资料少的情况下AI自然也不太行了,给的方案唯一有效的是以root启动:

1
2
3
$ sudo mv ~/Library/LaunchAgents/com.mycustom.lowpowerhook.plist /Library/LaunchDaemons/
$ sudo chown root:wheel /Library/LaunchDaemons/com.mycustom.lowpowerhook.plist
$ sudo launchctl bootstrap system /Library/LaunchDaemons/com.mycustom.lowpowerhook.plist

的确,也是解决了。但是我不太想使用root权限执行该工具。随着不断搜索资料,逼迫AI,终于提供了解决方案:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
$ cat Info.plist
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleIdentifier</key>
<string>com.mycustom.lowpowerhook</string>
<key>CFBundleName</key>
<string>LowPowerHook</string>
<key>NSLocalNetworkUsageDescription</key>
<string>需要连接本地网络以执行 SSH 自动化命令。</string>
</dict>
</plist>
$ swiftc LowPowerHook.swift \
-Xlinker -sectcreate \
-Xlinker __TEXT \
-Xlinker __info_plist \
-Xlinker Info.plist \
-o LowPowerHook
codesign --force --sign - LowPowerHook

最重要的就是需要添加Info.plist信息,并且进行签名。然后在该程序进行网络请求时,就会弹窗询问是否运行。点击运行后,该程序在后台运行就能出网了。

之后搭建OpenClaw时也遇到该问题,没有给OpenClaw root权限,gateway自启动脚本也是在~/Library/LaunchAgents/目录下,在请求LLM时也一样会遇到网络问题,只需要对node程序进行签名,就能解决问题了。

MacOS自启动程序网络权限问题小记

https://nobb.site/2026/03/13/0x99/

Author

Hcamael

Posted on

2026-03-13

Updated on

2026-03-13

Licensed under