X-Git-Url: https://git.saurik.com/apple/launchd.git/blobdiff_plain/e91b9f68c8f72465f3a6a45ce0aa2ad44c776f32..ab36757d38bc3680d699f3d9d5c21650195fc635:/launchd/doc/HOWTO.html diff --git a/launchd/doc/HOWTO.html b/launchd/doc/HOWTO.html new file mode 100644 index 0000000..a166903 --- /dev/null +++ b/launchd/doc/HOWTO.html @@ -0,0 +1,270 @@ + + +

Getting Started With Launchd

+ +

Launchd is rather simple actually. Far simpler than you might think.

+ +

Before We Get Started

+ +

Launchd, in an effort to be consistent with other Apple software, uses the +Property List file format for storing configuration information. Apple's +Property List APIs provide for three different file formats for storing a +property list to disk. A plain text option, a binary option, and an XML text +option. For the remainder of this HOWTO, we will use the XML varient to show +what a configuration file looks like.

+ +

The basics:

+ +

For the simplest of scenarios, launchd just keeps a process alive. A simple "hello +world" example of that would be:

+ +
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+        <key>Label</key>
+        <string>com.example.sleep</string>
+        <key>ProgramArguments</key>
+        <array>
+                <string>sleep</string>
+                <string>100</string>
+        </array>
+        <key>OnDemand</key>
+        <false/>
+</dict>
+</plist>
+
+ +

In the above example, we have three keys to our top level dictionary. The first +is the Label which is what is used to uniquely identify jobs when interacting +with launchd. The second is ProgramArguments which for its value, we have an +array of strings which represent the tokenized arguments and the program to +run. The third and final key is OnDemand which overrides the default value of +true with false thereby instructing launchd to always try and keep this job +running. That's it! A Label, some ProgramArguments and OnDemand set to false is all +you need to keep a daemon alive with launchd!

+ +

Now if you've ever written a daemon before, you've either called the +daemon() function or written one yourself. With launchd, that is +not only unnecessary, but unsupported. If you try and run a daemon you didn't +write under launchd, you must, at the very least, find a configuration option to +keep the daemon from daemonizing itself so that launchd can monitor it.

+ +

Going beyond the basics with optional keys:

+ +

There are many optional keys available and documented in the launchd.plist +man page, so we'll only give a few optional, but common examples:

+ +
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+        <key>Label</key>
+        <string>com.example.sleep</string>
+        <key>ProgramArguments</key>
+        <array>
+                <string>sleep</string>
+                <string>100</string>
+        </array>
+        <key>OnDemand</key>
+        <false/>
+        <key>UserName</key>
+        <string>daemon</string>
+        <key>GroupName</key>
+        <string>daemon</string>
+        <key>EnvironmentVariables</key>
+	<dict>
+		<key>FOO</key>
+		<string>bar</string>
+	</dict>
+</dict>
+</plist>
+
+ +

In the above example, we see that the job is run as a certain user and group, and additionally has an extra environment variable set.

+ +

Debugging tricks:

+ +

The following example will enable core dumps, set standard out and error to +go to a log file and to instruct launchd to temporarily bump up the debug level +of launchd's loggging while acting on behave of your job (remember to adjust +your syslog.conf accordingly):

+ +
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+        <key>Label</key>
+        <string>com.example.sleep</string>
+        <key>ProgramArguments</key>
+        <array>
+                <string>sleep</string>
+                <string>100</string>
+        </array>
+        <key>OnDemand</key>
+        <false/>
+        <key>StandardOutPath</key>
+        <string>/var/log/myjob.log</string>
+        <key>StandardErrorPath</key>
+        <string>/var/log/myjob.log</string>
+        <key>Debug</key>
+        <true/>
+        <key>SoftResourceLimits</key>
+	<dict>
+	        <key>Core</key>
+		<integer>9223372036854775807</integer>
+	</dict>
+        <key>HardResourceLimits</key>
+	<dict>
+	        <key>Core</key>
+		<integer>9223372036854775807</integer>
+	</dict>
+</dict>
+</plist>
+
+ +

But what if I don't want or expect my job to run continuously?

+ +

The basics of on demand launching:

+ +

Launchd provides a multitude of different criteria that can be used to specify +when a job should be started. It is important to note that launchd will only +run one instance of your job though. Therefore, if your on demand job +malfunctions, you are guaranteed that launchd will not spawn additional copies +when your criteria is satisfied once more in the future.

+ +

Starting a job periodically:

+ +

Here is an example on how to have a job start every five minutes (300 seconds):

+ +
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+        <key>Label</key>
+        <string>com.example.touchsomefile</string>
+        <key>ProgramArguments</key>
+        <array>
+                <string>touch</string>
+		<string>/tmp/helloworld</string>
+        </array>
+        <key>StartInterval</key>
+	<integer>300</integer>
+</dict>
+</plist>
+
+ +

Sometimes you want a job started on a calendar based interval. The following example will start the job on the 11th minute of the 11th hour every day (using a 24 hour clock system) on the 11th day of the month. Like the Unix cron subsystem, any missing key of the StartCalendarInterval dictionary is treated as a wildcard:

+ +
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+        <key>Label</key>
+        <string>com.example.touchsomefile</string>
+        <key>ProgramArguments</key>
+        <array>
+                <string>touch</string>
+		<string>/tmp/helloworld</string>
+        </array>
+        <key>StartCalendarInterval</key>
+        <dict>
+        	<key>Minute</key>
+		<integer>11</integer>
+		<key>Hour</key>
+		<integer>11</integer>
+		<key>Day</key>
+		<integer>11</integer>
+        </dict>
+</dict>
+
+ +

Starting a job based on file system activity:

+ +

The following example will start the job whenever any of the paths being watched change for whatever reason:

+ +
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+        <key>Label</key>
+	<string>com.example.watchetchostconfig</string>
+        <key>ProgramArguments</key>
+        <array>
+                <string>syslog</string>
+                <string>-s</string>
+                <string>-l</string>
+                <string>notice</string>
+		<string>somebody touched /etc/hostconfig</string>
+        </array>
+	<key>WatchPaths</key>
+        <array>
+        	<string>/etc/hostconfig</string>
+        </array>
+</dict>
+
+ +

An additional file system trigger is the notion of a queue directory. Launchd will star your job whenever +the given directories are non-empty and will keep your job running as long as those directories are not empty:

+ +
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+        <key>Label</key>
+	<string>com.example.mailpush</string>
+        <key>ProgramArguments</key>
+        <array>
+		<string>my_custom_mail_push_tool</string>
+        </array>
+	<key>QueueDirectories</key>
+        <array>
+        	<string>/var/spool/mymailqdir</string>
+        </array>
+</dict>
+
+ +

Inetd Emulation

+ +

Launchd will happily emulate inetd style daemon semantics:

+ +
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+        <key>Label</key>
+	<string>com.example.telnetd</string>
+        <key>ProgramArguments</key>
+        <array>
+		<string>/usr/libexec/telnetd</string>
+        </array>
+	<key>inetdCompatibility</key>
+        <dict>
+        	<key>Wait</key>
+        	<false/>
+        </dict>
+        <key>Sockets</key>
+        <dict>
+        	<key>Listeners</key>
+        	<dict>
+        		<key>SockServiceName</key>
+        		<string>telnet</string>
+        		<key>SockType</key>
+        		<string>stream</string>
+        	</dict>
+        </dict>
+</dict>
+
+ +

TBD

+ + +