文章目录
  1. 1. 前言
  2. 2. launchd
    1. 2.1. 文件配置
    2. 2.2. Example
    3. 2.3. 加载命令
  3. 3. 断电和睡眠的影响
  4. 4. FQA
  5. 5. 参考资料
  6. 6. 文档信息

前言


在 macOS 系统中,你能够通过两种方式定时完成后台执行任务:launchd 和 cron 。虽然系统支持 cron 方式,但是并不推荐使用,它将被废弃,由 launchd 代替。

launchd


macOS 使用 launchd 进程来管理守护进程和代理,而您还可以用它来运行 shell 脚本。您不与 launchd 直接交互,而是使用 launchctl 命令来载入或卸载 launchd 守护进程和代理。

在系统启动期间,launchd 是内核在设置电脑时首先运行的进程。若您想要 shell 脚本作为守护进程运行,应由 launchd 来启动它。其他用于启动守护进程和代理的机制可能会被 Apple 酌情移除。

Property list files describing daemons are installed in /Library/LaunchDaemons, and those describing agents are installed in /Library/LaunchAgents or in the LaunchAgents subdirectory of an individual user’s Library directory

FILES PATH:

1
2
3
4
5
6
7
8
9
10
11
12
13
仅适用于登录用户的第三方代理:
~/Library/LaunchAgents Per-user agents provided by the user.

基于每个用户且所有用户适用的第三方代理:
/Library/LaunchAgents Per-user agents provided by the administrator.

第三方系统守护进程:
/Library/LaunchDaemons System-wide daemons provided by the administrator.
Apple 提供的基于每个用户且所有用户适用的代理:
/System/Library/LaunchAgents Per-user agents provided by OS X.

Apple 提供的系统守护进程:
/System/Library/LaunchDaemons System-wide daemons provided by OS X.

文件配置


下面仅列出 Example Plist 中用到的主要的 Property Keys,您可以在终端中运行 man launchd.plist 查看全部参数和用法。


1
2
3
4
5
6
7
Label <string> (必须,独一无二)
Program <string> (必须)
ProgramArguments <array of strings>
StartInterval <integer>
StartCalendarInterval <dictionary of integers or array of dictionaries of integers>
StandardOutPath <string>
StandardErrorPath <string>

关于 StartCalendarInterval:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Minute <integer>
The minute (0-59) on which this job will be run.

Hour <integer>
The hour (0-23) on which this job will be run.

Day <integer>
The day of the month (1-31) on which this job will be run.

Weekday <integer>
The weekday on which this job will be run (0 and 7 are Sunday). If both Day and Weekday are specificed, then the job will be started if either
one matches the current date.

Month <integer>
The month (1-12) on which this job will be run.

Example


一、使用 StartInterval 键可设置 每隔 N 秒执行定时任务
com.devhitao.blog.plist

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?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.devhitao.blog</string>
<key>ProgramArguments</key>
<array>
<string>touch</string>
<string>/Users/devhitao/Desktop/launchd/xx.sh</string>
</array>
<key>StartInterval</key>
<integer>15</integer>
<key>StandardOutPath</key>
<string>/Users/devhitao/Desktop/logs/xktlog</string>
<key>StandardErrorPath</key>
<string>/Users/devhitao/Desktop/logs/xkterr</string>
</dict>
</plist>

二、使用 StartCalendarInterval 键可设置 某个时刻执行任务
blog.devhitao.com.plist

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?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>blog.devhitao.com</string>
<key>ProgramArguments</key>
<array>
<string>/Users/devhitao/Desktop/launchd/xx.sh</string>
</array>
<key>StartCalendarInterval</key>
<dict>
<key>Minute</key>
<integer>14</integer>
<key>Hour</key>
<integer>13</integer>
</dict>
<key>StandardOutPath</key>
<string>/Users/devhitao/Desktop/logs/xktlog</string>
<key>StandardErrorPath</key>
<string>/Users/devhitao/Desktop/logs/xkterr</string>
</dict>
</plist>

加载命令


将上述 plist 文件放到 /Library/LaunchAgents/Library/LaunchDaemons 等路径下,这里我放在 ~/Library/LaunchAgents 下。

1
2
3
$ launchctl load blog.devhitao.com.plist  #加载的系统中
$ launchctl unload blog.devhitao.com.plist #从系统中卸载
$ launchctl list # 查看 launchctl 列表

为了检测 定时任务 是否能够正常运行,可以使用 start 进行测试,eg:

1
2
$ launchctl start blog.devhitao.com     #立即执行,无需等待触发条件成立
$ launchctl stop blog.devhitao.com #停止执行或触发

注意:一定要对应关系顺序执行命令,不然有意想不到的事情发生哦!先 load, 后 unload;先 load,后 start;先 start,后 stop;先 load,后 start。

断电和睡眠的影响


为了让定时任务顺利执行,在不关机的情况下,我们可以阻止电脑自动进入睡眠状态。勾选“当显示器关闭时,防止电脑自动进入睡眠” 选框,同时接上 电源适配器 来阻止电脑睡眠。

当关闭显示器时,阻止电脑进入睡眠。
当显示器关闭时,接上电源适配器防止电脑自动进入睡眠。

所以,可以将这个方法 与 StartCalendarInterval 键设置的定时任务结合起来,让定时任务在某个时刻顺利执行。

原文:

If the system is turned off or asleep, cron jobs do not execute; they will not run until the next designated time occurs.

如果系统处于关闭或睡眠,cron 作业不能给执行;在下一个触发之前,他们也不会运行。

If you schedule a launchd job by setting the StartCalendarInterval key and the computer is asleep when the job should have run, your job will run when the computer wakes up. However, if the machine is off when the job should have run, the job does not execute until the next designated time occurs.

如果通过 StartCalendarInterval 键设置 launchd 调度作业,当作业将要运行而电脑处于睡眠时,该作业将在电脑唤醒时执行。然而,如果将运行作业的机器被关闭,该作业任务在下个时间触发才会运行。

All other launchd jobs are skipped when the computer is turned off or asleep; they will not run until the next designated time occurs.

关闭电脑或使其进入睡眠状态时,所有 lanuchd 作业被跳过,它们将在下个时间触发时运行。

Consequently, if the computer is always off at the job’s scheduled time, both cron jobs and launchd jobs never run. For example, if you always turn your computer off at night, a job scheduled to run at 1 A.M. will never be run.

所以,如果电脑始终在任务预定时间关闭,cron 和 launchd 作业都不会运行。例如:如果你总是在晚上关闭电脑,而计划在凌晨 1 点运行该作业,它将永远不会运行。

FQA


1、如果遇到类似这样的问题 Sandbox: bash(xxxx) System Policy: deny(1) file-read-data /path/blog.devhitao.com.sh, 是权限不够,需要赋予访问权限。在 系统偏好设置 -> 安全与隐私 -> 隐私 可以找到,这里我将 bash 赋予 完全磁盘访问权限 。如果点击 + 没有找到想要的,可以使用拖拽方式。eg:

安全与隐私 -> 隐私
赋予磁盘访问权限

参考资料


文档信息


  • 版权声明:自由转载-保持署名-非商用-非衍生 ( CC BY-NC-ND 4.0 )
文章目录
  1. 1. 前言
  2. 2. launchd
    1. 2.1. 文件配置
    2. 2.2. Example
    3. 2.3. 加载命令
  3. 3. 断电和睡眠的影响
  4. 4. FQA
  5. 5. 参考资料
  6. 6. 文档信息