tweak examples/var_service/*
[oweals/busybox.git] / examples / var_service / README_distro_proposal.txt
1         A distro which already uses runit
2
3 I installed Void Linux, in order to see what do they have.
4 Xfce desktop looks fairly okay, network is up.
5 ps tells me they did put X, dbus, NM and udev into runsvdir-supervised tree:
6
7     1 ?        00:00:01 runit
8   623 ?        00:00:00   runsvdir
9   629 ?        00:00:00     runsv
10   650 tty1     00:00:00       agetty
11   630 ?        00:00:00     runsv
12   644 ?        00:00:09       NetworkManager
13  1737 ?        00:00:00         dhclient
14   631 ?        00:00:00     runsv
15   639 tty4     00:00:00       agetty
16   632 ?        00:00:00     runsv
17   640 ?        00:00:00       sshd
18  1804 ?        00:00:00         sshd
19  1809 pts/3    00:00:00           sh
20  1818 pts/3    00:00:00             ps
21   633 ?        00:00:00     runsv
22   637 tty5     00:00:00       agetty
23   634 ?        00:00:00     runsv
24   796 ?        00:00:00       dhclient
25   635 ?        00:00:00     runsv
26   649 ?        00:00:00       uuidd
27   636 ?        00:00:00     runsv
28   647 ?        00:00:00       acpid
29   638 ?        00:00:00     runsv
30   652 ?        00:00:00       console-kit-dae
31   641 ?        00:00:00     runsv
32   651 tty6     00:00:00       agetty
33   642 ?        00:00:00     runsv
34   660 tty2     00:00:00       agetty
35   643 ?        00:00:00     runsv
36   657 ?        00:00:02       dbus-daemon
37   645 ?        00:00:00     runsv
38   658 ?        00:00:00       cgmanager
39   648 ?        00:00:00     runsv
40   656 tty3     00:00:00       agetty
41   653 ?        00:00:00     runsv
42   655 ?        00:00:00       lxdm-binary
43   698 tty7     00:00:14         Xorg
44   729 ?        00:00:00         lxdm-session
45   956 ?        00:00:00           sh
46   982 ?        00:00:00             xfce4-session
47  1006 ?        00:00:04               nm-applet
48   654 ?        00:00:00     runsv
49   659 ?        00:00:00       udevd
50
51 Here is a link to Void Linux's wiki:
52
53     https://wiki.voidlinux.eu/Runit
54
55 Void Linux packages install their services as subdirectories of /etc/rc,
56 such as /etc/sv/sshd, with a script file, "run", and a link
57 "supervise" -> /run/runit/supervise.sshd
58
59 For sshd, "run" contains:
60
61     #!/bin/sh
62     ssh-keygen -A >/dev/null 2>&1 # generate host keys if they don't exist
63     [ -r conf ] && . ./conf
64     exec /usr/bin/sshd -D $OPTS
65
66 That's it from the POV of the packager.
67
68 This is pretty minimalistic, and yet, it is already distro-specific:
69 the link to /run/runit/* is conceptually wrong, it requires packagers
70 to know that /etc/rc should not be mutable and thus they need to use
71 a different location in filesystem for supervise/ directory.
72
73 I think a good thing would be to require just one file: the "run" script.
74 The rest should be handled by distro tooling, not by packager.
75
76 A similar issue is arising with logging. It would be ideal if packagers
77 would not need to know how a particular distro manages logs.
78 Whatever their daemons print to stdout/stderr, should be automagically logged
79 in a way distro prefers.
80
81 * * * * * * * *
82
83         Proposed "standard" on how distros should use runit
84
85 The original idea of services-as-directories belongs to D.J.Bernstein (djb),
86 and his project to implement it is daemontools: https://cr.yp.to/daemontools.html
87
88 There are several reimplementations of daemontools:
89 - runit: by Gerrit Pape, http://smarden.org/runit/
90   (busybox has it included)
91 - s6: by Laurent Bercot, http://skarnet.org/software/s6/
92
93 It is not required that a specific clone should be used. Let evolution work.
94
95
96         Terminology
97
98 daemon: any long running background program. Common examples are sshd, getty,
99 ntpd, dhcp client...
100
101 service: daemon controlled by a service monitor.
102
103 service directory: a directory with an executable file (script) named "run"
104 which (usually) execs some daemon, possibly after some preparatory steps.
105 It should start it not as a child or daemonized process, but by exec'ing it
106 (inheriting the same PID and the place in the process tree).
107
108 service monitor: a tool which watches a set of service directories.
109 In daemontools package, it is called "svscan". In runit, it is called
110 "runsvdir". In s6, it is called "s6-svscan".
111 Service monitor starts a supervisor for each service directory.
112 If it dies, it restarts it. If service directory disappears,
113 service monitor will not be restarted if it dies.
114 runit's service monitor (runsvdir) sends SIGTERM to supervisors
115 whose directories disappeared.
116
117 supervisor: a tool which monitors one service directory.
118 It runs "run" script as its child. It restarts it if it dies.
119 It can be instructed to start/stop/signal its child.
120 In daemontools package, it is called "supervise". In runit, it is called
121 "runsv". In s6, it is called "s6-supervise".
122
123 Conceptually, a daemontools clone can be designed such that it does not *have*
124 the supervisor component: service monitor can directly monitor all its daemons
125 (for example, this may be a good idea for memory-constrained systems).
126 However all three existing projects (daemontools/runit/s6) do have a per-service
127 supervisor process.
128
129 log service: a service which is exclusively tasked with logging
130 the output of another service. It is implemented as log/ subdirectory
131 in a service directory. It has the same structure as "normal"
132 service dirs: it has a "run" script which starts a logging tool.
133
134 If log service exists, stdout of its "main" service is piped
135 to log service. Stops/restarts of either of them do not sever the pipe
136 between them.
137
138 If log service exists, daemontools and s6 run a pair of supervisors
139 (one for the daemon, one for the logger); runit runs only one supervisor
140 per service, which is handling both of them (presumably this is done
141 to use fewer processes and thus, fewer resources).
142
143
144         User API
145
146 "Users" of service monitoring are authors of software which has daemons.
147 They need to package their daemons to be installed as services at package
148 install time. And they need to do this for many distros.
149 The less distros diverge, the easier users' lives are.
150
151 System-wide service dirs reside in a distro-specific location.
152 The recommended location is /var/service. (However, since it is not
153 a mandatory location, avoid depending on it in your run scripts.
154 Void Linux wanted to have it somewhere in /run/*, and they solved this
155 by making /var/service a symlink).
156
157 The install location for service dirs is /etc/rc:
158 when e.g. ntpd daemon is installed, it creates the /etc/rc/ntpd
159 directory with (minimally) one executable file (script) named "run"
160 which starts ntpd daemon. It can have other files there.
161
162 At boot, distro should copy /etc/rc/* to a suitable writable
163 directory (common choice are /var/service, /run/service etc).
164 It should create log/ directories in each subdirectory
165 and create "run" files in them with suitable (for this particular distro)
166 logging tool invocation, unless this directory chose to channel
167 all logging from all daemons through service monitor process
168 and log all of them into one file/database/whatever,
169 in which case log/ directories should not be created.
170
171 It is allowable for a distro to directly use /etc/rc/ as the only
172 location of its service directories. (For example,
173 /var/service may be a symlink to /etc/rc).
174 However, it poses some problems:
175
176 (1) Supervision tools will need to write to subdirectories:
177 the control of running daemons is implemented via some files and fifos
178 in automatically created supervise/ subdirectory in each /etc/rc/DIR.
179
180 (2) Creation of a new service can race with the rescanning of /etc/rc/
181 by service monitor: service monitor may see a directory with only some files
182 present. If it attempts to start the service in this state, all sorts
183 of bad things may happen. This may be worked around by various
184 heuristics in service monitor which give new service a few seconds
185 of "grace time" to be fully populated; but this is not yet
186 implemented in any of three packages.
187 This also may be worked around by creating a .dotdir (a directory
188 whose name starts with a dot), populating it, and then renaming;
189 but packaging tools usually do not have an option to do this
190 automatically - additional install scripting in packages will be needed.
191
192 Daemons' output file descriptors are handled somewhat awkwardly
193 by various daemontools implementations. For example, for runit tools,
194 daemons' stdout goes to wherever runsvdir's stdout was directed;
195 stderr goes to runsvdir, which in turn "rotates" it on its command line
196 (which is visible in ps output).
197
198 Hopefully this get changed/standardized; while it is not, the "run" file
199 should start with a
200
201     exec 2>&1
202
203 command, making stderr equivalent to stdout.
204 An especially primitive service which does not want its output to be logged
205 with standard tools can do
206
207     exec >LOGFILE 2>&1
208
209 or even
210
211     exec >/dev/null 2>&1
212
213 To prevent creation of distro-specific log/ directory, a service directory
214 in /etc/rc can contain an empty "log" file.
215
216
217         Controlling daemons
218
219 The "svc" tool is available for admins and scripts to control services.
220 In particular, often one service needs to control another:
221 e.g. ifplugd can detect that the network cable was just plugged in,
222 and it needs to (re)start DHCP service for this network device.
223
224 The name of this tool is not standard either, which is an obvious problem.
225 I propose to fix this by implementing a tool with fixed name and API by all
226 daemontools clones. Lets use original daemontools name and API. Thus:
227
228 The following form must work:
229
230         svc -udopchaitkx DIR
231
232 Options map to up/down/once/STOP/CONT/HUP/ALRM/INT/TERM/KILL/exit
233 commands to the daemon being controlled.
234
235 The form with one option letter must work. If multiple-option form
236 is supported, there is no guarantee in which order they take effect:
237 svc -it DIR can deliver TERM and INT in any order.
238
239 If more than one DIR can be specified (which is not a requirement),
240 there is no guarantee in which order commands are sent to them.
241
242 If DIR has no slash and is not "." or "..", it is assumed to be
243 relative to the system-wide service directory.
244
245 [Currently, "svc" exists only in daemontools and in busybox.
246 This proposal asks developers of other daemontools implementations
247 to add "svc" command to their projects]
248
249 The "svok DIR" tool exits 0 if service is running, and nonzero if not.
250
251 Other tools with different names and APIs may exist; however
252 for portability scripts should use the above tools.
253
254 Creation of a new service on a running system should be done atomically.
255 To this end, first create and populate a new /etc/rc/DIR.
256
257 Then "activate" it by running ??????? - this copies (or symlinks,
258 depending on the distro) its files to the "live" service directory,
259 wherever it is located on this distro.
260
261 Removal of the service should be done as follows:
262 svc -d DIR [DIR/log], then remove the service directory:
263 this makes service monitor SIGTERM per-directory supervisors
264 (if they exist in the implementation).
265
266
267         Implementation details
268
269 Top-level service monitor program name is not standardized
270 [svscan, runsvdir, s6-svscan ...] - it does not need to be,
271 as far as daemon packagers are concerned.
272
273 It may run one per-directory supervisor, or two supervisors
274 (one for DIR/ and one for DIR/log/); for memory-constrained systems
275 an implementation is possible which itself controls all services, without
276 intermediate supervisors.
277 [runsvdir runs one "runsv DIR" per DIR, runsv handles DIR/log/ if that exists]
278 [svscan runs a pair of "supervise DIR" and "supervise DIR/log"]
279
280 Directories are remembered by device+inode numbers, not names. Renaming a directory
281 does not affect the running service (unless it is renamed to a .dotdir).
282
283 Removal (or .dotdiring) of a directory sends SIGTERM to any running services.
284
285 Standard output of non-logged services goes to standard output of service monitor.
286 Standard output of logger services goes to standard output of service monitor.
287 Standard error of them always goes to standard error of service monitor.
288
289 If you want to log standard error of your logged service along with its stdout, use
290 "exec 2>&1" in the beginning of your "run" script.
291
292 Whether stdout/stderr of service monitor is discarded (>/dev/null)
293 or logged in some way is system-dependent.
294
295
296         Containers
297
298 [What do containers need?]