在 macOS 中运行命令行程序,如果你不想开一个终端窗口,并且希望实现开机自启动等等功能,可以使用 macOS 自带的服务管理。这里以 easytier 这个组网工具为例:
直接执行的命令是:/usr/local/bin/easytier-core -c /Users/iuxt/config/easytier.toml
plist 分为系统级别和用户级别,分别位于:
特性
LaunchAgents (用户代理)
LaunchDaemons (守护进程)
运行时机
用户登录后启动
系统开机时启动,即用户登录前
运行用户
当前登录的用户
一般为 root 或指定的其他用户
适用场景
需要 GUI 界面、用户偏好设置或访问用户目录的服务
需要高权限、不依赖用户界面的后台服务,如 Web 服务器、数据库等
存放路径
~/Library/LaunchAgents/ (当前用户) /Library/LaunchAgents/ (所有用户)
/Library/LaunchDaemons/
加载命令
launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/com.example.app.plist
sudo launchctl bootstrap system /Library/LaunchDaemons/com.example.app.plist
系统级别服务 配置文件 vim /Library/LaunchDaemons/easytier.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 25 26 27 28 29 30 31 32 33 34 35 36 <?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 > easytier</string > <key > ProgramArguments</key > <array > <string > /usr/local/bin/easytier-core</string > <string > -c</string > <string > /Users/iuxt/config/easytier.toml</string > </array > <key > UserName</key > <string > root</string > <key > GroupName</key > <string > wheel</string > <key > InitGroups</key > <true /> <key > RunAtLoad</key > <true /> <key > KeepAlive</key > <true /> <key > WorkingDirectory</key > <string > /usr/local/bin</string > <key > StandardOutPath</key > <string > /var/log/easytier.log</string > <key > StandardErrorPath</key > <string > /var/log/easytier-error.log</string > </dict > </plist >
配置权限 1 2 sudo chown root:wheel /Library/LaunchDaemons/easytier.plist sudo chmod 644 /Library/LaunchDaemons/easytier.plist
启动 1 sudo launchctl bootstrap system /Library/LaunchDaemons/easytier.plist
bootstrap 命令会同时完成“安装”和“根据 RunAtLoad 配置决定是否启动”两个步骤。 gui/$(id -u) 是当前用户的 “ 域 “ (domain),system 则是系统的域。
卸载服务 1 2 3 4 sudo launchctl bootout system /Library/LaunchDaemons/easytier.plist sudo rm -rf /Library/LaunchDaemons/easytier.plist
用户级别服务 配置文件 vim ~/Library/LaunchAgents/picup.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 25 <?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 > picup</string > <key > ProgramArguments</key > <array > <string > /Users/iuxt/code/picup/picup</string > </array > <key > WorkingDirectory</key > <string > /Users/iuxt/code/picup/</string > <key > RunAtLoad</key > <true /> <key > KeepAlive</key > <true /> <key > StandardOutPath</key > <string > /Users/iuxt/code/picup/logs/stdout.log</string > <key > StandardErrorPath</key > <string > /Users/iuxt/code/picup/logs/stderr.log</string > </dict > </plist >
启动 1 launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/picup.plist
停止服务
卸载服务 1 launchctl bootout gui/$(id -u)/picup
从对应的目录中删除 .plist 文件。
1 rm -rf ~/Library/LaunchAgents/picup.plist