about summary refs log tree commit diff
path: root/doc/s6-rc-update.html
blob: 5b52a6b6eb133921f3eb087fddb3d5c062a85177 (plain) (blame)
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
<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-update program</title>
    <meta name="Description" content="s6-rc: the s6-rc-update program" />
    <meta name="Keywords" content="s6-rc command rc update s6-rc-update 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-update program </h1>

<p>
 s6-rc-update is an <em>online service database switcher</em>:
it will replace your compiled service database with another
one, and adjust the live state accordingly. This allows you to
change your set of services without having to reboot.
</p>

<p>
 Live upgrading a service database is not easy, and no
fully automated system can get it right in all cases.
s6-rc-update will do its best on its own, but it lets the user
give it instructions to handle
difficult cases; and rather than implement doubtful
heuristics, it will fail with an error message in
situations it cannot solve.
</p>

<h2> Interface </h2>

<pre>
     s6-rc-update [ -n ] [ -v <em>verbosity</em> ] [ -t <em>timeout</em> ] [ -l <em>live</em> ] [ -f <em>convfile</em> ] [ -b ] <em>newdb</em>
</pre>

<ul>
 <li> s6-rc-update analyzes the current live state, the current compiled service
database, and the compiled service database contained at <em>newdb</em>
(which must be an absolute path). </li>
 <li> Additionally, it can process an optional <em>conversion file</em> containing
instructions. </li>
 <li> It computes the necessary service transitions to safely update the live
database. </li>
 <li> It shuts down the necessary services. </li>
 <li> It updates the live directory so that <em>newdb</em> becomes the
live compiled service database. </li>
 <li> It starts up the necessary services. </li>
</ul>

<h2> Exit codes </h2>

<ul>
 <li> 0: success </li>
 <li> 1: failure to perform some state transitions, but the database was switched to <em>newdb</em> </li>
 <li> 2: timed out, but the database was switched to <em>newdb</em> </li>
 <li> 3: unknown service name in the conversion file </li>
 <li> 4: invalid service database </li>
 <li> 5: wrong service type in the conversion file </li>
 <li> 6: duplicate service in the conversion file </li>
 <li> 9: failure to perform some state transitions, and the database was not switched </li>
 <li> 10: timed out, and the database was not switched </li>
 <li> 100: wrong usage </li>
 <li> 111: system call failed </li>
 <li> 126: cannot exec into s6-rc for the final "up" transition (error other than ENOENT) </li>
 <li> 127: cannot exec into s6-rc for the final "up" transition (executable not found) </li>
</ul>

<h2> Options </h2>

<ul>
 <li> <tt>-n</tt>&nbsp;: dry run. s6-rc-update will compute the service
transitions, and print the <a href="s6-rc.html">s6-rc</a> command lines
it would execute to perform those transitions. It will not actually
run them or modify the live database. </li>
 <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 adds a bit more information about
what s6-rc-update is doing. 3 or more is heavy debug output. </li>
 <li> <tt>-t&nbsp;<em>timeout</em></tt>&nbsp;: if s6-rc-update cannot
perform its job within <em>timeout</em> milliseconds, it will exit.
The default is 0, meaning infinite (no timeout). Be aware that timing
out and exiting may leave the live database in an inconsistent state,
so use of this option is not recommended. </li>
 <li> <tt>-l&nbsp;<em>live</em></tt>&nbsp;: look for the
live state in <em>live</em>. It must be an absolute path.
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>-f&nbsp;<em>convfile</em></tt>&nbsp;: use the conversion
file located at <em>convfile</em>. Default is <tt>/dev/null</tt>,
meaning no special instructions. </li>
 <li> <tt>-b</tt>&nbsp;: blocking lock. If the database is currently
being used by another program, s6-rc-update will wait until that
other program has released its lock on the database, then proceed.
By default, s6-rc-update fails with an error message if the database
is currently in use. </li>
</ul>

<h2> Transition details </h2>

<p>
 s6-rc-update's job is to ensure consistency of the live state across
a change of compiled service databases. To do so, it must make sure
that the services that are up at the time of its invocation are still
up after its invocation; but service definitions in the new compiled
may be different from those in the old one - in particular, dependencies
may change, or a service can change types: a oneshot can become
a longrun and vice-versa, and an atomic service can even become a
bundle.
</p>

<h3> Service identity </h3>

<p>
 s6-rc-update examines atomic services, as defined in the old compiled,
that are up at invocation time, and computes what is necessary for the
"same" services, as defined in the new compiled, to be up. Barring
instructions from the conversion file, the service is "the same" if it has the
same name in the new compiled, no matter its type.
</p>

<p>
 So, if there is an up oneshot named <tt>sshd</tt> in the old compiled,
and there is a longrun named <tt>sshd</tt> in the new compiled, then
s6-rc-update will decide that the new <tt>sshd</tt> longrun will replace
the old <tt>sshd</tt> oneshot. If the new compiled defines a <tt>sshd</tt>
bundle instead, then s6-rc-update will decide that the old <tt>sshd</tt>
oneshot will be replaced with the contents of the <tt>sshd</tt> bundle.
</p>

<h3> Restarts </h3>

<p>
 s6-rc-update tries to avoid needlessly restarting services. For instance,
running it with a new compiled that is an exact copy of
the old compiled should not cause any restarts. s6-rc-update will flag a
service to be restarted in the following cases:
</p>

