macOS 服务需用 launchd 实现自动重启与监控,通过 KeepAlive、ThrottleInterval 等配置控制重启行为,辅以健康检查脚本和 log 命令排查问题。

macOS 系统本身不使用 systemd,而是依赖 launchd 管理服务生命周期。要实现服务状态实时监控与异常自动重启,需围绕 launchd 的配置机制展开,结合系统日志、健康检查脚本和合理重试策略来补足原生能力的限制。
用 launchd 配置服务自动重启
launchd 支持在进程意外退出时自动拉起服务,但不像 systemd 那样提供细粒度的重启策略(如仅对非零退出码重启)。关键在于正确设置 KeepAlive 和退出条件:
-
KeepAlive true:只要进程退出就立即重启(等效于 systemd 的Restart=always) -
KeepAlive { "Crashed" = true; }:仅当进程崩溃(信号终止或非正常退出)时重启 -
StartInterval 30:每30秒尝试启动一次(适合无守护模式的脚本,需配合RunAtLoad false避免开机即跑) -
ThrottleInterval 60:60秒内最多重启一次,防雪崩(类似 systemd 的StartLimit*)
添加健康检查与主动恢复逻辑
纯依赖 launchd 无法判断服务“假死”(进程存活但不响应请求)。建议在服务启动脚本中嵌入轻量级自检,并通过外部触发器增强可靠性:
- 写一个 shell 脚本定期调用
curl -f http://localhost:8080/health或检测端口连通性(lsof -i :8080),失败则执行launchctl kickstart -k gui/$(id -u)/your.service - 将该脚本设为另一个 launchd 定时任务(
StartCalendarInterval),每2分钟运行一次 - 避免用
kill -9强杀主进程;优先发SIGTERM并等待优雅退出,再由 launchd 按配置决定是否重启
实时查看服务运行状态与日志
macOS 原生日志统一由 log 命令管理,launchd 服务的日志默认归入 Unified Logging 系统:
- 查服务当前状态:
launchctl list | grep your.service(看 PID 和最后一次退出状态) - 查实时日志:
log stream --predicate 'subsystem == "your.service.identifier"' --info --debug - 查历史错误:
log show --predicate 'eventMessage contains "error" && subsystem == "your.service.identifier"' --last 24h - 若服务输出到文件,可在 launchd plist 中配置:
<key>StandardOutPath</key><string>/var/log/your-service.log</string>
排查重启失败或频繁崩溃
当服务反复启动又退出,需从三个层面交叉验证:
-
退出码分析:在 plist 中加
<key>StandardErrorPath</key><string>/var/log/your-service.err</string>,捕获 stderr 输出 -
系统资源限制:检查是否因内存不足被 Jetsam 杀掉(
log show --predicate 'eventMessage contains "Jetsam"' --last 1h) -
权限与路径问题:确保
User字段指定的用户对ProgramArguments中所有路径有执行权,尤其注意 SIP 对 /usr/bin 下符号链接的限制










