wiki:UsingLaunchd

Using launchd

launchd is Mac OS X's system wide and per-user daemon/agent manager. It handles many tasks previously handled by various scripts (/etc/rc) and programs (xinitd, cron, SystemStarter). Introduced in Mac OS X 10.4 Tiger, it fully replaces the traditional init program and should be used to manage all server jobs, particularly on Mac OS X 10.5 Leopard and later. For more information on launchd, see the launchd(8) man page or http://developer.apple.com/macosx/launchd.html.

It is fairly easy to run a buildbot slave or master as a launchd job, though buildbot can't be invoked using the buildbot command as usual, because the process needs to remain in the foreground for launchd to function correctly. Instead, the process must be started directly using the Twisted launcher as shown in the examples below.

Processes on OS X do not derive all of their authority by virtue of their userid/groupid alone. There are several low-level Mach ports and Mach namespaces which are used for, among other things, DNS lookup and disk image handling (the hdiutil program, used to create .dmg files for installers). A buildbot process which is not started through launchd may not work properly. Worse yet, some of these authorities will be available to a process started in an ssh session, but will go away once you log out of that ssh session. Technical Note TN2083 has more background. The /usr/libexec/StartupItemContext utility may be necessary even for jobs started under launchd. In this case, put the line <string>/usr/libexec/StartupItemContext</string> as an extra item of ProgramArguments before your actual program.

Sample launchd job property lists for buildbot

Sample property list for a slave

The following launchd job property list file describes a buildbot slave using MacPorts's Python 2.5 installation. You will need to edit PATH and PYTHONPATH to use Mac OS 10.5's stock Python installation. Using the stock Python also requires that you manually install the Twisted framework.

Note that the specified process owner, buildbot, is not part of the built-in system users on Mac OS X 10.5. Additional users can be created through the Accounts prefpane, with the dscl utility, or by using Workgroup Manager, part of the server administration programs freely available from Apple.

If setting up through dscl or Workgroup Manager, note that you should specify a home directory (a NFSHomeDirectory attribute in the DirectoryServices user record) for the user you decide to run your buildbots as. This will ensure that programs who wish to write configuration or runtime files in their user's home directory (such as Subversion's .subversion directory or ssh's .ssh directory) may do so. In the case of this sample file, the buildbot user has its NFSHomeDirectory attribute set to /var/buildbot.

This properly list should be named after the job label (here net.buildbot.slave.test) with the addition of a plist extension (thus in this example, net.buildbot.slave.test.plist) and placed in the /Library/LaunchDaemons directory. The property list must be owned by root:wheel, otherwise the system will not load it. For details on managing launchd jobs, see the launchctl(1) man page.

Note that placing the launchd plist in /Library/LaunchDaemons will cause buildbot to launch on booting the machine, even if the buildbot user does not have a graphical context (auto login on boot, say). If the machine you're setting this up as is a test slave and requires a GUI context to run tests with, you should place this plist inside ~buildbot/Library/LaunchAgents, which means that builbot will only run when the buildbot user auto logs in (don't forget to set auto login in the Accounts prefpane). This will avoid any issues with a system-wide context trying to access a GUI context, which blocks certain API level calls.

You will need to edit the WorkingDirectory key to point to the root directory for the slave you want to start and edit the job label to have a more informative name corresponding to your slave. If you want to run multiple slaves, you will need to create a new plist for each slave in /Library/LaunchDaemons and set WorkingDirectory and Label accordingly in each file.

<?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>StandardOutPath</key>
	<string>twistd.log</string>
	<key>StandardErrorPath</key>
	<string>twistd-err.log</string>
	<key>EnvironmentVariables</key>
	<dict>
		<key>PATH</key>
		<string>/opt/local/bin:/sbin:/usr/sbin:/bin:/usr/bin</string>
		<key>PYTHONPATH</key>
		<string>/opt/local/lib/python2.6/site-packages</string>
	</dict>
	<key>GroupName</key>
	<string>daemon</string>
	<key>KeepAlive</key>
	<dict>
		<key>SuccessfulExit</key>
		<false/>
	</dict>
	<key>Label</key>
	<string>net.buildbot.slave.test</string>
	<key>ProgramArguments</key>
	<array>
		<string>twistd</string>
		<string>--nodaemon</string>
		<string>-y</string>
		<string>./buildbot.tac</string>
	</array>
	<key>RunAtLoad</key>
	<true/>
	<key>UserName</key>
	<string>buildbot</string>
	<key>WorkingDirectory</key>
	<string>/Users/buildbot/slave/test</string>
	<key>SessionCreate</key>
	<true/>
</dict>
</plist>

Note: /Library/LaunchDaemons and "Network, Managed" accounts don't work together. Launchd reports that getpwnam failed. Local accounts appear to be required to run as a Daemon.

Sample property list for a master

Running a master is very similar to running a slave through launchd. The same things noted above for running a slave apply here too. As above, you need to edit the Label and WorkingDirectory keys to correspond to your installation.

<?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>StandardOutPath</key>
	<string>twistd.log</string>
	<key>StandardErrorPath</key>
	<string>twistd-err.log</string>
	<key>EnvironmentVariables</key>
	<dict>
		<key>PATH</key>
		<string>/opt/local/bin:/sbin:/usr/sbin:/bin:/usr/bin</string>
		<key>PYTHONPATH</key>
		<string>/opt/local/lib/python2.6/site-packages</string>
	</dict>
	<key>GroupName</key>
	<string>daemon</string>
	<key>KeepAlive</key>
	<dict>
		<key>SuccessfulExit</key>
		<false/>
	</dict>
	<key>Label</key>
	<string>net.buildbot.master.test</string>
	<key>ProgramArguments</key>
	<array>
		<string>twistd</string>
		<string>--nodaemon</string>
		<string>-y</string>
		<string>./buildbot.tac</string>
	</array>
	<key>RunAtLoad</key>
	<true/>
	<key>UserName</key>
	<string>buildbot</string>
	<key>WorkingDirectory</key>
	<string>/Users/buildbot/master/test</string>
</dict>
</plist>
Last modified 11 months ago Last modified on Nov 7, 2013, 5:04:06 PM