CINXE.COM
Creating Launch Daemons and Agents
<!DOCTYPE html> <html lang="en"> <head> <title>Creating Launch Daemons and Agents</title> <meta http-equiv="X-UA-Compatible" content="IE=7"> <meta charset="utf-8"> <meta id="book-resource-type" name="book-resource-type" content="Guide"> <meta scheme="apple_ref" id="identifier" name="identifier" content="//apple_ref/doc/uid/10000172i"> <meta id="document-version" name="document-version" content="6.3.4"> <meta id="build" name="build" content="c1e4c7a89af8f899a21cfa81fc33ba42" /> <meta id="chapterId" name="chapterId" content="10000172i-SW7"> <meta id="date" name="date" content="2016-09-13"> <meta id="description" name="description" content="Explains how to write background processes that perform work on behalf of applications or serve content over the network."> <meta id="book-title" name="book-title" content="Daemons and Services Programming Guide"> <meta id="book-root" name="book-root" content="../"> <meta id="book-json" name="book-json" content="../book.json"> <meta id="devcenter" name="devcenter" content="Mac Dev Center"> <meta id="devcenter-url" name="devcenter-url" content="http://developer.apple.com/devcenter/mac"> <meta id="reflib" name="reflib" content="Documentation Archive"> <meta id="book-assignments" name="book-assignments" content="{Type/Guide}, {Topic/General}"> <meta id="copyright" name="copyright" content="Copyright 2018 Apple Inc. All Rights Reserved."> <meta id="xcode-display" name="xcode-display" content="render"> <meta id="IndexTitle" name="IndexTitle" content="Daemons and Services Programming Guide: Creating Launch Daemons and Agents"> <meta id="resources-uri" name="resources-uri" content="../../../../../Resources/1282"> <link id="book-index-page" rel="Start" title="Daemons and Services Programming Guide" type="text/html" href="../index.html"> <link id="next-page" rel="Next" type="text/html" href="ScheduledJobs.html"> <link id="previous-page" rel="Prev" type="text/html" href="CreatingXPCServices.html"> <link rel="stylesheet" type="text/css" href="../../../../../Resources/1282/CSS/screen.css"> <!-- xcode_css --> <link rel="stylesheet" type="text/css" href="../../../../../Resources/1282/CSS/feedback.css"> <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"> <meta id="platforms" name="platforms" content=""> </head> <body><a name="//apple_ref/doc/uid/10000172i-SW7" title="Creating Launch Daemons and Agents"></a> <div id="_omniture_top"> <!-- SiteCatalyst code version: H.8. Copyright 1997-2006 Omniture, Inc. --> <script type="text/javascript"> /* RSID: */ var s_account="awdappledeveloper" </script> <script type="text/javascript" src="https://developer.apple.com/assets/metrics/scripts/analytics.js"></script> <script type="text/javascript"> s.channel="www.documentationarchive.developer" /************* DO NOT ALTER ANYTHING BELOW THIS LINE ! **************/ var s_code=s.t();if(s_code)document.write(s_code)</script> <!-- End SiteCatalyst code version: H.8. --> </div> <div id="adcHeader" class="hideOnPrint hideInXcode"> <div id='ssi_Header' class="hideInXcode unified"> <a id="ssi_LibraryTitle" href='../../../../../navigation/'>Documentation Archive</a> <a id="ssi_AppleDeveloperConnection" href='https://developer.apple.com/'>Developer</a> <div id='ssi_SearchButton' role="button" title="Search">Search</div> </div> <form id='ssi_SearchMenu' method='get' action='../../../../../search/' accept-charset='utf-8'> <label for='adcsearch'>Search Documentation Archive</label> <input type='search' id='ssi_SearchField' name='q' accesskey='s' results='5' /> </form> </div> <header id="header"> <div id="title" role="banner"> <h1>Daemons and Services Programming Guide</h1> <span id="file_links"> <a id="PDF_link" role="button" tabindex='4' rel="alternate" title="Download PDF"><span id="pdf_icon"></span>PDF</a> <a id="Companion_link" role="button" tabindex='3' title="Download Companion File"><span id="companion_icon"></span>Companion File</a> </span> </div> <ul id="headerButtons" class="hideOnPrint" role="toolbar"> <li id="toc_button" style="display:none"> <button tabindex="5" id="table_of_contents" class="open" role="checkbox" aria-label="Show Table of Contents"><span class="disclosure"></span>Table of Contents</button> </li> <li id="jumpto_button" style="display:none" role="navigation"><select tabindex="6" id="jumpTo"><option value="top">Jump To…</option></select></li> <li id="downloadSample_button" style="display:none"> <a id="Sample_link"><button id="Sample_button">Download Sample Code</button></a> </li> </ul> </header> <nav id="tocContainer" tabindex="7"> <ul id="toc" role="tree"></ul> </nav> <article id="contents" tabindex="0" role="main"> <div id="pageNavigationLinks_top" class="pageNavigationLinks"> <a class='nextLink' rel='next' href='ScheduledJobs.html'>Next</a><a class='previousLink' rel='prev' href='CreatingXPCServices.html'>Previous</a> </div> <a id="top" name="top"></a> <a id="INDEX" href="../index.html" style="display:none;"></a> <a name="//apple_ref/doc/uid/10000172i-SW7-BCIEDDBJ" title="Creating Launch Daemons and Agents"></a><h1 id="pageTitle">Creating Launch Daemons and Agents</h1><p>If you are developing daemons to run on OS X, it is highly recommended that you design your daemons to be <code>launchd</code> compliant. Using <code>launchd</code> provides better performance and flexibility for daemons. It also improves the ability of administrators to manage the daemons running on a given system.</p><p>If you are running per-user background processes for OS X, <code><!--a target="_self" -->launchd<!--/a--></code> is also the preferred way to start these processes. These per-user processes are referred to as user agents. A user agent is essentially identical to a daemon, but is specific to a given logged-in user and executes only while that user is logged in.</p><p>Unless otherwise noted, for the purposes of this chapter, the terms “daemon” and “agent” can be used interchangeably. Thus, the term “daemon” is used generically in this section to encompass both system-level daemons and user agents except where otherwise noted.</p><p>There are four ways to launch daemons using <code>launchd</code>. The preferred method is on-demand launching, but <code>launchd</code> can launch daemons that run continuously, and can replace <code>inetd</code>for launching <code>inetd</code>-style daemons. In addition, <code>launchd</code> can start jobs at timed intervals.</p><p>Although <code>launchd</code> supports non-launch-on-demand daemons, this use is not recommended. The <code>launchd</code> daemon was designed to remove the need for dependency ordering among daemons. If you do not make your daemon be launched on demand, you will have to handle these dependencies in another way, such as by using the legacy startup item mechanism.</p><section><a name="//apple_ref/doc/uid/10000172i-SW7-105327" title="Launching Custom Daemons Using launchd"></a><h2 class="jump">Launching Custom Daemons Using launchd</h2><p>With the introduction of <code><!--a target="_self" -->launchd<!--/a--></code><a name="//apple_ref/doc/uid/10000172i-SW7-DontLinkElementID_10"></a> in OS X v10.4, an effort was made to improve the steps needed to launch and maintain daemons. What <code>launchd</code><a name="//apple_ref/doc/uid/10000172i-SW7-DontLinkElementID_11"></a> provides is a harness for launching your daemon as needed. To client programs, the port representing your daemon’s service is always available and ready to handle requests. In reality, the daemon may or may not be running. When a client sends a request to the port, <code>launchd</code> may have to launch the daemon so that it can handle the request. Once launched, the daemon can continue running or shut itself down to free up the memory and resources it holds. If a daemon shuts itself down, <code>launchd</code> once again relaunches it as needed to process requests.</p><p>In addition to the launch-on-demand feature, <code>launchd</code> provides the following benefits to daemon developers:</p><ul class="ul"><li class="li"><p>Simplifies the process of making a daemon by handling many of the standard housekeeping chores normally associated with launching a daemon.</p></li><li class="li"><p>Provides system administrators with a central place to manage daemons on the system.</p></li><li class="li"><a name="//apple_ref/doc/uid/10000172i-SW7-DontLinkElementID_12"></a><p>Supports <code>inetd</code>-style daemons.</p></li><li class="li"><p>Eliminates the primary reason for running daemons as root. Because <code>launchd</code> runs as root, it can create low-numbered TCP/IP listen sockets and hand them off to the daemon.</p></li><li class="li"><p>Simplifies error handling and dependency management for inter-daemon communication. Because daemons launch on demand, communication requests do not fail if the daemon is not launched. They are simply delayed until the daemon can launch and process them.</p></li></ul></section><section><a name="//apple_ref/doc/uid/10000172i-SW7-108425" title="The launchd Startup Process"></a><h2 class="jump">The launchd Startup Process</h2><p>After the system is booted and the kernel is running, <code><!--a target="_self" -->launchd<!--/a--></code><a name="//apple_ref/doc/uid/10000172i-SW7-DontLinkElementID_13"></a> is run to finish the system initialization. As part of that initialization, it goes through the following steps: </p><ol class="ol"><li class="li"><p>It loads the parameters for each launch-on-demand system-level daemon from the property list files found in <code>/System/Library/LaunchDaemons/</code> and <code>/Library/LaunchDaemons/</code>.</p></li><li class="li"><p>It registers the sockets and file descriptors requested by those daemons. </p></li><li class="li"><p>It launches any daemons that requested to be running all the time. </p></li><li class="li"><p>As requests for a particular service arrive, it launches the corresponding daemon and passes the request to it. </p></li><li class="li"><p>When the system shuts down, it sends a <code>SIGTERM</code> signal to all of the daemons that it started.</p></li></ol><p>The process for per-user agents is similar. When a user logs in, a per-user <code>launchd</code> is started. It does the following:</p><ol class="ol"><li class="li"><p>It loads the parameters for each launch-on-demand user agent from the property list files found in <code>/System/Library/LaunchAgents</code>, <code>/Library/LaunchAgents</code>, and the user’s individual <code>Library/LaunchAgents</code> directory.</p></li><li class="li"><p>It registers the sockets and file descriptors requested by those user agents.</p></li><li class="li"><p>It launches any user agents that requested to be running all the time.</p></li><li class="li"><p>As requests for a particular service arrive, it launches the corresponding user agent and passes the request to it.</p></li><li class="li"><p>When the user logs out, it sends a <code>SIGTERM</code> signal to all of the user agents that it started.</p></li></ol><p>Because <code>launchd</code> registers the sockets and file descriptors used by all daemons before it launches any of them, daemons can be launched in any order. If a request comes in for a daemon that is not yet running, the requesting process is suspended until the target daemon finishes launching and responds.</p><p>If a daemon does not receive any requests over a specific period of time, it can choose to shut itself down and release the resources it holds. When this happens, <code>launchd</code> monitors the shutdown and makes a note to launch the daemon again when future requests arrive. </p><div class="importantbox clear"><aside><a name="//apple_ref/doc/uid/10000172i-SW7-DontLinkElementID_3" title="Important"></a><p><strong>Important:</strong> If your daemon shuts down too quickly after being launched, <code>launchd</code> 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. </p><p></p></aside></div></section><section><a name="//apple_ref/doc/uid/TP40001762-104142" title="Creating a launchd Property List File"></a><a name="//apple_ref/doc/uid/10000172i-SW7-104142-BCICCCFI" title="Creating a launchd Property List File"></a><h2 class="jump">Creating a launchd Property List File</h2><p><a name="//apple_ref/doc/uid/10000172i-SW7-DontLinkElementID_14"></a>To run under <code><!--a target="_self" -->launchd<!--/a--></code>, you must provide a configuration property list file for your daemon. This file contains information about your daemon, including the list of sockets or file descriptors it uses to process requests. Specifying this information in a property list file lets <code>launchd</code> register the corresponding file descriptors and launch your daemon only after a request arrives for your daemon’s services. <span class="content_text">Table 5-1</span> lists the required and recommended keys for all daemons.</p><p>The property list file is structured the same for both daemons and agents. You indicate whether it describes a daemon or agent by the directory you place it in. Property list files describing daemons are installed in <code>/Library/LaunchDaemons</code>, and those describing agents are installed in <code>/Library/LaunchAgents</code> or in the <code>LaunchAgents</code> subdirectory of an individual user’s <code>Library</code> directory. (The appropriate location for executables that you launch from your job is <code>/usr/local/libexec</code>.)</p><a name="//apple_ref/doc/uid/10000172i-SW7-105851-BCIEDHIA" title="Table 5-1Required and recommended property list keys"></a><div class="tableholder"><table class="graybox" border = "0" cellspacing="0" cellpadding="5"><caption class="tablecaption"><a name="//apple_ref/doc/uid/TP40001762-105851" title="Table 5-1Required and recommended property list keys"></a><strong class="caption_number">Table 5-1</strong> Required and recommended property list keys</caption><tr><th scope="col" class="TableHeading_TableRow_TableCell"><p>Key</p></th><th scope="col" class="TableHeading_TableRow_TableCell"><p>Description</p></th></tr><tr><td scope="row"><p><code>Label</code></p></td><td ><p>Contains a unique string that identifies your daemon to <code>launchd</code>. (required)</p></td></tr><tr><td scope="row"><p><code>ProgramArguments</code></p></td><td ><p>Contains the arguments used to launch your daemon. (required) </p></td></tr><tr><td scope="row"><p><code>inetdCompatibility</code></p></td><td ><p>Indicates that your daemon requires a separate instance per incoming connection. This causes <code>launchd</code> to behave like <code>inetd</code>, passing each daemon a single socket that is already connected to the incoming client. (required if your daemon was designed to be launched by <code>inetd</code>; otherwise, must not be included)</p></td></tr><tr><td scope="row"><p><code>KeepAlive</code></p></td><td ><p>This key specifies whether your daemon launches on-demand or must always be running. It is recommended that you design your daemon to be launched on-demand.</p></td></tr></table></div><div class="notebox"><aside><a name="//apple_ref/doc/uid/10000172i-SW7-SW1" title="For more information"></a><p><strong>For more information:</strong> For a complete listing of the keys, see the <code><!--a target="_self" -->launchd.plist<!--/a--></code> manual page.</p><p>For sample configuration property lists, look at the files in <code>/System/Library/LaunchDaemons/</code>. These files are used to configure many daemons that run on OS X.</p><p></p></aside></div><section><a name="//apple_ref/doc/uid/10000172i-SW7-SW3" title="Writing a “Hello World!” launchd Job"></a><h3 class="jump">Writing a “Hello World!” launchd Job</h3><p>The following simple example launches a daemon named <code>hello</code>, passing <code>world</code> as a single argument, and instructs launchd to keep the job running:</p><div class="codesample clear"><table><tr><td scope="row"><pre><?xml version="1.0" encoding="UTF-8"?><span></span></pre></td></tr><tr><td scope="row"><pre><!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"><span></span></pre></td></tr><tr><td scope="row"><pre><plist version="1.0"><span></span></pre></td></tr><tr><td scope="row"><pre><dict><span></span></pre></td></tr><tr><td scope="row"><pre> <key>Label</key><span></span></pre></td></tr><tr><td scope="row"><pre> <string>com.example.hello</string><span></span></pre></td></tr><tr><td scope="row"><pre> <key>ProgramArguments</key><span></span></pre></td></tr><tr><td scope="row"><pre> <array><span></span></pre></td></tr><tr><td scope="row"><pre> <string>hello</string><span></span></pre></td></tr><tr><td scope="row"><pre> <string>world</string><span></span></pre></td></tr><tr><td scope="row"><pre> </array><span></span></pre></td></tr><tr><td scope="row"><pre> <key>KeepAlive</key><span></span></pre></td></tr><tr><td scope="row"><pre> <true/><span></span></pre></td></tr><tr><td scope="row"><pre></dict><span></span></pre></td></tr><tr><td scope="row"><pre></plist><span></span></pre></td></tr><tr><td scope="row"><pre> <span></span></pre></td></tr></table></div><p>In this example, there are three keys in the top level dictionary. The first is <code>Label</code>, which uniquely identifies the job. when. The second is <code>ProgramArguments</code> which has a value of an array of strings which represent the tokenized arguments and the program to run. The third and final key is <code>KeepAlive</code> which indicates that this job needs to be running at all times, rather than the default launch-on-demand behavior, so launchd should always try to keep this job running.</p></section><section><a name="//apple_ref/doc/uid/10000172i-SW7-SW4" title="Listening on Sockets"></a><h3 class="jump">Listening on Sockets</h3><p>You can also include other keys in your configuration property list file. For example, if your daemon monitors a well-known port (one of the ports listed in <code>/etc/services</code>), add a <code>Sockets</code> entry as follows:</p><div class="codesample clear"><table><tr><td scope="row"><pre><key>Sockets</key> <dict> <key>Listeners</key> <dict> <key>SockServiceName</key> <string>bootps</string> <key>SockType</key> <string>dgram</string> <key>SockFamily</key> <string>IPv4</string> </dict> </dict><span></span></pre></td></tr></table></div><p>The string for <code>SockServiceName</code> typically comes from the leftmost column in <code>/etc/services</code>. The <code>SockType</code> is one of <code>dgram</code> (UDP) or <code>stream</code> (TCP/IP). If you need to pass a port number that is not listed in the well-known ports list, the format is the same, except the string contains a number instead of a name. For example:</p><div class="codesample clear"><table><tr><td scope="row"><pre><key>SockServiceName</key><span></span></pre></td></tr><tr><td scope="row"><pre><string>23</string><span></span></pre></td></tr></table></div></section><section><a name="//apple_ref/doc/uid/10000172i-SW7-SW5" title="Debugging launchd Jobs"></a><h3 class="jump">Debugging launchd Jobs</h3><p>There are some options that are useful for debugging your launchd job.</p><p>The following example enables core dumps, sets standard out and error to go to a log file, and instructs launchd to temporarily increase the debug level of its logging while acting on behalf of your job (remember to adjust your syslog.conf accordingly):</p><div class="codesample clear"><table><tr><td scope="row"><pre> <span></span></pre></td></tr><tr><td scope="row"><pre><?xml version="1.0" encoding="UTF-8"?><span></span></pre></td></tr><tr><td scope="row"><pre><!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"><span></span></pre></td></tr><tr><td scope="row"><pre><plist version="1.0"><span></span></pre></td></tr><tr><td scope="row"><pre><dict><span></span></pre></td></tr><tr><td scope="row"><pre> <key>Label</key><span></span></pre></td></tr><tr><td scope="row"><pre> <string>com.example.sleep</string><span></span></pre></td></tr><tr><td scope="row"><pre> <key>ProgramArguments</key><span></span></pre></td></tr><tr><td scope="row"><pre> <array><span></span></pre></td></tr><tr><td scope="row"><pre> <string>sleep</string><span></span></pre></td></tr><tr><td scope="row"><pre> <string>100</string><span></span></pre></td></tr><tr><td scope="row"><pre> </array><span></span></pre></td></tr><tr><td scope="row"><pre> <key>StandardOutPath</key><span></span></pre></td></tr><tr><td scope="row"><pre> <string>/var/log/myjob.log</string><span></span></pre></td></tr><tr><td scope="row"><pre> <key>StandardErrorPath</key><span></span></pre></td></tr><tr><td scope="row"><pre> <string>/var/log/myjob.log</string><span></span></pre></td></tr><tr><td scope="row"><pre> <key>Debug</key><span></span></pre></td></tr><tr><td scope="row"><pre> <true/><span></span></pre></td></tr><tr><td scope="row"><pre> <key>SoftResourceLimits</key><span></span></pre></td></tr><tr><td scope="row"><pre> <dict><span></span></pre></td></tr><tr><td scope="row"><pre> <key>Core</key><span></span></pre></td></tr><tr><td scope="row"><pre> <integer>9223372036854775807</integer><span></span></pre></td></tr><tr><td scope="row"><pre> </dict><span></span></pre></td></tr><tr><td scope="row"><pre> <key>HardResourceLimits</key><span></span></pre></td></tr><tr><td scope="row"><pre> <dict><span></span></pre></td></tr><tr><td scope="row"><pre> <key>Core</key><span></span></pre></td></tr><tr><td scope="row"><pre> <integer>9223372036854775807</integer><span></span></pre></td></tr><tr><td scope="row"><pre> </dict><span></span></pre></td></tr><tr><td scope="row"><pre></dict><span></span></pre></td></tr><tr><td scope="row"><pre></plist><span></span></pre></td></tr></table></div></section><section><a name="//apple_ref/doc/uid/10000172i-SW7-SW7" title="Running a Job Periodically"></a><h3 class="jump">Running a Job Periodically</h3><p>The following example creates a job that is run every five minutes (300 seconds):</p><div class="codesample clear"><table><tr><td scope="row"><pre><?xml version="1.0" encoding="UTF-8"?><span></span></pre></td></tr><tr><td scope="row"><pre><!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"><span></span></pre></td></tr><tr><td scope="row"><pre><plist version="1.0"><span></span></pre></td></tr><tr><td scope="row"><pre><dict><span></span></pre></td></tr><tr><td scope="row"><pre> <key>Label</key><span></span></pre></td></tr><tr><td scope="row"><pre> <string>com.example.touchsomefile</string><span></span></pre></td></tr><tr><td scope="row"><pre> <key>ProgramArguments</key><span></span></pre></td></tr><tr><td scope="row"><pre> <array><span></span></pre></td></tr><tr><td scope="row"><pre> <string>touch</string><span></span></pre></td></tr><tr><td scope="row"><pre> <string>/tmp/helloworld</string><span></span></pre></td></tr><tr><td scope="row"><pre> </array><span></span></pre></td></tr><tr><td scope="row"><pre> <key>StartInterval</key><span></span></pre></td></tr><tr><td scope="row"><pre> <integer>300</integer><span></span></pre></td></tr><tr><td scope="row"><pre></dict><span></span></pre></td></tr><tr><td scope="row"><pre></plist><span></span></pre></td></tr></table></div><p>Alternately, you can specify a calendar-based interval. The following example starts the job on the 7th day of every month at 13:45 (1:45 pm). Like the Unix cron subsystem, any missing key of the <code>StartCalendarInterval</code> dictionary is treated as a wildcard—in this case, the month is omitted, so the job is run every month.</p><div class="codesample clear"><table><tr><td scope="row"><pre><?xml version="1.0" encoding="UTF-8"?><span></span></pre></td></tr><tr><td scope="row"><pre><!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"><span></span></pre></td></tr><tr><td scope="row"><pre><plist version="1.0"><span></span></pre></td></tr><tr><td scope="row"><pre><dict><span></span></pre></td></tr><tr><td scope="row"><pre> <key>Label</key><span></span></pre></td></tr><tr><td scope="row"><pre> <string>com.example.touchsomefile</string><span></span></pre></td></tr><tr><td scope="row"><pre> <key>ProgramArguments</key><span></span></pre></td></tr><tr><td scope="row"><pre> <array><span></span></pre></td></tr><tr><td scope="row"><pre> <string>touch</string><span></span></pre></td></tr><tr><td scope="row"><pre> <string>/tmp/helloworld</string><span></span></pre></td></tr><tr><td scope="row"><pre> </array><span></span></pre></td></tr><tr><td scope="row"><pre> <key>StartCalendarInterval</key><span></span></pre></td></tr><tr><td scope="row"><pre> <dict><span></span></pre></td></tr><tr><td scope="row"><pre> <key>Minute</key><span></span></pre></td></tr><tr><td scope="row"><pre> <integer>45</integer><span></span></pre></td></tr><tr><td scope="row"><pre> <key>Hour</key><span></span></pre></td></tr><tr><td scope="row"><pre> <integer>13</integer><span></span></pre></td></tr><tr><td scope="row"><pre> <key>Day</key><span></span></pre></td></tr><tr><td scope="row"><pre> <integer>7</integer><span></span></pre></td></tr><tr><td scope="row"><pre> </dict><span></span></pre></td></tr><tr><td scope="row"><pre></dict><span></span></pre></td></tr><tr><td scope="row"><pre></plist><span></span></pre></td></tr></table></div></section><section><a name="//apple_ref/doc/uid/10000172i-SW7-SW8" title="Monitoring a Directory"></a><h3 class="jump">Monitoring a Directory</h3><p>The following example starts the job whenever any of the paths being watched have changed:</p><div class="codesample clear"><table><tr><td scope="row"><pre><?xml version="1.0" encoding="UTF-8"?><span></span></pre></td></tr><tr><td scope="row"><pre><!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"><span></span></pre></td></tr><tr><td scope="row"><pre><plist version="1.0"><span></span></pre></td></tr><tr><td scope="row"><pre><dict><span></span></pre></td></tr><tr><td scope="row"><pre> <key>Label</key><span></span></pre></td></tr><tr><td scope="row"><pre> <string>com.example.watchhostconfig</string><span></span></pre></td></tr><tr><td scope="row"><pre> <key>ProgramArguments</key><span></span></pre></td></tr><tr><td scope="row"><pre> <array><span></span></pre></td></tr><tr><td scope="row"><pre> <string>syslog</string><span></span></pre></td></tr><tr><td scope="row"><pre> <string>-s</string><span></span></pre></td></tr><tr><td scope="row"><pre> <string>-l</string><span></span></pre></td></tr><tr><td scope="row"><pre> <string>notice</string><span></span></pre></td></tr><tr><td scope="row"><pre> <string>somebody touched /etc/hostconfig</string><span></span></pre></td></tr><tr><td scope="row"><pre> </array><span></span></pre></td></tr><tr><td scope="row"><pre> <key>WatchPaths</key><span></span></pre></td></tr><tr><td scope="row"><pre> <array><span></span></pre></td></tr><tr><td scope="row"><pre> <string>/etc/hostconfig</string><span></span></pre></td></tr><tr><td scope="row"><pre> </array><span></span></pre></td></tr><tr><td scope="row"><pre></dict><span></span></pre></td></tr><tr><td scope="row"><pre></plist><span></span></pre></td></tr></table></div><p>An additional file system trigger is the notion of a queue directory. The launchd daemon starts your job whenever the given directories are non-empty, and it keeps your job running as long as those directories are not empty:</p><div class="codesample clear"><table><tr><td scope="row"><pre><?xml version="1.0" encoding="UTF-8"?><span></span></pre></td></tr><tr><td scope="row"><pre><!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"><span></span></pre></td></tr><tr><td scope="row"><pre><plist version="1.0"><span></span></pre></td></tr><tr><td scope="row"><pre><dict><span></span></pre></td></tr><tr><td scope="row"><pre> <key>Label</key><span></span></pre></td></tr><tr><td scope="row"><pre> <string>com.example.mailpush</string><span></span></pre></td></tr><tr><td scope="row"><pre> <key>ProgramArguments</key><span></span></pre></td></tr><tr><td scope="row"><pre> <array><span></span></pre></td></tr><tr><td scope="row"><pre> <string>my_custom_mail_push_tool</string><span></span></pre></td></tr><tr><td scope="row"><pre> </array><span></span></pre></td></tr><tr><td scope="row"><pre> <key>QueueDirectories</key><span></span></pre></td></tr><tr><td scope="row"><pre> <array><span></span></pre></td></tr><tr><td scope="row"><pre> <string>/var/spool/mymailqdir</string><span></span></pre></td></tr><tr><td scope="row"><pre> </array><span></span></pre></td></tr><tr><td scope="row"><pre></dict><span></span></pre></td></tr><tr><td scope="row"><pre></plist><span></span></pre></td></tr></table></div></section><section><a name="//apple_ref/doc/uid/10000172i-SW7-SW9" title="Emulating inetd"></a><h3 class="jump">Emulating inetd</h3><p>The launchd daemon emulates the older <code>inetd</code>-style daemon semantics if you provide the <code>inetdCompatibility</code> key:</p><div class="codesample clear"><table><tr><td scope="row"><pre><?xml version="1.0" encoding="UTF-8"?><span></span></pre></td></tr><tr><td scope="row"><pre><!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"><span></span></pre></td></tr><tr><td scope="row"><pre><plist version="1.0"><span></span></pre></td></tr><tr><td scope="row"><pre><dict><span></span></pre></td></tr><tr><td scope="row"><pre> <key>Label</key><span></span></pre></td></tr><tr><td scope="row"><pre> <string>com.example.telnetd</string><span></span></pre></td></tr><tr><td scope="row"><pre> <key>ProgramArguments</key><span></span></pre></td></tr><tr><td scope="row"><pre> <array><span></span></pre></td></tr><tr><td scope="row"><pre> <string>/usr/libexec/telnetd</string><span></span></pre></td></tr><tr><td scope="row"><pre> </array><span></span></pre></td></tr><tr><td scope="row"><pre> <key>inetdCompatibility</key><span></span></pre></td></tr><tr><td scope="row"><pre> <dict><span></span></pre></td></tr><tr><td scope="row"><pre> <key>Wait</key><span></span></pre></td></tr><tr><td scope="row"><pre> <false/><span></span></pre></td></tr><tr><td scope="row"><pre> </dict><span></span></pre></td></tr><tr><td scope="row"><pre> <key>Sockets</key><span></span></pre></td></tr><tr><td scope="row"><pre> <dict><span></span></pre></td></tr><tr><td scope="row"><pre> <key>Listeners</key><span></span></pre></td></tr><tr><td scope="row"><pre> <dict><span></span></pre></td></tr><tr><td scope="row"><pre> <key>SockServiceName</key><span></span></pre></td></tr><tr><td scope="row"><pre> <string>telnet</string><span></span></pre></td></tr><tr><td scope="row"><pre> <key>SockType</key><span></span></pre></td></tr><tr><td scope="row"><pre> <string>stream</string><span></span></pre></td></tr><tr><td scope="row"><pre> </dict><span></span></pre></td></tr><tr><td scope="row"><pre> </dict><span></span></pre></td></tr><tr><td scope="row"><pre></dict><span></span></pre></td></tr><tr><td scope="row"><pre></plist><span></span></pre></td></tr></table></div></section></section><section><a name="//apple_ref/doc/uid/10000172i-SW7-104738" title="Behavior for Processes Managed by launchd"></a><h2 class="jump">Behavior for Processes Managed by launchd</h2><p>Processes that are managed by <code>launchd</code> must follow certain requirements so that they interact properly with <code>launchd</code>. This includes launch daemons and launch agents.</p><section><a name="//apple_ref/doc/uid/10000172i-SW7-104302" title="Required Behaviors"></a><h3 class="jump">Required Behaviors</h3><a name="//apple_ref/doc/uid/10000172i-SW7-DontLinkElementID_15"></a><p>To support <code>launchd</code>, you must obey the following guidelines when writing your daemon code:</p><ul class="ul"><li class="li"><p>You must provide a property list with some basic launch-on-demand criteria for your daemon. See <span class="content_text"><a href="#//apple_ref/doc/uid/TP40001762-104142" data-renderer-version="1">Creating a launchd Property List File</a></span>. </p></li><li class="li"><a name="//apple_ref/doc/uid/10000172i-SW7-DontLinkElementID_16"></a><p>You must not daemonize your process. This includes calling the <code><a href="../../../../System/Conceptual/ManPages_iPhoneOS/man3/daemon.3.html#//apple_ref/doc/man/3/daemon" data-renderer-version="1" target="_self">daemon</a></code> function, calling <code><!--a target="_self" -->fork<!--/a--></code> followed by <code><a href="../../../../System/Conceptual/ManPages_iPhoneOS/man3/exec.3.html#//apple_ref/doc/man/3/exec" data-renderer-version="1" target="_self">exec</a></code>, or calling <code><!--a target="_self" -->fork<!--/a--></code> followed by <code><a href="../../../../System/Conceptual/ManPages_iPhoneOS/man3/exit.3.html#//apple_ref/doc/man/3/exit" data-renderer-version="1" target="_self">exit</a></code>. If you do, <code>launchd</code> thinks your process has died. Depending on your property list key settings, <code>launchd</code> will either keep trying to relaunch your process until it gives up (with a “respawning too fast” error message) or will be unable to restart it if it really does die.</p></li><li class="li"><p>Daemons and agents that are installed globally must be owned by the root user. Agents installed for the current user must be owned by that user. All daemons and agents must not be group writable or world writable. (That is, they must have file mode set to <code>600</code> or <code>400</code>.)</p></li></ul></section><section><a name="//apple_ref/doc/uid/10000172i-SW7-104489" title="Recommended Behaviors"></a><h3 class="jump">Recommended Behaviors</h3><a name="//apple_ref/doc/uid/10000172i-SW7-DontLinkElementID_17"></a><p>To support <code>launchd</code>, it is recommended that you obey the following guidelines when writing your daemon code:</p><ul class="ul"><li class="li"><a name="//apple_ref/doc/uid/10000172i-SW7-DontLinkElementID_18"></a><p>Wait until your daemon is fully initialized before attempting to process requests. Your daemon should always provide a reasonable response (rather than an error) when processing requests.</p></li><li class="li"><p>Register the sockets and file descriptors used by your daemon in your <code>launchd</code> configuration property list file.</p></li><li class="li"><p>If your daemon advertises a socket, check in with <code>launchd</code> as part of your daemon initialization. For an example implementation of the check-in process, see <em><a href="../../../../../samplecode/SampleD/Introduction/Intro.html#//apple_ref/doc/uid/DTS10003653" data-renderer-version="1" target="_self">SampleD</a></em>.</p></li><li class="li"><a name="//apple_ref/doc/uid/10000172i-SW7-DontLinkElementID_19"></a><p>During check-in, get the launch dictionary from <code>launchd</code>, extract and store its contents, and then discard the dictionary. Accessing the data structure used for the dictionary is very slow, so storing the whole dictionary locally and accessing it frequently could hurt performance.</p></li><li class="li"><a name="//apple_ref/doc/uid/10000172i-SW7-DontLinkElementID_20"></a><p>Provide a handler to catch the <code>SIGTERM</code> signal.</p></li></ul><p>In addition to the preceding list, the following is a list of things it is recommended you <em>avoid</em> in your code:</p><ul class="ul"><li class="li"><a name="//apple_ref/doc/uid/10000172i-SW7-DontLinkElementID_21"></a><a name="//apple_ref/doc/uid/10000172i-SW7-DontLinkElementID_22"></a><p>Do not set the user or group ID for your daemon. Include the <code>UserName</code>, <code>UID</code>, <code>GroupName</code>, or <code>GID</code> keys in your daemon’s configuration property list instead.</p></li><li class="li"><a name="//apple_ref/doc/uid/10000172i-SW7-DontLinkElementID_23"></a><p>Do not set the working directory. Include the <code>WorkingDirectory</code> key in your daemon’s configuration property list instead.</p></li><li class="li"><a name="//apple_ref/doc/uid/10000172i-SW7-DontLinkElementID_24"></a><p>Do not call <code>chroot</code> to change the root directory. Include the <code>RootDirectory</code> key in your daemon’s configuration property list instead.</p></li><li class="li"><p>Do not call <code>setsid</code> to create a new session.</p></li><li class="li"><p>Do not close any stray file descriptors.</p></li><li class="li"><p>Do not change <code>stdio</code> to point to <code>/dev/null</code>. Include the <code>StandardOutPath</code> or <code>StandardErrorPath</code> keys in your daemon’s configuration property list file instead.</p></li><li class="li"><a name="//apple_ref/doc/uid/10000172i-SW7-DontLinkElementID_25"></a><p>Do not set up resource limits with <code>setrusage</code>.</p></li><li class="li"><p>Do not set the daemon priority with <code>setpriority</code></p></li></ul><p>Although many of the preceding behaviors may be standard tasks for daemons to perform, they are not recommended when running under <code>launchd</code>. The reason is that <code>launchd</code> configures the operating environment for the daemons that it manages. Changing this environment could interfere with the normal operation of your daemon.</p></section></section><section><a name="//apple_ref/doc/uid/10000172i-SW7-107182" title="Deciding When to Shut Down"></a><h2 class="jump">Deciding When to Shut Down</h2><a name="//apple_ref/doc/uid/10000172i-SW7-DontLinkElementID_26"></a><p>If you do not expect your daemon to handle many requests, you might want to shut it down after a predetermined amount of idle time, rather than continue running. Although a well-written daemon does not consume any CPU resources when idle, it still consumes memory and could be paged out during periods of intense memory use. </p><p>The timing of when to shut down is different for each daemon and depends on several factors, including:</p><ul class="ul"><li class="li"><p>The number and frequency of requests it receives</p></li><li class="li"><p>The time it takes to launch the daemon</p></li><li class="li"><p>The time it takes to shut down the daemon</p></li><li class="li"><p>The need to retain state information</p></li></ul><p>If your daemon does not receive frequent requests and can be launched and shut down quickly, you might prefer to shut it down rather than wait for it to be paged out to disk. Paging memory to disk, and subsequently reading it back, incurs two disk operations. If you do not need the data stored in memory, your daemon can shut down and avoid the step of writing memory to disk.</p></section><section><a name="//apple_ref/doc/uid/10000172i-SW7-SW2" title="Special Dependencies"></a><h2 class="jump">Special Dependencies</h2><p>While <code><!--a target="_self" -->launchd<!--/a--></code> takes care of dependencies between daemons, in some cases, your daemon may depend on other system functionality that cannot be addressed in this manner. This section describes many of these special cases and how to handle them.</p><section><a name="//apple_ref/doc/uid/10000172i-SW7-SW10" title="Network Availability"></a><h3 class="jump">Network Availability</h3><p>If your daemon depends on the network being available, this cannot be handled with dependencies because network interfaces can come and go at any time in OS X. To solve this problem, you should use the network reachability functionality or the dynamic store functionality in the System Configuration framework. This is documented in <em><a href="../../../../Networking/Conceptual/SystemConfigFrameworks/SC_Intro/SC_Intro.html#//apple_ref/doc/uid/TP40001065" data-renderer-version="1" target="_self">System Configuration Programming Guidelines</a></em> and <em><a href="https://developer.apple.com/documentation/systemconfiguration" class="urlLink" target="_self">System Configuration Framework Reference</a></em>. For more information about network reachability, see <span class="content_text"><a href="../../../../Networking/Conceptual/SystemConfigFrameworks/SC_ReachConnect/SC_ReachConnect.html#//apple_ref/doc/uid/TP40001065-CH204" data-renderer-version="1" target="_self">Determining Reachability and Getting Connected</a></span> in <em><a href="../../../../Networking/Conceptual/SystemConfigFrameworks/SC_Intro/SC_Intro.html#//apple_ref/doc/uid/TP40001065" data-renderer-version="1" target="_self">System Configuration Programming Guidelines</a></em>.</p></section><section><a name="//apple_ref/doc/uid/10000172i-SW7-SW11" title="Disk or Server Availability"></a><h3 class="jump">Disk or Server Availability</h3><p>If your daemon depends on the availability of a mounted volume (whether local or remote), you can determine the status of that volume using the Disk Arbitration framework. This is documented in <em><a href="https://developer.apple.com/documentation/diskarbitration" class="urlLink" target="_self">Disk Arbitration Framework Reference</a></em>.</p></section><section><a name="//apple_ref/doc/uid/10000172i-SW7-SW12" title="Non-launchd Daemons"></a><h3 class="jump">Non-launchd Daemons</h3><p>If your daemon has a dependency on a non-<code>launchd</code> daemon, you must take additional care to ensure that your daemon works correctly if that non-<code>launchd</code> daemon has not started when your daemon is started. The best way to do this is to include a loop at start time that checks to see if the non-<code>launchd</code> daemon is running, and if not, sleeps for several seconds before checking again.</p><p>Be sure to set up handlers for <code>SIGTERM</code> prior to this loop to ensure that you are able to properly shut down if the daemon you rely on never becomes available.</p></section><section><a name="//apple_ref/doc/uid/10000172i-SW7-SW13" title="User Logins"></a><h3 class="jump">User Logins</h3><p>In general, a daemon should not care whether a user is logged in, and user agents should be used to provide per-user functionality. However, in some cases, this may be useful.</p><p>To determine what user is logged in at the console, you can use the System Configuration framework, as described in <span class="content_text"><a href="http://developer.apple.com/qa/qa2001/qa1133.html" class="browserLink" >Technical Q&A QA1133</a></span>.</p></section><section><a name="//apple_ref/doc/uid/10000172i-SW7-SW14" title="Kernel Extensions"></a><h3 class="jump">Kernel Extensions</h3><p>If your daemon requires that a certain kernel extension be loaded prior to executing, you have two options: load it yourself, or wait for it to be loaded.</p><p>The daemon may manually request that an extension be loaded. To do this, run <code><!--a target="_self" -->kextload<!--/a--></code> with the appropriate arguments using <code><a href="../../../../System/Conceptual/ManPages_iPhoneOS/man3/exec.3.html#//apple_ref/doc/man/3/exec" data-renderer-version="1" target="_self">exec</a></code> or variants thereof. I/O Kit kernel extensions should not be loaded with <code>kextload</code>; the I/O Kit will load them automatically when they are needed.</p><div class="notebox"><aside><a name="//apple_ref/doc/uid/10000172i-SW7-SW15" title="Note"></a><p><strong>Note:</strong> The <code>kextload</code> executable must be run as root in order to load extensions into the kernel. For security reasons, it is not a setuid executable. This means that your daemon must either be running as the root user or must include a helper binary that is setuid root in order to use <code>kextload</code> to load a kernel extension.</p><p></p></aside></div><p>Alternatively, our daemon may wait for a kernel service to be available. To do this, you should first register for service change notification. This is further documented in <em><a href="https://developer.apple.com/documentation/iokit" class="urlLink" target="_self">I/O Kit Framework Reference</a></em>.</p><p>After registering for these notifications, you should check to see if the service is already available. By doing this after registering for notifications, you avoid waiting forever if the service becomes available between checking for availability and registering for the notification.</p><div class="notebox"><aside><a name="//apple_ref/doc/uid/10000172i-SW7-SW16" title="Note"></a><p><strong>Note:</strong> In order for your kernel extension to be detected in a useful way, it must publish a node in the I/O registry to advertise the availability of its service. For I/O Kit drivers, this is usually handled by the I/O Kit family.</p><p>For other kernel extensions, you must explicitly register the service by publishing a nub, which must be an instance of <code><a href="https://developer.apple.com/documentation/kernel/ioservice" class="urlLink" target="_self">IOService</a></code>.</p><p></p></aside></div><p>For more information about I/O Kit services and matching, see <em><a href="../../../../DeviceDrivers/Conceptual/IOKitFundamentals/Introduction/Introduction.html#//apple_ref/doc/uid/TP0000011" data-renderer-version="1" target="_self">IOKit Fundamentals</a></em>, <em><a href="https://developer.apple.com/documentation/iokit" class="urlLink" target="_self">I/O Kit Framework Reference</a></em> (user space reference), and <em><a href="https://developer.apple.com/documentation/kernel" class="urlLink" target="_self">Kernel Framework Reference</a></em> (kernel space reference).</p></section></section><section><a name="//apple_ref/doc/uid/10000172i-SW7-SW6" title="For More Information"></a><h2 class="jump">For More Information</h2><p>The manual pages for <code><!--a target="_self" -->launchd<!--/a--></code> and <code><!--a target="_self" -->launchd.plist<!--/a--></code> are the two best sources for information about <code>launchd</code>.</p><p>In addition, you can find a source daemon accompanying the <code>launchd</code> source code (available from <span class="content_text"><a href="http://www.macosforge.org/" class="urlLink" rel="external">http://www.macosforge.org/</a></span>). This daemon is also provided from the Mac Developer Library as the <span class="content_text"><a href="../../../../../samplecode/SampleD/Introduction/Intro.html#//apple_ref/doc/uid/DTS10003653-Intro" data-renderer-version="1" target="_self">SampleD</a></span> sample code project.</p><p>The <em><a href="../../../../../technotes/tn2083/_index.html#//apple_ref/doc/uid/DTS10003794" data-renderer-version="1" target="_self">Daemons and Agents</a></em> technical note provides additional information about how <code>launchd</code> daemons and agents work under the hood.</p><p>Finally, many Apple-provided daemons support <code>launchd</code>. Their property list files can be found in <code>/System/Library/LaunchDaemons</code>. Some of these daemons are also available as open source from <span class="content_text"><a href="http://www.opensource.apple.com/" class="urlLink" rel="external">http://www.opensource.apple.com/</a></span> or <span class="content_text"><a href="http://www.macosforge.org/" class="urlLink" rel="external">http://www.macosforge.org/</a></span>.</p></section> <div id="pageNavigationLinks_bottom" class="pageNavigationLinks"> <a class='nextLink' rel='next' href='ScheduledJobs.html'>Next</a><a class='previousLink' rel='prev' href='CreatingXPCServices.html'>Previous</a> </div><br/> <div class="copyright"><br/><hr /><div align="center"><p class="content_text" lang="en" dir="ltr"> Copyright © 2003, 2016 Apple Inc. All Rights Reserved. <a href="http://www.apple.com/legal/internet-services/terms/site.html" target="_blank">Terms of Use</a> | <a href="http://www.apple.com/privacy/" target="_blank">Privacy Policy</a> | Updated: 2016-09-13</p></div></div> <div id="pediaWindow"> <div id="pediaHeader"></div> <div id="pediaBody"></div> </div> </article> <div id="blackout"> <div id="preload"></div> </div> <div id="modal" aria-hidden="true"> <div id="closebox" tabindex="0" aria-label="Close feedback form" role="button"></div> <div id="sending" class="hidden"> <h2 tabindex="0">Sending feedback…</h2> <div id="sending_img"></div> </div> <div id="error" class="hidden"> <h2 tabindex="0">We’re sorry, an error has occurred.</h2> <p>Please try submitting your feedback later.</p> <div id="error_icon"></div> </div> <div id="success" class="hidden"> <h2 tabindex="0">Thank you for providing feedback!</h2> <p>Your input helps improve our developer documentation.</p> <div id="thank_you_icon"></div> </div> <form id="feedback" action="#" method="post"> <div class="left-leaf"> <h2 id="helpful_title" data-asterisk="a1" tabindex="0">How helpful is this document?</h2> <sup id="a1" class="asterisk" aria-hidden="true">*</sup> <div id="star_group" role="radiogroup" aria-required="true"> <label> <input class="radio" type="radio" name="helped" value="1" /> Very helpful </label> <label> <input class="radio" type="radio" name="helped" value="2" /> Somewhat helpful </label> <label> <input class="radio" type="radio" name="helped" value="3" /> Not helpful </label> </div> </div> <div class="right-leaf"> <h2>How can we improve this document?</h2> <div id="improve" class="checkboxes"> <label> <input type="checkbox" name="typo" /> Fix typos or links </label> <label> <input type="checkbox" name="infoIncorrect" /> Fix incorrect information </label> <label> <input type="checkbox" name="needs_examples" /> Add or update code samples </label> <label> <input type="checkbox" name="needs_art" /> Add or update illustrations </label> <label> <input type="checkbox" name="missingInfo" /> Add information about... </label> </div> </div> <textarea id="comment" name="problem" cols="70" rows="8" placeholder="Please tell us more about your experience with this document" data-asterisk="a2" required></textarea> <sup id="a2" class="asterisk" aria-hidden="true">*</sup> <p class="fineprint"> <em aria-hidden="true"><span>*</span> Required information</em> </p> <input id="submit" type="button" value="Send" /> <section id="legal"> <p> To submit a product bug or enhancement request, please visit the <a href="https://developer.apple.com/bugreporter/" target="_blank">Bug Reporter</a> page. </p> <p> Please read <a href="http://www.apple.com/legal/policies/ideas.html" target="_blank">Apple's Unsolicited Idea Submission Policy</a> before you send us your feedback. </p> </section> </form> </div> <script charset="utf-8" src="../../../../../Resources/1282/JavaScript/lib/prototype.js"></script> <script src="../../../../../Resources/1282/JavaScript/library.js"></script> </body> </html>