OS X may seem inordinately complicated, to the point where it all becomes a meaningless blur, but it really boils down to two major components: the kernel, and
launchd. The kernel is the heart, vital to everything, and its failure is catastrophe. Kernel extensions (KEXTs) extend its functionality to operate hardware beyond the essential core.
The kernel cannot, though, do much else, for which it looks to
launchd, the first task to run outside the kernel and always with the process ID of 1.
launchd then gets everything else loaded up and running, from services which have to be started each time that OS X starts up, to those routine housekeeping functions which run in the middle of the night. If the kernel is the heart, then surely
launchd is its brain.
If you want to get a quick idea of how much
launchd is responsible for, you can use its control and admin tool
launchctl to list all the tasks which it is currently managing, with the command
which will generate a huge list of all sorts of things that you didn’t know that your Mac was up to.
launchd is a relatively recent innovation in OS X: it was not there in the first release, not appearing until OS X 10.4 (Tiger). Designed and written by Dave Zarzycki, its beauty lies in bringing together, into a single service, all the things that several other services did. The most prominent of those is the standard Unix service for running scheduled commands,
cron. Although OS X still has
cron and can still run timed events with it, it does so thanks to
If you wanted to back your Home folder up to a networked file server at 2300 every weeknight, for example, in traditional Unix you would write an entry in your
crontab, a table which acts as the timetable for such events. The diehard Unix wizard can still do that in OS X, but Apple discourages you from doing so. At some stages during the introduction of
cron service, inevitably known as
crond, became extremely unreliable, forcing users to migrate to
Chances are that nothing on your Mac now uses the old, deprecated
cron system with
crontabs. You can check by looking for its
crontabs, located in /etc/crontab or /usr/lib/cron/tabs. Because the latter are protected (they are user-specific), the best way to check on these is with the commands
ls -la /etc/crontabs
which will almost certainly return
No such file or directory
sudo ls -la /usr/lib/cron/tabs/username
where username is your short user name, and should return an empty folder.
crontabs, the only way that your Mac is going to run scheduled commands is under
launchd relies on XML property lists (.plist files) which are placed in standard locations:
- ~/Library/LaunchAgents for user agents provided by the user,
- /Library/LaunchAgents for user agents provided by the administrator,
- /Library/LaunchDaemons for system-wide daemons provided by the administrator,
- /System/Library/LaunchAgents for user agents provided by Apple,
- /System/Library/LaunchDaemons for system-wide daemons provided by Apple.
It is easy to remember which is which: if they’re in either of the folders in /System/Library/, they should now be part of OS X, and protected by SIP, so that you cannot tamper with them. If they’re in either of the folders in /Library, then they will run for all users, and typically support apps, hardware, and other services which are accessible to all users. If they’re in ~/Library/LaunchAgents they are specific to that user alone.
The differences between daemons and agents can appear subtle, but there is one which is decisive: daemons cannot display any sort of user interface, or interact directly with your login session; if the service or action needs an interface or interaction, then it should go into one of the LaunchAgents folders.
Adding and controlling agents and daemons
There are three ways that you can create and add a new agent/daemon, or modify the settings of an existing one. If you want to do this on a temporary basis, and enjoy using the command line, then the shell command
launchctl provides a complete set of commands for doing that. And the best of luck to you – it is not at all easy.
In most cases, you will want any changes to persist into the future. In that case, you will need to create a new XML property list and install it into the appropriate folder, or edit an existing one. Although this is not as tough as using
launchctl, you will need to be comfortable editing property lists, and study Apple’s documentation for these particular files.
By far the best way of adding to or tweaking the property lists is using Peter Borg’s excellent Lingon X. This comes in two different versions: that offered in the App Store has limited functionality because of the constraints placed on App Store apps. It is perfectly suitable for creating your own periodic tasks, but if you want full access to its power you will need to purchase the unlimited version of Lingon X from here.
A service which runs every day might be set up like this Adobe service. Each time that my Mac starts up, and every twenty-four hours afterwards, this will automatically run the background service named AGSService. You could configure a similar service to synchronise the contents of a working documents folder with that on a file server, for example, in the same way. Instead of using a repeat interval like this, you could set a fixed time each day, perhaps.
launchctl/launchd system allows more advanced options too, which you can also edit easily using Lingon. Most common among these are the bottom two, which set the paths for normal and error output.
So long as you are working with a small number of daemons/agents,
launchd is not that complex, and certainly not difficult to use. It can get messier when you need to know about other tasks. One example of this is when your Mac starts crashing or freezing at 0200 every morning, but the logs provide insufficient information to identify what has caused the problem – something that I have recently experienced.
Trying to use
launchctl to list all tasks is futile: for a start you’d never find that needle in its haystack, and in any case if the service is only run at 0200, you won’t find it there now. A better solution is to browse those property list files, either in the Finder or using Lingon, until you identify which is configured to run then. You could then disable it, and see whether that made the problem vanish too.
launchd, launchctl, cron, and
crontabs are fully documented in their
man files. The best overall guide to
launchd is at launchd.info, which explains how to make your own property list files and much more.