Replacing Cron Jobs With Launchd on OS X
Several basic setup tasks on OS X Server — especially those related to maintaining backups — can be made easier via launchd, OS X’s replacement for cron.
On Mac OS X, the venerable cron
has been deprecated since 10.4, so if you’d like to schedule jobs to run at particular intervals on your OS X Server, the preferred approach is to use launchd
instead. Scheduling jobs with launchd
is a little more involved than with , but it’s not too onerous.
In place of a single crontab
scheduling actions for each user on the server, launchd
draws on a collection of .plist
files stored in various locations depending on whether the actions are to be scheduled for individual users or for the server as a whole. Although it might seem unnecessarily complicated at first glance, it’s the splitting up of each task specification into an individual, structured plist which brings a great deal more flexibility to the launchd
system than was possible with single lines in a crontab
.
To schedule a task with launchd
so it will run regardless of whether a specific individual user is logged in, begin by creating a .plist
file and dropping it into /Library/LaunchDaemons/
. Individual jobs can be enabled or disabled, respectively, with the following two lines:
sudo launchctl load /Library/LaunchDaemons/example.plist
sudo launchctl unload /Library/LaunchDaemons/example.plist
The structure of a basic launchd
plist looks like this, with two optional extras that are particularly useful when scheduling for a server, an array for StartCalendarInterval
and a specific UserName
key:
<?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>launchd_example</string> <key>ProgramArguments</key> <array> <string>touch</string> <string>/Users/myusername/example.txt</string> <string>sleep</string> <string>10</string> </array> <key>QueueDirectories</key> <array/> <key>StartCalendarInterval</key> <array> <dict> <key>Hour</key> <integer>2</integer> <key>Minute</key> <integer>0</integer> <key>Weekday</key> <integer>2</integer> </dict> <dict> <key>Hour</key> <integer>2</integer> <key>Minute</key> <integer>0</integer> <key>Weekday</key> <integer>5</integer> </dict> </array> <key>UserName</key> <string>myusername</string> <key>WatchPaths</key> <array/> </dict> </plist>
This example, which would be saved as launchd_example.plist
, will touch
/Users/myusername/example.txt
every Tuesday and Friday at 2:00 a.m. and then wait for 10 seconds before finishing. There are several other ways of scheduling described in Apple’s documentation, but I’ve chosen this particular method because it corresponds to a commonly used pattern for cron
jobs, where you may be accustomed to configuring a cron
job to run on certain days of the week at certain times.
In addition, this example demonstrates the use of the ‘UserName’ key. On a server, we almost always want to specify system-level jobs rather than user-level jobs, since the latter run only when a given user is logged in. But system-level jobs normally run as root. If we don’t need or want that for whatever reason, we can simply specify the name of the user under which the job should be run. The job will still run regardless of whether that user is logged in, but it will run as that user. Generally speaking, it is preferable to take jobs which do not need root access and run them as a user other than root. For example, if you’re expiring site-specific cache files that have been generated by code running as Apache on a given site, these jobs can be run as the ‘_www’ user, thereby avoiding any risks inherent in running them as root.
It is worth reading Apple’s documentation about launchd
, by the way, as it includes some important little nuggets, such as:
Important: If your daemon shuts down too quickly after being launched,
launchd
may think it has crashed. Daemons that continue this behavior may be suspended and not launched again when future requests arrive. To avoid this behavior, do not shut down for at least 10 seconds after launch.
(Thus the 10-second wait included in the above example.)
Finally, note that you can edit plist files either manually with a plain text editor, or with one of several editors able to speak plist, including Xcode. Lingon was a popular graphical front-end specifically intended for editing launch agents and launch daemons, and in fact the original (free) version of 2 of Lingon, before it moved to the Mac App Store, is still entirely usable for exactly this purpose. Unfortunately, the current paid version is severely limited due to restrictions on apps allowed to appear in the Mac App Store and so can no longer be used to edit or save system-level jobs. (It’s a bit fiddly, but the editing function can still be used: just copy and save the resulting text yourself into the correct position and load it yourself from the command line.)
All material on this site is carefully reviewed, but its accuracy cannot be guaranteed, and some suggestions offered here might just be silly ideas. For best results, please do your own checking and verifying. This specific article was last reviewed or updated by Greg on .
https://codedmemes.com/lib/replacing-cron-jobs-with-launchd/