<ul>
 <li> The service has disappeared in the new compiled. In this case, the
old service will simply be stopped. </li>
 <li> The service has changed types: a oneshot becomes a longrun, a longrun
becomes a oneshot, or an atomic service becomes a bundle. In this case, the
old service will be stopped, then the new service will be started. </li>
 <li> The service has a dependency to a service that must restart, or to an
old service that must stop, or to a new service that did not previously
exist or that was previously down. </li>
 <li> There is an instruction to restart the service in the conversion file. </li>
</ul>

<h3> Steps </h3>

<p>
 After it has decided what services it should restart, s6-rc-update will:
</p>

<ul>
 <li> Invoke <a href="s6-rc.html">s6-rc</a> to stop old services. </li>
 <li> Update the live directory with the data from the new compiled.
This is the critical part; s6-rc-update should not be interrupted at this point.
It does its best to avoid risking leaving behind an inconsistent state,
but a 100% atomicity guarantee is impossible to achieve. </li>
 <li> Adjust pipe names for the existing pipelines, if needed. </li>
 <li> Exec into <a href="s6-rc.html">s6-rc</a> to start new services. </li>
</ul>

<h2> The conversion file </h2>

<p>
 The conversion file is used to give s6-rc-update instructions when the
change of databases is not entirely straightforward. Currently, it
supports the following features:
</p>

<ul>
 <li> changing the name of a service </li>
 <li> forcing a restart on a service </li>
</ul>

<h3> Format </h3>

<p>
 The conversion file is a sequence of lines; each line is parsed
independently, there's no carrying of information from one line to
the next.
</p>

<p>
 A line is lexed into words by the
<a href="//skarnet.org/software/execline/execlineb.html">execlineb</a>
lexer, which means that words are normally separated by whitespace, but
can be quoted, that <tt>#</tt> comments are recognized, etc.
</p>

<p>
 The first word in a line must be the name of an "old" atomic service, i.e.
an atomic service contained in the current live database. The remaining
words in the line are instructions telling s6-rc-update how to convert
that service.
</p>

<h4> Renaming </h4>

<p>
 If the second word in the line is <tt>-></tt>, then the third word in the
line must be the new name of the service in the new database: s6-rc-update
will then rename it. It is possible
to rename an atomic service to another atomic service or a bundle, but no
matter whether a service is renamed or not, changing its type will force a
restart.
</p>

<h4> Restarting </h4>

<p>
 If the word following either the old name, or a renaming instruction, is the
word <tt>restart</tt>, then the service will forced to restart.
</p>

<h3> Examples </h3>

<p>
 Consider the following conversion file:
</p>

<pre># Simple conversion file
mount-var -> mount-rwfs
httpd restart
sqld -> mysqld restart
</pre>

<ul>
 <li> It will rename <tt>mount-var</tt> to <tt>mount-rwfs</tt>, not restarting it
if <tt>mount-var</tt> in the old database and <tt>mount-rwfs</tt> in the new
database have the same type and do not depend on services that would force a
restart. </li>
 <li> It will restart <tt>httpd</tt> </li>
 <li> It will rename <tt>sqld</tt> to <tt>mysqld</tt> and make it restart.
</ul>

<h2> Safely managing and updating compiled databases </h2>

<p>
 The sequence of operations needed to update a database from source to live
can be a little tricky. It involves:
</p>

<ul>
 <li> Compiling the new database without overwriting the live one </li>
 <li> Calling s6-rc-update to safely replace the live database </li>
 <li> Making sure the new database will be correctly used at boot time </li>
</ul>

<p>
 <a href="https://skarnet.org/software/s6-rc/faq.html#compiledmanagement">This
FAQ entry</a> gives a step-by-step explanation on how to proceed.
</p>

<h2> Notes </h2>

<ul>
 <li> The <em>live</em> argument to the <tt>-l</tt> option, if present, should
be the same argument that was given to the
<a href="s6-rc-init.html">s6-rc-init</a> invocation when the system was
booted. In other words: it should be the name of the symbolic link pointing
to the real directory containing the live information, not the name of the
real directory. </li>
 <li> If a longrun service is renamed from <em>oldname</em> to <em>newname</em>,
but not restarted, the
<a href="//skarnet.org/software/s6/s6-supervise.html">s6-supervise</a>
process in charge of it will still show up in the process list as
<tt>s6-supervise <em>oldname</em></tt>. This is purely cosmetic and
will have no impact on the service; nevertheless, if you wish to avoid that,
simply force a restart on every longrun you rename. </li>
 <li> After a s6-rc-update invocation, the old compiled service database
is left unchanged where it was, and the new compiled
service database is used in-place. If the machine is rebooted, the
<a href="s6-rc-init.html">s6-rc-init</a> invocation will still boot on the
old compiled unless more work is performed. It is recommended to keep a
<tt>current</tt> symbolic link to the current compiled, to always
<a href="s6-rc-init.html">s6-rc-init</a> on <tt>current</tt>, and to
make <tt>current</tt> a link to the new compiled right after a s6-rc-update
invocation. </li>
 <li> s6-rc-update is the only way to "free" the old compiled database
for displacement or deletion. A live compiled database must not be
tampered with. After a s6-rc-update invocation, the old database isn't
live anymore and can be moved or deleted; instead, <em>newdb</em> is
live. </li>
</ul>

</body>
</html>