A principal misconception I’ve encountered among people who have heard of launchd or looked into it and chose some other solution is that they seem to think it’s just for making startup items. It’s quite different.
Launchd allows for starting a program under any of these conditions:
- configuration file is loaded
- time has elapsed (repeating)
- time has arrived (scheduled)
- program exit (to keep a program running)
- network connection (inetd-style)
- file is modified
- file exists in a queue directory
Example Configs
Tools Needed
As with any other launchd property list you can use any tool that fits your fancy. There’s the shareware Launchd Editor, there’s the Property List Editor that Apple includes with Xcode, and, if you’re feeling lazy and cheap, copy an existing property list, cut the middle out, and start typing.
Config: One-time Launch
To setup a one-time launch configuration where the program starts when the file is loaded and never again, configure the following keys in the configuration file:
- Label
- ProgramArguments
- RunAtLoad = true
Config: Timed Launch
As of 10.4.1 this does not take time asleep into account and, thus, will be off by a certain amount after sleeping. The author of launchd has noted that this should be resolved in 10.4.2.
A timed launch starts once every time period. You could use this to start a program once every hour, four times a day, or every other minute.
- Label
- ProgramArguments
- RunAtLoad = true or false
- StartInterval
Config: Scheduled Launch
As of 10.4.1 this will only start the first time the scheduled time comes around. The author of launchd has noted that this should be resolved in 10.4.2.
A launchd scheduled launch is similar to a cron-style scheduled launch except that some of the features of the newer GNU-style crons are not supported, such as running several times per component. Still, if you want to simply schedule a process to run at a certain time on certain days (or every day) then this is the option to use.
- Label
- ProgramArguments
- StartCalendarInterval
Config: Program Exit
Since launchd replaced init in Tiger it should be no surprise that it supports init-style behavior in keeping a program running. In fact, it just takes one flag to enable this.
- Label
- ProgramArguments
- OnDemand = false
Config: Network Connection
Launchd also managed to replace (x)inetd and, thus, has this ability as well. If inetdCompatibility is specified, launchd will behave like inetd for the launched program. This way, common Unix servers can be integrated into the system without being recoded to talk to launchd’s services.
- Label
- ProgramArguments
- Sockets
- inetdCompatibility (opt)
Config: Modified Path
If the destination of the listed path is modified, launchd will trigger the process. This works a lot like folder actions, but for scripts and binaries rather than just AppleScripts. Moreover, the item at the end of the path can be a file or a folder. You could, for instance, notify an admin via email if the network settings (preferences.plist) are changed or a system-wide font is added.
- Label
- ProgramArguments
- WatchPaths
Config: Queue Directory
Designed more for mail programs and the like, you can use queue directories for more fun things like a downloads folder with an auto-sorting script. As long as there exists something in the listed folder, the target will be launched. It is expected to clean the folder out.
- Label
- ProgramArguments
- QueueDirectories
Timing is everything
You can, in addition, load your configuration file at varying times and with varying privileges. For timing, place your file in the right folder:
| Files in |
Run as |
Load at |
| /Library/LaunchDaemons |
root |
system startup |
| /Library/LaunchAgents |
user |
any user login |
| ~/Library/LaunchAgents |
user |
specific user login |
While there exists a /System/Library/LaunchDaemons and LaunchAgents, use the ones provided in /Library instead. It provides the same functionality, consolidates files you’ve added to the system, and keeps the chances of inadvertently changing something important low.
If the fact that the processes in LaunchDaemons run as root bothers you, use the UserName key in the configuration file to have launchd start the process with reduced privileges. It’s akin to a “su user -c ‘process arguments’” command.
Limitations
As far, launch items do not have shutdown capabilities. That is, unlike a startup item, launch items cannot run a command when stopped or unloaded via launchctl. They are killed and forgotten. If you need a shutdown command you have two choices:
- use a startup item
- write a program or script that catches the kill signal and executes the stop command before going down
Also, there is no way to use cron-like repeating tasks such as:
*/10 * * * 6,7 task
Which translates to “every ten minutes on the weekend, run this task.”
Since neither startup items or cron are removed in Tiger, if you need these capabilities those are still the best route for your task unless you can add code to your task to fake the behavior you want.
is there any way, directly or indirectly, that launchd could be programed to wake the computer from sleep? and if not what are the chances that this might be added in future?
No. Never.
It has absolutely no features remotely related to power management.
—
cp
You could grab Wakein from the EyeTV distribution and write a wrapper around that. The only documentation for it is the command syntax:
% /Library/Application\ Support/EyeTV/Wakein -h Syntax: Wakein <time_to_wake> Wakein -build Wakein -schedule <event_time> [<event_type>] [<application_name>] Wakein -cancel [<event_time_start>] [<event_time_end>] [<event_type>] [<application_name>]</application_name></event_type></event_time_end></event_time_start></application_name></event_type></event_time></time_to_wake>Pretty sure I’ve seen similar utilities but that’s the only one that comes to mind right now.
Is it possible to launch login script with launchd?
Per-user, yes. Add a launchd item to the users’ ~/Library/LaunchAgents/ folder.
—
cp
The problem is that the launchd agent (in user domain) will not unload when the user log out.
I’m having trouble getting webmin to launch. I can run /etc/webmin/setup.sh and it will work just fine until I restart.
I took a look at my old 10.3 machine where webmin launches just fine, and I tried to use the /Library/StartupItems/webmin/ contents to construct a LaunchDaemon for my 10.4 machine.
Alas, no luck.
Here’s what worked in 10.3:
/Library/StartupItems/Webmin/StartupParameters.plist
{ Description = "Webmin system administration daemon"; Provides = ("Webmin"); Requires = ("Resolver"); OrderPreference = "None"; Messages = { start = "Starting Webmin Server"; stop = "Stopping Webmin Server"; }; }/Library/StartupItems/Webmin/Webmin
Two things: The script being called cannot terminate and must always stay active or else launchd will keep trying to start it. So the start script might not be the best thing to use for this.
Secondarily, you need to add the OnDemand=NO key in there so that it knows to start it and keep it running.
Either way, watch the system.log file for errors and see what’s going on. Note that the old startup item will work in 10.4 and might still be the best way of handling this.
—
cp
I need to run various scripts on startup that use the network. I haven’t been able to figure out how to make a LaunchDaemon load after the is network available. I have tried using this syntax to make a script dependant on configd but I cannot find documented examples to verify its syntax. So far this hasn’t been working for me. Any ideas?
<key>Sockets</key> <dict> <key>Listeners</key> <dict> <key>SockServiceName</key> <string>configd</string> </dict> </dict>launchd does not do dependancies at all. You will need to put a 10-15 second pause at the start of your script or test for network functionality before doing any work.
—
cp
Save this in /Library/LaunchDaemons as webmin.plist.
I am trying to run a script once when my powerbook is connected to a network. It looks to me like inetdCompatibility would be the right option but I can’t figure how to make it work.
That option does not do what you think. Launchd cannot do what you want in this case. Investigate a configd plugin.
—
cp
Good example to learn launchd.