summaryrefslogtreecommitdiff
path: root/doc/s6-rc.html
blob: 7052b45f1c0059e96c6ec738a70a5c19771d60ac (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
<html>
  <head>
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <meta http-equiv="Content-Language" content="en" />
    <title>s6-rc: the s6-rc program</title>
    <meta name="Description" content="s6-rc: the s6-rc program" />
    <meta name="Keywords" content="s6-rc command rc init dependency state management services" />
    <!-- <link rel="stylesheet" type="text/css" href="//skarnet.org/default.css" /> -->
  </head>
<body>

<p>
<a href="index.html">s6-rc</a><br />
<a href="//skarnet.org/software/">Software</a><br />
<a href="//skarnet.org/">skarnet.org</a>
</p>

<h1> The s6-rc program </h1>

<p>
 s6-rc is a <em>service manager</em>, a.k.a <em>machine state manager</em>:
a program to manage the <em>live state</em> of a machine -
what services are currently up and what services are currently down. It
can list active services, or change the live state.
</p>

<p>
 s6-rc is meant to be the one-stop shop of service management: once
service definitions have been made into a compiled service database
via <a href="s6-rc-compile.html">s6-rc-compile</a>, and the machine
state has been initialized via <a href="s6-rc-init.html">s6-rc-init</a>,
any state change - be it initial startup, shutdown, or anything else -
should be achieved by a single <tt>s6-rc change</tt> invocation.
</p>

<p>
 Except in test installations with specifically made compiled
databases and live directories, s6-rc should only be run as root -
especially when asking for a state change.
</p>

<h2> Interface </h2>

<pre>
     s6-rc help
     s6-rc [ -l live ] [ -b ] [ -a ] [ -u | -d ] list <em>servicenames...</em>
     s6-rc [ -l live ] [ -b ] [ -a ] [ -u | -d ] listall <em>servicenames...</em>
     s6-rc [ -l live ] [ -b ] [ -a ] [ -u | -d ] [ -p ] [ -v <em>verbosity</em> ] [ -n <em>dryrunthrottle</em> ] [ -t timeout ] change [ <em>servicenames...</em> ]
</pre>

<ul>
 <li> s6-rc expects to find a functional <em>live state</em> in
<em>live</em>. The live state is normally created at boot time by
<a href="s6-rc-init.html">s6-rc-init</a>. If the live state is
invalid, s6-rc complains and exits 4. </li>
 <li> Depending on the arguments given, it prints the requested
information to stdout, then exits 0; or it performs a machine
state change. </li>
</ul>

<h2> Exit codes </h2>

<ul>
 <li> 0: success </li>
 <li> 1: some of the state transitions could not be performed </li>
 <li> 2: timed out during state change </li>
 <li> 3: unknown service name in the arguments </li>
 <li> 4: invalid service database </li>
 <li> 100: wrong usage </li>
 <li> 111: system call failed </li>
</ul>

<h2> Service selection </h2>

<p>
The arguments <em>servicenames...</em> may be atomic services or
bundles; they are resolved into a set of atomic services, which is
called the <em>selection</em>. If the <tt>-a</tt> option is present,
the current set of active services (i.e. services that are up) is
added to the selection.
<strong>The s6-rc command always operates on the selection</strong>.
</p>

<h2> Options </h2>

<h3> General options </h3>

<ul>
 <li> <tt>-l&nbsp;<em>live</em></tt>&nbsp;: look for the
live state in <em>live</em>. Default is
<tt>/run/s6-rc</tt>. The default can be changed at compile-time by
giving the <tt>--livedir=<em>live</em></tt> option to <tt>./configure</tt>. </li>
 <li> <tt>-a</tt>&nbsp;: add the current set of active services to
the selection. This is useful for instance at
shutdown time: <tt>s6-rc -da change</tt>
will stop all services. </li>
 <li> <tt>-b</tt>&nbsp;: blocking lock. If the service database is currently
being used by another program, s6-rc will wait until that
other program has released its lock on the database, then proceed.
By default, s6-rc fails with an error message if the service database
is currently in use. The default is the safe behaviour: for instance,
it will correctly detect and fail nested s6-rc invocations (which are
an admin error), whereas <tt>s6-rc -b</tt> would deadlock in
such a case. </li>
</ul>

<h3> Up or down </h3>

<p>
 These options control what is to be done: bring selected services
up or down (for <tt>s6-rc change</tt>) or whether to use the
forward or reverse dependency graph (for <tt>s6-rc listall</tt>).
Default is <em>up</em>.
</p>

<ul>
 <li> <tt>-u</tt>&nbsp;: up. </li>
 <li> <tt>-d</tt>&nbsp;: down. </li>
</ul>

<h3> <tt>s6-rc change</tt> control </h3>

<ul>
 <li> <tt>-v&nbsp;<em>verbosity</em></tt>&nbsp;: be more or less
verbose. Default is 1: warning and error messages will be printed to
stderr. 0 silences warnings. 2 writes information messages whenever
s6-rc performs a transition. 3 or more is debug info. </li>
 <li> <tt>-n&nbsp;<em>dryruntimeout</em></tt>&nbsp;: dry run.
s6-rc will pretend to perform transitions, but will replace all its
program invocations by a call to
<a href="s6-rc-dryrun.html">s6-rc-dryrun</a>, which will do nothing but
print the command line s6-rc would have executed, then sleep for
<em>dryruntimeout</em> milliseconds before reporting success. </li>
 <li> <tt>-t&nbsp;<em>timeout</em></tt>&nbsp;: timeout. If s6-rc
isn't done after <em>timeout</em> milliseconds, it will exit, leaving
the live state as it is at exit time. It does not kill its children, so
a child may successfully complete afterwards and the live state will
not be updated; in that case, subsequent <tt>s6-rc change</tt>
invocations will notice
and correctly update it. </li>
 <li> <tt>-p</tt>&nbsp;: prune. The state will be brought to
<em>exactly</em> the set of selected services, plus their dependencies, and
the other services will be brought down. With the <tt>-d</tt> option,
the meaning is reversed: the state will be brought to the maximum
possible set that does not include selected services. The change, however,
is always performed in the same manner: first the unwanted services are
all brought down, then the wanted services are all brought up. </li>
</ul>

<h2> Subcommands </h2>

<h3> s6-rc help </h3>

<p>
 Prints a short help message.
</p>

<h3> s6-rc list <em>servicenames...</em> </h3>

<p>
 Prints the selection. If the <tt>-d</tt> option has been given,
the selection is inverted before it is printed, i.e. all the
services but <em>servicenames...</em> will be printed.
</p>

<p>
 This is mostly useful as <tt>s6-rc -a list</tt>, which simply prints
the list of currently active services. <tt>s6-rc -da list</tt>
will print the list of currently down services.
</p>

<h3> s6-rc listall <em>servicenames...</em> </h3>

<ul>
 <li> s6-rc computes the complete dependency tree of the
selection: the selection, plus the dependencies of every service
in the selection, and recursively down. With the <tt>-d</tt>
option, it computes the reverse dependency tree: the selection,
plus what depends on it, and recursively up. The result is
called the <em>closed selection</em>. </li>
 <li> It prints the closed selection to its standard output.
Note that the closed selection may be a very long list of services,
including the most basic ones. </li>
</ul>

<h3> s6-rc change </h3>

<p>
 <tt>s6-rc change</tt> is the service state engine. It will bring the
machine to a state where:
</p>

<ul>
 <li> <tt>-u</tt> (default): all the services in the selection are up </li>
 <li> <tt>-d</tt>: all the services in the selection are down </li>
 <li> <tt>-pu</tt>: all the services in the selection, and <em>only</em> them, are up </li>
 <li> <tt>-pd</tt>: all the services in the selection, and <em>only</em> them, are down </li>
</ul>

<p>
 To do so:
</p>

<ul>
 <li> From the selection, s6-rc computes the closed selection </li>
 <li> It then computes the necessary transitions so that all the
services in the closed selection can match the desired state </li>
 <li> It then performs the transitions - or simulates them if the
<tt>-n</tt> option has been given. </li>
 <li> s6-rc processes services as soon as they can be processed:
as soon as a service that needs to change state has all its dependencies
fulfilled, it undergoes its transition. Independent services are processed
in parallel: s6-rc parallelizes the transitions as much as it can, and
there is no useless waiting time. </li>
 <li> s6-rc updates the live state in <em>live</em> after every
successful transition. </li>
 <li> If every transition completes successfully, the live state
eventually matches the desired state, and s6-rc exits 0. </li>
 <li> If a transition fails, s6-rc will not perform the transitions
that depend on it. It will keep processing all the other independent
transitions, though, until there is no more work it can complete; then
it will exit 1. </li>
</ul>

<h4> Longrun transitions </h4>

<p>
 Transitions for longrun services are simple: s6-rc removes or creates
a <tt>./down</tt> file in the live service directory for the longrun
service, then sends a command
to the supervision tree to start or stop the service. (A service that
is considered down by s6-rc will have a <tt>./down</tt> file in its live service
directory; a service that is considered up by s6-rc will not.) The
transition is considered successful as soon as the daemon dies (for
down transitions), or becomes up and
<a href="//skarnet.org/software/s6/notifywhenup.html">ready</a>
(for up transitions). If a longrun service does not support
readiness notification, the
<a href="//skarnet.org/software/s6/s6-svc.html">s6-svc</a>
command that is invoked by s6-rc will print a warning message, and
the transition will be considered successful as soon as the daemon
is up, i.e. as soon as the <tt>./run</tt> script is executed by
<a href="//skarnet.org/software/s6/s6-supervise.html">s6-supervise</a>.
</p>

<p>
 When a longrun service supports readiness notification, unless
a nonzero timeout has been declared in the <tt>timeout-up</tt> file
in the service definition directory,
s6-rc will wait forever on an "up" transition for the notification
to arrive. The transition will fail if a timeout occurs.
</p>

<p>
 If a <em>down</em> transition fails, s6-rc does nothing with it. The service
has already received a SIGTERM, and may be stuck in the process of exiting;
or it may already have died but is stuck in a bad <tt>finish</tt> script
that is not timing out. In any case, it is not a situation that s6-rc
can recover from; the service is most likely down, but the administrator
should manually check their process list. And fix their scripts, or
timeout values, because a <em>down</em> transition failure is always a
programmer or sysadmin error.
</p>

<p>
 If an <em>up</em> transition fails, s6-rc sends an explicit
<a href="//skarnet.org/software/s6/s6-svc.html">s6-svc -d</a> command to
the longrun. This ensures the service is in a known <em>down</em> state
when failing to go up, instead of (for instance) being stuck in a not-ready
limbo state.
</p>

<p>
 Note that proper usage of the <tt>timeout-kill</tt> and <tt>timeout-finish</tt>
values in the longrun's definition directory can considerably reduce the
number of cases where the service is left in an unknown state.
</p>

<p>
 Transitions are supposed to be idempotent, but it is a general
rule of supervision that <tt>run</tt> and <tt>finish</tt> scripts
must be idempotent, so a properly designed service directory
should work with s6-rc with no additional effort.
</p>

<h4> Oneshot transitions </h4>

<p>
 Transitions for oneshot services amount to running the <em>up</em>
or <em>down</em> script for the service; those scripts are stored
in the compiled service database that is linked from the live state.
The transition is considered successful if the script exits zero,
and unsuccessful otherwise.
</p>

<p>
 s6-rc performs some black magic so that <em>up</em> and <em>down</em>
scripts are always run in a reproducible way, no matter when or how
<tt>s6-rc change</tt> is invoked. That black magic involves a special
longrun service, <tt>s6rc-oneshot-runner</tt>, that every oneshot
service automatically depends on, and that is actually used to fork
the <em>up</em> or <em>down</em> scripts as scions of the s6 supervision
tree, instead of children of the s6-rc process.
</p>

<p>
 Transitions should be ideally transactional, or at the very least
idempotent. If a
transition fails, it should leave the machine in the same state as
before the transition was attempted; at the very least, it should not
prevent a subsequent run of the same transition from completing
successfully. If an <tt>s6-rc change</tt> invocation fails because
some transition experienced a temporary failure, it should be possible
to run the exact same <tt>s6-rc change</tt> invocation later, and be
met with success.
</p>

<p>
 This is important: it means that oneshot scripts should be treated
as atoms, and that some care should be taken when writing them.
</p>

<h4> Dry runs </h4>

<p>
 For any manual change, is it recommended to perform a dry run before
the state change itself: add the <tt>-n <em>dryrunthrottle</em></tt>
option to the s6-rc command line. s6-rc will then simulate all the
transitions, but not actually perform them or change the real live
state.
 The command lines that s6-rc would have run will be printed to stdout
instead, and
each simulated transition will take <em>dryrunthrottle</em>
milliseconds to complete successfully.
</p>

<h2> Signals </h2>

<p>
 <tt>s6-rc change</tt> reacts to the following signals:
</p>

<ul>
 <li> SIGTERM: s6-rc immediately aborts all its longrun transitions with
a failure, and the impacted longruns will most likely be in a <em>down</em>
state. Oneshot transitions are untouched, because killing the
oneshot subprocess would make it impossible to determine what state the
oneshot service is in. </li>
 <li> SIGINT: same as SIGTERM. </li>
</ul>

<h2> Usage examples </h2>

<pre> s6-rc change <em>myservicebundle</em> </pre>
<p>
 Brings up all the services represented by <em>myservicebundle</em>,
bringing up all its dependencies first (recursively).
</p>

<pre> s6-rc -bad change </pre>
<p>
 Waits for any pending program of the s6-rc family to stop using
the live database and current compiled service database, then
brings down all the currently running services in an orderly manner.
This is typically run at shutdown time. (And it's not necessarily
a bad change!)
</p>

<pre> s6-rc -l /zork -ua listall <em>myservicebundle</em> </pre>
<p>
 Prints the names of all atomic services represented by
<em>myservicebundle</em> plus the current live services, as well as
everything they depend on, recursively. Assumes the live state is
stored in the <tt>/zork</tt> directory instead of <tt>/run/s6-rc</tt>.
</p>

<pre> s6-rc -d listall <em>myservicebundle</em> </pre>
<p>
 Prints the names of all atomic services represented by
<em>myservicebundle</em>, as well as everything that depends on them.
</p>

<pre> s6-rc -pun0 change <em>myservicebundle</em> </pre>
<p>
 Prints what s6-rc would do to bring the state to <em>exactly</em>
the contents of <em>myservicebundle</em> as well as its recursive
dependencies, and pruning all the rest. Does not wait any extra time
between simulated transitions.
</p>

</body>
</html>