launchd
launchd
– 系统范围内的守护进程(LaunchDaemons
)/代理程序(LaunchAgents
)的主程序
在启动过程中,内核调用 launchd
作为第一个进程运行,并进一步引导系统的其余部分。
守护进程和服务启动图例
根据定义,守护进程是系统范围的服务,其中所有客户端都有一个实例。 代理是一种服务,以每个用户为基础运行。
守护进程不应尝试显示 UI
或直接与用户的登录会话交互。 所有涉及与用户交互地应通过代理服务完成,如:运行程序,显示 UI
。
路径说明
路径 | 加载 | 说明 |
---|---|---|
/System/Library/LaunchDaemons | 系统启动 | 提供系统范围的守护进程(Apple) |
/System/Library/LaunchAgents | 系统启动 | 提供系统范围的用户代理(Apple) |
/Library/LaunchDaemons | 用户登录 | 提供所有用户的守护进程 |
/Library/LaunchAgents | 用户登录 | 提供所有用户的代理进程 |
~/Library/LaunchAgents | 用户登录 | 提供当前用户的代理进程 |
更多具体信息查看系统帮助文档:launchd
launchd.plist
launchd.plist
– 系统范围内的守护进程(LaunchDaemons
)/代理程序(LaunchAgents
)的配置文件
可以使用 launchctl
加载到 launchd
的列表,并根据配置文件的具体参数属性进行配置加载运行。
配置文件的命名
文件命名为 <Label>.plist
。 因此,如果您的工作标签(Label
)是 com.ichochy.test
,您的 plist
文件应命名为:com.ichochy.test.plist
参数属性
- Label
- 作业进程的唯一标识,是必要参数
- Program
- 作业执行的命令
- ProgramArguments
- 作业执行的参数
- 第一个参数为作业执行的命令,
Program
存在时,将由Program
替代 - 从第二个参数开始为执行的参数
- KeepAlive
- 作业进程是否保留运行
false
为默认值,停止后不再保留运行true
,停止后再次启动运行- SuccessfulExit
- NetworkState
- PathState
- Crashed
- RunAtLoad
false
为默认值,启动加载时不启动运行true
,启动加载时启动运行
- WorkingDirectory
- 工作目录
- EnvironmentVariables
- 配置环境变量
- TimeOut
- 启动超时时间
- ExitTimeOut
- 退出超时时间
- ThrottleInterval
- 间歇时间
- StartInterval
- 间隔启动时间,单位为秒
- StartCalendarInterval
- 间隔启动时间,单位可以指定日期
- Minute
- 分钟 0-59
- Hour
- 小时 0-23
- Day
- 天 1-31
- Weekday
- 工作日 0-7
- Month
- 月 1-12
- StandardInPath
- stdin 输入信息的日志路径
- StandardOutPath
- stdout 输出信息的日志路径
- StandardErrorPath
- stderr 错误输出信息的日志路径
- ProcessType
- 进程类型,根据作业类型限制应用资源
- Background
- Standard
- Adaptive
- Interactive
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.ichochy.example</string>
<key>Program</key>
<string>/path/tp/example</string>
<key>ProgramArguments</key>
<array>
<string>example</string>
<string>argv1</string>
<string>argv2</string>
</array>
<key>MachServices</key>
<dict>
<key>com.ichochy.example</key>
<true/>
</dict>
</dict>
</plist>
“Hello World!” launchd Job
<?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.ichochy.hello</string>
<key>ProgramArguments</key>
<array>
<string>hello</string>
<string>world</string>
</array>
<key>KeepAlive</key>
<true/>
</dict>
</plist>
Debugging launchd Jobs
<?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.ichochy.sleep</string>
<key>ProgramArguments</key>
<array>
<string>sleep</string>
<string>100</string>
</array>
<key>StandardOutPath</key>
<string>/var/log/myjob.log</string>
<key>StandardErrorPath</key>
<string>/var/log/myjob.log</string>
<key>Debug</key>
<true/>
<key>SoftResourceLimits</key>
<dict>
<key>Core</key>
<integer>9223372036854775807</integer>
</dict>
<key>HardResourceLimits</key>
<dict>
<key>Core</key>
<integer>9223372036854775807</integer>
</dict>
</dict>
</plist>
Running a Job Periodically
<?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.ichochy.touchsomefile</string>
<key>ProgramArguments</key>
<array>
<string>touch</string>
<string>/tmp/helloworld</string>
</array>
<key>StartInterval</key>
<integer>300</integer>
</dict>
</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.ichochy.touchsomefile</string>
<key>ProgramArguments</key>
<array>
<string>touch</string>
<string>/tmp/helloworld</string>
</array>
<key>StartCalendarInterval</key>
<dict>
<key>Minute</key>
<integer>45</integer>
<key>Hour</key>
<integer>13</integer>
<key>Day</key>
<integer>7</integer>
</dict>
</dict>
</plist>
Monitoring a Directory
<?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.ichochy.watchhostconfig</string>
<key>ProgramArguments</key>
<array>
<string>syslog</string>
<string>-s</string>
<string>-l</string>
<string>notice</string>
<string>somebody touched /etc/hostconfig</string>
</array>
<key>WatchPaths</key>
<array>
<string>/etc/hostconfig</string>
</array>
</dict>
</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.ichochy.mailpush</string>
<key>ProgramArguments</key>
<array>
<string>my_custom_mail_push_tool</string>
</array>
<key>QueueDirectories</key>
<array>
<string>/var/spool/mymailqdir</string>
</array>
</dict>
</plist>
更多具体信息查看系统帮助文档:launchd.plist
launchctl
launchctl
– launchd
的管理工具
通过 launchctl
交互来管理和检查 launchd
守护进程、代理进程和 XPC
服务。
命令执行
launchctl subcommand [arguments ...]
显示加载列表
launchctl list
基本操作
# enable | disable
launchctl enable com.ichochy.example.plist #启用 plist
launchctl disable com.ichochy.example.plist #禁用 plist
# load | unload
launchctl load com.ichochy.example.plist #加载 plist
launchctl unload com.ichochy.example.plist #卸载 plist
#加载/卸载 plist,
# 参数 w 覆盖操作
# 参数 F 强制操作
launchctl load/unload [-wF] plist
# start | stop | remove
launchctl start com.ichochy.example #启动 plist
launchctl stop com.ichochy.example #停止 plist
launchctl remove com.ichochy.example #删除 plist
更多具体信息查看系统帮助文档:launchctl
查看日志
launchctl
操作时,出现错误后,可以查看launchd
日志,了解具体的错误信息
命令查看launchd
日志
tail -f /private/var/log/com.apple.xpc.launchd/launchd.log
控制台
应用查看launchd
日志
- 在
应用程序
中的实用工具
中找到控制台
,并打开 - 切换到
日志报告
,找到launchd.log,并打开,就可以查看launchd
日志
参考引用
launchd
launchd.plist
launchctl
https://developer.apple.com/
https://www.launchd.info/