macOS 自启动服务管理
macOS 使用 launchd
管理自启动服务,配置文件为 .plist
格式。
配置文件位置
- 用户级别:
~/Library/LaunchAgents/
- 系统级别:
/Library/LaunchAgents/
- 系统守护进程:
/Library/LaunchDaemons/
查看服务
# 查看所有服务
launchctl list
# 查看特定服务
launchctl list | grep 应用名
添加自启动服务
-
创建 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.example.myapp</string> <key>ProgramArguments</key> <array> <string>/path/to/your/app</string> </array> <key>RunAtLoad</key> <true/> <key>KeepAlive</key> <true/> </dict> </plist>
-
加载服务
# 加载用户级别服务 launchctl load ~/Library/LaunchAgents/com.example.myapp.plist
加载系统级别服务
sudo launchctl load /Library/LaunchDaemons/com.example.myapp.plist
### 移除自启动服务
1. **停止服务**
```bash
launchctl remove 服务名
# 或
sudo launchctl remove 服务名
-
删除配置文件
rm ~/Library/LaunchAgents/服务名.plist # 或 sudo rm /Library/LaunchAgents/服务名.plist sudo rm /Library/LaunchDaemons/服务名.plist
实战案例:RustDesk 自启动管理
查找 RustDesk 服务:
launchctl list | grep -i rustdesk
ls ~/Library/LaunchAgents/ | grep -i rustdesk
ls /Library/LaunchAgents/ | grep -i rustdesk
sudo ls /Library/LaunchDaemons/ | grep -i rustdesk
一键移除 RustDesk 自启动:
# 停止服务
launchctl remove com.rustdesk.service 2>/dev/null
launchctl remove com.carriez.RustDesk_server 2>/dev/null
sudo launchctl remove com.carriez.RustDesk_service 2>/dev/null
# 删除配置文件
rm ~/Library/LaunchAgents/com.rustdesk.service.plist 2>/dev/null
sudo rm /Library/LaunchAgents/com.carriez.RustDesk_server.plist 2>/dev/null
sudo rm /Library/LaunchDaemons/com.carriez.RustDesk_service.plist 2>/dev/null
# 验证清除结果
launchctl list | grep -i rustdesk
常用命令速查
# 查看服务状态
launchctl list 服务名
# 启动服务
launchctl start 服务名
# 停止服务
launchctl stop 服务名
# 重启服务
launchctl kickstart 服务名
# 卸载服务(临时)
launchctl unload 配置文件路径
# 加载服务
launchctl load 配置文件路径
注意事项
- 系统级别操作需要
sudo
权限 - 删除配置文件前建议备份
- 重启后验证服务状态
- 某些应用可能会重新创建自启动服务
添加自启动服务详解
服务添加步骤
- 创建 plist 文件
- 放置到对应目录
- 加载服务
- 验证运行状态
RustDesk 实际案例分析
LaunchAgent 配置(用户级别):
<!-- /Library/LaunchAgents/com.carriez.RustDesk_server.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.carriez.RustDesk_server</string>
<key>LimitLoadToSessionType</key>
<array>
<string>LoginWindow</string>
<string>Aqua</string>
</array>
<key>KeepAlive</key>
<dict>
<key>SuccessfulExit</key>
<false />
<key>AfterInitialDemand</key>
<false />
</dict>
<key>RunAtLoad</key>
<true />
<key>ProgramArguments</key>
<array>
<string>/Applications/RustDesk.app/Contents/MacOS/RustDesk</string>
<string>--server</string>
</array>
<key>WorkingDirectory</key>
<string>/Applications/RustDesk.app/Contents/MacOS/</string>
</dict>
</plist>
LaunchDaemon 配置(系统级别):
<!-- /Library/LaunchDaemons/com.carriez.RustDesk_service.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.carriez.RustDesk_service</string>
<key>KeepAlive</key>
<true/>
<key>ProgramArguments</key>
<array>
<string>/bin/sh</string>
<string>-c</string>
<string>/Applications/RustDesk.app/Contents/MacOS/service</string>
</array>
<key>RunAtLoad</key>
<true/>
<key>WorkingDirectory</key>
<string>/Applications/RustDesk.app/Contents/MacOS/</string>
<key>StandardErrorPath</key>
<string>/tmp/rustdesk_service.err</string>
<key>StandardOutPath</key>
<string>/tmp/rustdesk_service.out</string>
</dict>
</plist>
关键配置项说明
配置项 | 作用 | 示例值 |
---|---|---|
Label |
服务唯一标识 | com.carriez.RustDesk_server |
RunAtLoad |
启动时自动运行 | true |
KeepAlive |
进程保活策略 | true 或复杂字典 |
LimitLoadToSessionType |
限制加载的会话类型 | LoginWindow , Aqua |
ProgramArguments |
程序路径和参数 | 数组格式 |
WorkingDirectory |
工作目录 | /Applications/RustDesk.app/Contents/MacOS/ |
StandardOutPath |
标准输出日志 | /tmp/rustdesk_service.out |
StandardErrorPath |
错误输出日志 | /tmp/rustdesk_service.err |
部署策略对比
只添加 LaunchAgent:
# 创建文件
sudo cp com.carriez.RustDesk_server.plist /Library/LaunchAgents/
# 加载服务
sudo launchctl load /Library/LaunchAgents/com.carriez.RustDesk_server.plist
特点:
- ✅ 用户登录后启动
- ✅ 有 GUI 访问权限
- ❌ 用户未登录时无法远程连接
只添加 LaunchDaemon:
# 创建文件
sudo cp com.carriez.RustDesk_service.plist /Library/LaunchDaemons/
# 加载服务
sudo launchctl load /Library/LaunchDaemons/com.carriez.RustDesk_service.plist
特点:
- ✅ 系统启动即运行
- ✅ 无需用户登录
- ❌ 无 GUI 访问权限
- ❌ 功能可能受限
同时添加两者(RustDesk 策略):
# 添加 LaunchAgent
sudo cp com.carriez.RustDesk_server.plist /Library/LaunchAgents/
sudo launchctl load /Library/LaunchAgents/com.carriez.RustDesk_server.plist
# 添加 LaunchDaemon
sudo cp com.carriez.RustDesk_service.plist /Library/LaunchDaemons/
sudo launchctl load /Library/LaunchDaemons/com.carriez.RustDesk_service.plist
特点:
- ✅ 系统启动即有基础服务
- ✅ 用户登录后有完整功能
- ✅ 最佳的远程访问体验
- ❌ 资源占用稍高
验证服务状态
# 检查服务是否加载
launchctl list | grep -i rustdesk
# 检查进程是否运行
ps aux | grep -i rustdesk
# 查看日志
tail -f /tmp/rustdesk_service.out
tail -f /tmp/rustdesk_service.err
最佳实践建议
- 远程访问应用:推荐双重部署(Agent + Daemon)
- 用户工具:只需 LaunchAgent
- 系统服务:只需 LaunchDaemon
- 日志管理:设置合适的日志路径
- 权限控制:根据需要选择部署级别