]>
Commit | Line | Data |
---|---|---|
ab36757d A |
1 | <html> |
2 | <body> | |
3 | <h1>Getting Started With Launchd</h1> | |
4 | ||
5 | <p>Launchd is rather simple actually. Far simpler than you might think.</p> | |
6 | ||
7 | <h2>Before We Get Started</h2> | |
8 | ||
9 | <p>Launchd, in an effort to be consistent with other Apple software, uses the | |
10 | Property List file format for storing configuration information. Apple's | |
11 | Property List APIs provide for three different file formats for storing a | |
12 | property list to disk. A plain text option, a binary option, and an XML text | |
13 | option. For the remainder of this HOWTO, we will use the XML varient to show | |
14 | what a configuration file looks like.</p> | |
15 | ||
16 | <h3>The basics:</h3> | |
17 | ||
18 | <p>For the simplest of scenarios, launchd just keeps a process alive. A simple "hello | |
19 | world" example of that would be:</p> | |
20 | ||
21 | <blockquote><pre> | |
22 | <?xml version="1.0" encoding="UTF-8"?> | |
23 | <!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | |
24 | <plist version="1.0"> | |
25 | <dict> | |
26 | <key>Label</key> | |
27 | <string>com.example.sleep</string> | |
28 | <key>ProgramArguments</key> | |
29 | <array> | |
30 | <string>sleep</string> | |
31 | <string>100</string> | |
32 | </array> | |
33 | <key>OnDemand</key> | |
34 | <false/> | |
35 | </dict> | |
36 | </plist> | |
37 | </pre></blockquote> | |
38 | ||
39 | <p>In the above example, we have three keys to our top level dictionary. The first | |
40 | is the <code>Label</code> which is what is used to uniquely identify jobs when interacting | |
41 | with launchd. The second is <code>ProgramArguments</code> which for its value, we have an | |
42 | array of strings which represent the tokenized arguments and the program to | |
43 | run. The third and final key is <code>OnDemand</code> which overrides the default value of | |
44 | true with false thereby instructing launchd to always try and keep this job | |
45 | running. That's it! A <code>Label</code>, some <code>ProgramArguments</code> and <code>OnDemand</code> set to false is all | |
46 | you need to keep a daemon alive with launchd!</p> | |
47 | ||
48 | <p>Now if you've ever written a daemon before, you've either called the | |
49 | <code>daemon()</code> function or written one yourself. With launchd, that is | |
50 | not only unnecessary, but unsupported. If you try and run a daemon you didn't | |
51 | write under launchd, you must, at the very least, find a configuration option to | |
52 | keep the daemon from daemonizing itself so that launchd can monitor it.</p> | |
53 | ||
54 | <h3>Going beyond the basics with optional keys:</h3> | |
55 | ||
56 | <p>There are many optional keys available and documented in the launchd.plist | |
57 | man page, so we'll only give a few optional, but common examples:</p> | |
58 | ||
59 | <blockquote><pre> | |
60 | <?xml version="1.0" encoding="UTF-8"?> | |
61 | <!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | |
62 | <plist version="1.0"> | |
63 | <dict> | |
64 | <key>Label</key> | |
65 | <string>com.example.sleep</string> | |
66 | <key>ProgramArguments</key> | |
67 | <array> | |
68 | <string>sleep</string> | |
69 | <string>100</string> | |
70 | </array> | |
71 | <key>OnDemand</key> | |
72 | <false/> | |
73 | <key>UserName</key> | |
74 | <string>daemon</string> | |
75 | <key>GroupName</key> | |
76 | <string>daemon</string> | |
77 | <key>EnvironmentVariables</key> | |
78 | <dict> | |
79 | <key>FOO</key> | |
80 | <string>bar</string> | |
81 | </dict> | |
82 | </dict> | |
83 | </plist> | |
84 | </pre></blockquote> | |
85 | ||
86 | <p>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.</p> | |
87 | ||
88 | <h3>Debugging tricks:</h3> | |
89 | ||
90 | <p>The following example will enable core dumps, set standard out and error to | |
91 | go to a log file and to instruct launchd to temporarily bump up the debug level | |
92 | of launchd's loggging while acting on behave of your job (remember to adjust | |
93 | your syslog.conf accordingly):</p> | |
94 | ||
95 | <blockquote><pre> | |
96 | <?xml version="1.0" encoding="UTF-8"?> | |
97 | <!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | |
98 | <plist version="1.0"> | |
99 | <dict> | |
100 | <key>Label</key> | |
101 | <string>com.example.sleep</string> | |
102 | <key>ProgramArguments</key> | |
103 | <array> | |
104 | <string>sleep</string> | |
105 | <string>100</string> | |
106 | </array> | |
107 | <key>OnDemand</key> | |
108 | <false/> | |
109 | <key>StandardOutPath</key> | |
110 | <string>/var/log/myjob.log</string> | |
111 | <key>StandardErrorPath</key> | |
112 | <string>/var/log/myjob.log</string> | |
113 | <key>Debug</key> | |
114 | <true/> | |
115 | <key>SoftResourceLimits</key> | |
116 | <dict> | |
117 | <key>Core</key> | |
118 | <integer>9223372036854775807</integer> | |
119 | </dict> | |
120 | <key>HardResourceLimits</key> | |
121 | <dict> | |
122 | <key>Core</key> | |
123 | <integer>9223372036854775807</integer> | |
124 | </dict> | |
125 | </dict> | |
126 | </plist> | |
127 | </pre></blockquote> | |
128 | ||
129 | <h2>But what if I don't want or expect my job to run continuously?</h2> | |
130 | ||
131 | <h3>The basics of on demand launching:</h3> | |
132 | ||
133 | <p>Launchd provides a multitude of different criteria that can be used to specify | |
134 | when a job should be started. It is important to note that launchd will only | |
135 | run one instance of your job though. Therefore, if your on demand job | |
136 | malfunctions, you are guaranteed that launchd will not spawn additional copies | |
137 | when your criteria is satisfied once more in the future.</p> | |
138 | ||
139 | <h3>Starting a job periodically:</h3> | |
140 | ||
141 | <p>Here is an example on how to have a job start every five minutes (300 seconds):</p> | |
142 | ||
143 | <blockquote><pre> | |
144 | <?xml version="1.0" encoding="UTF-8"?> | |
145 | <!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | |
146 | <plist version="1.0"> | |
147 | <dict> | |
148 | <key>Label</key> | |
149 | <string>com.example.touchsomefile</string> | |
150 | <key>ProgramArguments</key> | |
151 | <array> | |
152 | <string>touch</string> | |
153 | <string>/tmp/helloworld</string> | |
154 | </array> | |
155 | <key>StartInterval</key> | |
156 | <integer>300</integer> | |
157 | </dict> | |
158 | </plist> | |
159 | </pre></blockquote> | |
160 | ||
161 | <p>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 <code>StartCalendarInterval</code> dictionary is treated as a wildcard:</p> | |
162 | ||
163 | <blockquote><pre> | |
164 | <?xml version="1.0" encoding="UTF-8"?> | |
165 | <!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | |
166 | <plist version="1.0"> | |
167 | <dict> | |
168 | <key>Label</key> | |
169 | <string>com.example.touchsomefile</string> | |
170 | <key>ProgramArguments</key> | |
171 | <array> | |
172 | <string>touch</string> | |
173 | <string>/tmp/helloworld</string> | |
174 | </array> | |
175 | <key>StartCalendarInterval</key> | |
176 | <dict> | |
177 | <key>Minute</key> | |
178 | <integer>11</integer> | |
179 | <key>Hour</key> | |
180 | <integer>11</integer> | |
181 | <key>Day</key> | |
182 | <integer>11</integer> | |
183 | </dict> | |
184 | </dict> | |
185 | </pre></blockquote> | |
186 | ||
187 | <h3>Starting a job based on file system activity:</h3> | |
188 | ||
189 | <p>The following example will start the job whenever any of the paths being watched change for whatever reason:</p> | |
190 | ||
191 | <blockquote><pre> | |
192 | <?xml version="1.0" encoding="UTF-8"?> | |
193 | <!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | |
194 | <plist version="1.0"> | |
195 | <dict> | |
196 | <key>Label</key> | |
197 | <string>com.example.watchetchostconfig</string> | |
198 | <key>ProgramArguments</key> | |
199 | <array> | |
200 | <string>syslog</string> | |
201 | <string>-s</string> | |
202 | <string>-l</string> | |
203 | <string>notice</string> | |
204 | <string>somebody touched /etc/hostconfig</string> | |
205 | </array> | |
206 | <key>WatchPaths</key> | |
207 | <array> | |
208 | <string>/etc/hostconfig</string> | |
209 | </array> | |
210 | </dict> | |
211 | </pre></blockquote> | |
212 | ||
213 | <p>An additional file system trigger is the notion of a queue directory. Launchd will star your job whenever | |
214 | the given directories are non-empty and will keep your job running as long as those directories are not empty:</p> | |
215 | ||
216 | <blockquote><pre> | |
217 | <?xml version="1.0" encoding="UTF-8"?> | |
218 | <!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | |
219 | <plist version="1.0"> | |
220 | <dict> | |
221 | <key>Label</key> | |
222 | <string>com.example.mailpush</string> | |
223 | <key>ProgramArguments</key> | |
224 | <array> | |
225 | <string>my_custom_mail_push_tool</string> | |
226 | </array> | |
227 | <key>QueueDirectories</key> | |
228 | <array> | |
229 | <string>/var/spool/mymailqdir</string> | |
230 | </array> | |
231 | </dict> | |
232 | </pre></blockquote> | |
233 | ||
234 | <h3>Inetd Emulation</h3> | |
235 | ||
236 | <p>Launchd will happily emulate inetd style daemon semantics:</p> | |
237 | ||
238 | <blockquote><pre> | |
239 | <?xml version="1.0" encoding="UTF-8"?> | |
240 | <!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | |
241 | <plist version="1.0"> | |
242 | <dict> | |
243 | <key>Label</key> | |
244 | <string>com.example.telnetd</string> | |
245 | <key>ProgramArguments</key> | |
246 | <array> | |
247 | <string>/usr/libexec/telnetd</string> | |
248 | </array> | |
249 | <key>inetdCompatibility</key> | |
250 | <dict> | |
251 | <key>Wait</key> | |
252 | <false/> | |
253 | </dict> | |
254 | <key>Sockets</key> | |
255 | <dict> | |
256 | <key>Listeners</key> | |
257 | <dict> | |
258 | <key>SockServiceName</key> | |
259 | <string>telnet</string> | |
260 | <key>SockType</key> | |
261 | <string>stream</string> | |
262 | </dict> | |
263 | </dict> | |
264 | </dict> | |
265 | </pre></blockquote> | |
266 | ||
267 | <h1>TBD</h1> | |
268 | ||
269 | </body> | |
270 | </html> |