MacOS launchd plist FAQ: Can you share some examples of how to use the MacOS launchd
plist file StartInterval
and StartCalendarInterval
keys?
Sure, here's a quick look at the MacOS launchd StartInterval and StartCalendarInterval keys. These two keys can be used to represent time values in a Mac launchd
plist file, and many people have questions about them.
MacOS launchd plist StartInterval examples
The general syntax for the MacOS launchd
plist StartInterval
key is shown here:
StartInterval <integer>
which, in a launchd
plist file, looks like this:
<key>StartInterval</key> <integer>60</integer>
From Apple's launchd plist man page, the StartInterval
key is described like this:
“This optional key causes the job to be started every N seconds. If the system is asleep, the job will be started the next time the computer wakes up. If multiple intervals transpire before the computer is woken, those events will be coalesced into one event upon wake from sleep.”
In English, this means that any job you specify with the "60" second StartInterval
shown above will be run about every 60 seconds.
If you have experience with the standard Unix and Linux crontab approach, you would simply put an "*" symbol in the minute's field to represent the "60" seconds shown in the XML above.
MacOS launchd StartCalendarInterval examples
The syntax for the MacOS launchd plist StartCalendarInterval
key is shown here:
StartCalendarInterval <dictionary of integers or array of dictionary of integers>
And here is the description of the launchd
plist StartCalendarInterval
key from from Apple's launchd plist man page:
“This optional key causes the job to be started every calendar interval as specified. Missing arguments are considered to be wildcard. The semantics are much like crontab(5). Unlike cron which skips job invocations when the computer is asleep, launchd
will start the job the next time the computer wakes up. If multiple intervals transpire before the computer is woken, those events will be coalesced into one event upon wake from sleep.”
You can specify StartCalendarInterval
times using these time keys:
Minute <integer> The minute on which this job will be run. Hour <integer> The hour on which this job will be run. Day <integer> The day on which this job will be run. Weekday <integer> The weekday on which this job will be run (0 and 7 are Sunday). Month <integer> The month on which this job will be run.
Since I learn best by example, I dug around through some sample launchd
plist files until I found these StartCalendarInterval examples.
I believe this example means run at the 0th minute of every hour of every day:
<key>StartCalendarInterval</key> <dict> <key>Minute</key> <integer>0</integer> </dict>
This StartCalendarInterval
example should mean "run at 3:55" every day, where I think this implies 3:55 am.
<key>StartCalendarInterval</key> <dict> <key>Hour</key> <integer>3</integer> <key>Minute</key> <integer>55</integer> </dict>
This next StartCalendarInterval
example is similar to the previous one, but the job is only run on Day 6 of the week, which should be Saturday.
<key>StartCalendarInterval</key> <dict> <key>Hour</key> <integer>3</integer> <key>Minute</key> <integer>15</integer> <key>Weekday</key> <integer>6</integer> </dict>
(Personally, I think if you're going through all this trouble to put this stuff in XML you should be able to use "Sat" or "Saturday" here.)
StartCalendarInterval and running every day of the week
In a related note, this is the approach that seems to be required to run a script or command every day of the work week, Monday through Friday:
<key>StartCalendarInterval</key> <array> <!-- SUNDAY (testing) --> <dict> <key>Weekday</key> <integer>0</integer> <key>Hour</key> <integer>16</integer> <key>Minute</key> <integer>00</integer> </dict> <dict> <key>Weekday</key> <integer>1</integer> <key>Hour</key> <integer>11</integer> <key>Minute</key> <integer>0</integer> </dict> <dict> <key>Weekday</key> <integer>2</integer> <key>Hour</key> <integer>11</integer> <key>Minute</key> <integer>0</integer> </dict> <dict> <key>Weekday</key> <integer>3</integer> <key>Hour</key> <integer>11</integer> <key>Minute</key> <integer>0</integer> </dict> <dict> <key>Weekday</key> <integer>4</integer> <key>Hour</key> <integer>11</integer> <key>Minute</key> <integer>0</integer> </dict> <dict> <key>Weekday</key> <integer>5</integer> <key>Hour</key> <integer>11</integer> <key>Minute</key> <integer>0</integer> </dict> </array>
While the approach is verbose, I can verify that it works. The first “Sunday” entry is for tests that I ran when I was creating my plist file, and the other entries are for Monday through Friday. Note that the integer value for Sunday is both 0 and 7, so you can use either of those for its Weekday
entry.
launchd plist StartInterval and StartCalendarInterval examples - summary
I hope these launchd
plist StartInterval
and StartCalendarInterval
key examples are helpful. As you can see, the StartInterval
key is for simple "run every XX seconds", while StartCalendarInterval
is used for more complicated timings with launchd jobs. For more information, please see the link to the Apple docs above, or take a look at my Mac startup jobs with launchd plist (instead of cron/crontab) tutorial.