1. 前言

最近在公司做了个内部提效的飞书机器人,公司有台公共的mac mini,之前一直是手动打包好代码上传到mac mini上用 uv run python main.py 运行,可以说是非常不优雅了。

以前都是在 Linux 上用 systemctl 部署服务,没在 mac 弄过,查了一下 mac 系统上有个 launchd 用于管理服务,这篇文档记录一下第一次在 mac 上用 launchd 部署服务

2. launchctl 与 systemctl 的区别

功能 systemctl launchctl
主要配置文件 .service .plist
启动服务 systemctl start [name] launchctl bootstrap gui/$(id -u) [path]
停止服务 systemctl stop [name] launchctl bootout gui/$(id -u) [path]
开机自启 systemctl enable [name] 只要 .plist 文件放到特定目录,默认加载
查看状态 systemctl status [name] launchctl list [label]

服务配置文件位置

macOS 使用 Property List (.plist) 文件来定义服务。根据你想让服务以什么权限运行,存放路径也不同:

  • 用户级 Agent (~/Library/LaunchAgents): 只有当前用户登录后才运行,以该用户权限运行。

  • 系统级 Agent (/Library/LaunchAgents): 任何用户登录后都会运行。

  • 系统级 Daemon (/Library/LaunchDaemons): 开机即运行,通常以 root 权限运行(适合 Web 服务器、数据库等)。

3. 配置文件的编写

创建 ~/Library/LaunchAgents/com.yingdao-fj.cyber-monkey.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>Label</key>
    <string>com.yingdao-fj.cyber-monkey</string>

    <key>ProgramArguments</key>
    <array>
        <string>/opt/homebrew/bin/uv</string>
        <string>run</string>
        <string>python</string>
        <string>main.py</string>
        <string>--config</string>
        <string>/Users/shadowbotfj/.cyber-monkey/config.yaml</string>
    </array>

    <key>WorkingDirectory</key>
    <string>/Users/shadowbotfj/project/cyber-monkey</string>

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

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

    <key>StandardOutPath</key>
    <string>/dev/null</string>
    <key>StandardErrorPath</key>
    <string>/dev/null</string>

    <key>EnvironmentVariables</key>
    <dict>
        <key>PATH</key>
        <string>/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin</string>
        <key>PYTHONUNBUFFERED</key>
        <string>1</string>
    </dict>
</dict>
</plist>