Skip to content

macOS LaunchAgent 入门与本地服务常驻实践

什么是 LaunchAgent

LaunchAgent 是 macOS 提供的用户级后台服务机制,适合把“登录后就应该自动可用”的本地进程交给系统托管。

它的几个核心特点:

  • 跟随当前用户会话启动,不需要手动开终端
  • 可以设置 RunAtLoad,实现登录后自动拉起
  • 可以设置 KeepAlive,让服务退出后自动重启
  • 能为服务固定工作目录、环境变量、日志输出路径

如果一个本地服务满足下面任一条件,就很适合改成 LaunchAgent:

  • 每次开机或登录后都要用
  • 关闭终端后不应该中断
  • 需要固定本地端口和访问入口
  • 希望由系统自动守护,而不是手工 npm run dev

LaunchAgent 适合解决什么问题

日常开发里,最常见的问题不是“服务不会启动”,而是“服务只在当前终端活着”。

典型表现:

  • 浏览器能打开面板,但关掉终端后页面立刻 ERR_CONNECTION_REFUSED
  • 电脑重启后,本地控制台、文档站点、网关都要重新手动启动
  • 网关忘记启动时,飞书机器人或本地控制面板整体失效

这类问题本质上都不是业务逻辑错误,而是“进程生命周期没有交给操作系统管理”。

LaunchAgent 的价值就在这里:

  1. 把启动动作标准化
  2. 把运行时环境固定下来
  3. 把日志路径固定下来
  4. 把重启恢复交给系统

典型配置项

一个最常见的 LaunchAgent 配置会包含这些字段:

xml
<key>Label</key>
<string>ai.example.control-center</string>

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

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

<key>WorkingDirectory</key>
<string>/path/to/project</string>

<key>ProgramArguments</key>
<array>
  <string>/path/to/node</string>
  <string>/path/to/server.js</string>
</array>

<key>EnvironmentVariables</key>
<dict>
  <key>NODE_ENV</key>
  <string>production</string>
</dict>

<key>StandardOutPath</key>
<string>/path/to/out.log</string>

<key>StandardErrorPath</key>
<string>/path/to/error.log</string>

可以把它理解成“系统级的启动脚本声明文件”。

常用命令

bash
# 加载服务
launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/<label>.plist

# 重新拉起服务
launchctl kickstart -k gui/$(id -u)/<label>

# 查看服务状态
launchctl print gui/$(id -u)/<label>

# 卸载服务
launchctl bootout gui/$(id -u)/<label>

# 列出当前用户已加载服务
launchctl list

如果服务已经交给 LaunchAgent 管理,排查顺序通常是:

  1. launchctl print
  2. 看端口是否监听
  3. 看标准输出和错误日志
  4. 再看业务服务自己的健康检查接口

在本地 AI 工具链中的典型用法

LaunchAgent 特别适合托管下面这类本地 AI 服务:

  • 本地控制中心面板
  • 本地帮助中心或文档站点
  • 提供消息收发能力的网关服务
  • 需要长期轮询、监听或定时响应的用户级后台进程

一套比较常见的组合是:

  1. 网关负责连接本地工具与外部渠道
  2. 控制中心负责查看真实状态、日志和人工干预
  3. 帮助中心负责承接文档、说明和排障手册

这三类服务一旦都改成 LaunchAgent,日常体验会明显稳定很多:

  • 电脑重启后自动恢复
  • 终端关闭后仍可访问
  • 浏览器固定地址不变
  • 面板、网关、文档站点的运行状态更可预测

什么时候没必要用 LaunchAgent

不是所有东西都要常驻。

下面这些情况通常不值得:

  • 只在开发时临时运行的调试服务
  • 启动很重但使用频率很低的任务
  • 更适合用 cron、GitHub Actions 或 CI 跑的任务
  • 纯前端本地开发态热更新服务

判断标准很简单:

  • “每天都要重新开一次,而且关终端就挂”就值得
  • “偶尔用一次,随用随起”就不必强行常驻

设计建议

把本地服务做成 LaunchAgent 时,优先遵守这几条:

  1. 使用稳定运行时路径,不要依赖临时 shell 初始化状态。
  2. 给每个服务固定独立日志文件,方便排查。
  3. 生产态服务优先使用构建产物,不要直接常驻开发服务器。
  4. 把服务入口做成脚本,避免未来手工改多个 plist。
  5. 对外入口固定,对内实现可替换。

一句话总结

LaunchAgent 不是“高级技巧”,而是 macOS 上最合适的用户级服务托管方式。

只要你的本地服务满足“登录后要自动可用、关终端不能挂、需要长期稳定监听”这三个条件,就很适合改成 LaunchAgent。