在 macos 上配置系统服务与后台扩展插件,核心是创建并注册 .plist 格式的 launch agent 或 launch daemon 文件。launch agent 用于用户级后台任务,需放置在 ~/library/launchagents/ 目录;launch daemon 用于系统级服务,需放置在 /library/launchdaemons/ 目录。通过 launchctl load 命令加载配置文件即可启动服务,使用 launchctl unload 停止服务。

如何区分 Launch Agent 和 Launch Daemon 的使用场景
Launch Agent 和 Launch Daemon 的主要区别在于运行权限和生命周期。Launch Agent 以普通用户身份运行,随用户登录启动,适合处理用户特定的任务,如同步工具、即时通讯客户端等。Launch Daemon 以 root 权限运行,随系统启动,适合需要高权限的系统级服务,如网络守护进程、定时备份任务等。选择哪种类型取决于你的服务是否需要访问用户资源或系统底层接口。

{
"Label": "com.example.myagent",
"ProgramArguments": [
"/usr/local/bin/myapp",
"--config",
"/etc/myapp.conf"
],
"RunAtLoad": true,
"KeepAlive": false,
"StandardOutPath": "/tmp/myapp.log",
"StandardErrorPath": "/tmp/myapp_error.log"
}
上述示例是一个典型的 Launch Agent 配置。它指定了程序路径、参数、日志输出位置以及是否随登录启动。将此类文件保存为 com.example.myagent.plist 并放入 ~/Library/LaunchAgents/ 后,执行 launchctl load ~/Library/LaunchAgents/com.example.myagent.plist 即可生效。若需调试,可检查 /tmp/myapp.log 查看标准输出,或使用 log show --predicate 'process == "myapp"' --last 1m 查看系统日志。
如何编写一个自动重启的后台守护进程
对于需要持续运行并在崩溃后自动恢复的服务,应使用 KeepAlive 键配合 WatchPaths 或 StartOnMount 等条件。Launch Daemon 更适合此类场景,因为它具有更高的优先级和更稳定的生命周期。通过设置 KeepAlive 为 true,系统在进程退出时会立即重启它。结合 WatchPaths 可以监控特定文件或目录的变化来触发启动,实现事件驱动的后台服务。

{
"Label": "com.example.daemon",
"ProgramArguments": [
"/usr/sbin/mydaemon",
"-d"
],
"KeepAlive": {
"SuccessfulExit": false,
"NetworkState": true
},
"WatchPaths": [
"/var/log/system.log"
],
"StandardOutPath": "/var/log/mydaemon.log",
"StandardErrorPath": "/var/log/mydaemon_err.log"
}
此配置定义了一个 Launch Daemon,它在非正常退出时重启,并在网络状态变化时启动。同时,它监控 /var/log/system.log 文件,一旦该文件被修改(如写入新日志),守护进程会被唤醒。这种模式常用于日志聚合器或安全审计工具。注意,由于涉及系统日志监控,可能需要授予“完全磁盘访问权限”或在 SIP 关闭环境下运行。实际部署时,务必确保程序能正确处理信号量,避免僵尸进程堆积。
当服务无法启动时如何通过日志排查具体错误
服务加载失败通常由 plist 语法错误、权限不足或依赖缺失引起。首先使用 launchctl load -S Aqua -v /path/to/plist 命令加载,-v 参数会输出详细错误信息。常见错误包括:XML 格式非法、缺少 Label 字段、程序路径不存在或无执行权限。若服务已加载但立即退出,需检查 StandardOutPath 和 StandardErrorPath 指定的日志文件,或使用 log stream --predicate 'subsystem == "com.apple.launchd"' 过滤相关日志。此外,可通过 launchctl list com.example.service 查看服务当前状态码,负值表示异常终止,正值表示正常运行。











