launchd
launchd is an init and operating system service management daemon created by Apple Inc. as part of macOS to replace its BSD-style init and SystemStarter. There have been efforts to port launchd to FreeBSD and derived systems.
如 维基百科 所说,launchd 是 MacOS 上所使用的一套服务管理框架。它作为系统启动的第一个进程,系统的其它进程均由它直接或间接创建。
➜ hunterx.xyz git:(master) ✗ ps -ef | grep launchd | grep -v grep
0 1 0 0 25 623 ?? 272:23.76 /sbin/launchd
213 546 1 0 25 623 ?? 4:06.61 /System/Library/PrivateFrameworks/MobileDevice.framework/Versions/A/Resources/usbmuxd -launchd
0 567 1 0 25 623 ?? 26:32.81 /usr/libexec/corebrightnessd --launchd
0 582 1 0 25 623 ?? 0:13.89 /System/Library/CoreServices/backupd.bundle/Contents/Resources/backupd-helper -launchd
501 1345 1 0 25 623 ?? 0:14.19 /System/Library/PrivateFrameworks/AMPDevices.framework/Versions/A/Support/AMPDeviceDiscoveryAgent --launchd
501 1653 1 0 25 623 ?? 3:26.36 /System/Library/CoreServices/Siri.app/Contents/MacOS/Siri launchd
501 1658 1 0 25 623 ?? 0:24.43 /System/Library/CoreServices/AirPlayUIAgent.app/Contents/MacOS/AirPlayUIAgent --launchd
501 48141 1 0 9:05上午 ?? 0:12.19 /System/Library/PrivateFrameworks/AMPDevices.framework/Versions/A/Support/AMPDevicesAgent --launchd
0 60348 1 0 18 823 ?? 0:00.08 /usr/libexec/xpcroleaccountd -launchd
0 61549 1 0 18 823 ?? 0:02.47 /usr/libexec/biometrickitd --launchd
501 72715 1 0 19 823 ?? 0:04.52 /System/Library/PrivateFrameworks/AMPLibrary.framework/Versions/A/Support/AMPLibraryAgent --launchd
501 72843 1 0 19 823 ?? 0:00.15 /System/Library/PrivateFrameworks/AMPLibrary.framework/Versions/A/Support/AMPArtworkAgent --launchd
在 Linux 系统下,有一个与之对应的进程为 systemd,它的对应管理工具为 systemctl,launchd 的管理工具就是下文所要介绍的 launchctl。
plist 文件
launchd 对一个服务的管理行为需要记录在以 .plist 为后缀的 xml 文件中,通常我们将这类文件称为 plist 文件。plist 的定义语法可以参考 文档,以下是一个简单的示例:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC -//Apple Computer//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.exampled</string>
<key>ProgramArguments</key>
<array>
<string>exampled</string>
</array>
<key>KeepAlive</key>
<true/>
</dict>
</plist>
不同类型的 plist 文件存放的目录和运行用户有所不同:
| 类型 | 路径 | 说明 |
|---|---|---|
| User Agents | ~/Library/LaunchAgents | 为当前登录用户启动 |
| Global Agents | /Library/LaunchAgents | 为当前登录用户启动 |
| Global Daemons | /Library/LaunchDaemons | root 或者通过 UserName 配置指定的用户 |
| System Agents | /System/Library/LaunchAgents | 当前登录用户 |
| System Daemons | /System/Library/LaunchDaemons | root 或者通过 UserName 配置指定的用户 |
launchctl 使用
使用 launchctl 可以非常方便地对查询/添加/删除服务,以下是我经常使用到的一些命令:
# 列出当前加载的服务
launchctl list
# 卸载某一个服务
launchctl unload xyz.hunterx.plist
# 加载某一个服务
launchctl load xyz.hunterx.plist
# 无视 Disabled 配置值,加载并启动某一个服务
launchctl load -w xyz.hunterx.plist
注意事项
-
如果一个服务之前已经被加载,使用
launchctl load命令时会报错,可以尝试先对服务进行卸载:launchctl list | grep xyz.hunterx.plist && launchctl unload xyz.hunterx.plist -
如果启动的服务需要一些环境变量(如用户登录后自动 source 引入的变量),需要在配置中使用
EnvironmentVariables定义:<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC -//Apple Computer//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.exampled</string> <key>ProgramArguments</key> <array> <string>exampled</string> </array> <key>KeepAlive</key> <true/> <key>EnvironmentVariables</key> <dict> <key>PYTHON_PATH</key> <key>/usr/bin/python</key> </dict> </dict> </plist>