summaryrefslogtreecommitdiff
path: root/doc
diff options
context:
space:
mode:
authorLaurent Bercot <ska-skaware@skarnet.org>2015-07-04 01:40:10 +0000
committerLaurent Bercot <ska-skaware@skarnet.org>2015-07-04 01:40:10 +0000
commit96fbd74d6d70b562f45e327eeb0f625b54899bcc (patch)
tree9ea39925915206e3f40ef2ed4c1298f92dff5858 /doc
parent53e51768c75662a66a8b5656ee557640376d252b (diff)
downloads6-rc-96fbd74d6d70b562f45e327eeb0f625b54899bcc.tar.xz
Start of doc
Diffstat (limited to 'doc')
-rw-r--r--doc/index.html142
-rw-r--r--doc/overview.html220
-rw-r--r--doc/s6-rc-compile.html163
-rw-r--r--doc/s6-rc-db.html134
-rw-r--r--doc/s6-rc-dryrun.html64
-rw-r--r--doc/s6-rc-init.html168
-rw-r--r--doc/s6-rc-upgrade.html174
-rw-r--r--doc/s6-rc.html2
-rw-r--r--doc/upgrade.html28
-rw-r--r--doc/why.html278
10 files changed, 1372 insertions, 1 deletions
diff --git a/doc/index.html b/doc/index.html
new file mode 100644
index 0000000..543b4ca
--- /dev/null
+++ b/doc/index.html
@@ -0,0 +1,142 @@
+<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 - a service manager for s6</title>
+ <meta name="Description" content="s6-rc - a service manager for s6" />
+ <meta name="Keywords" content="s6 rc unix s6-rc init service management rc.d scripts administration root laurent bercot ska skarnet" />
+ <!-- <link rel="stylesheet" type="text/css" href="http://skarnet.org/default.css" /> -->
+ </head>
+<body>
+
+<p>
+<a href="http://skarnet.org/software/">Software</a><br />
+<a href="http://skarnet.org/">skarnet.org</a>
+</p>
+
+<h1> s6-rc </h1>
+
+<h2> What is it&nbsp;? </h2>
+
+<p>
+ s6-rc is a service manager for
+<a href="http://skarnet.org/software/s6/">s6</a>-based
+systems, i.e. a suite of programs that can start and stop
+services, both long-running daemons and one-time
+initialization scripts, in the proper order according to a
+dependency tree. It ensures that long-running daemons are
+supervised by the s6 infrastructure, and that one-time
+scripts are also run in a controlled environment.
+</p>
+
+<hr />
+
+<ul>
+ <li> <a href="why.html">Why</a> such a program&nbsp;? </li>
+ <li> A <a href="overview.html">high-level overview</a> of s6-rc </li>
+</ul>
+
+<hr />
+
+<h2> Installation </h2>
+
+<h3> Requirements </h3>
+
+<ul>
+ <li> A POSIX-compliant system with a standard C development environment </li>
+ <li> GNU make, version 4.0 or later </li>
+ <li> <a href="http://skarnet.org/software/skalibs/">skalibs</a> version
+2.3.5.1 or later </li>
+ <li> <a href="http://skarnet.org/software/execline/">execline</a> version
+2.1.2.2 or later </li>
+ <li> <a href="http://skarnet.org/software/s6/">s6</a> version
+2.1.6.0 or later </li>
+</ul>
+
+<h3> Licensing </h3>
+
+<p>
+ s6-rc is free software. It is available under the
+<a href="http://opensource.org/licenses/ISC">ISC license</a>.
+</p>
+
+<h3> Download </h3>
+
+<ul>
+ <li> The current released version of s6-rc is
+<a href="s6-rc-0.0.1.0.tar.gz">0.0.1.0</a>. </li>
+ <li> Alternatively, you can checkout a copy of the s6-rc git repository:
+<pre> git clone git://git.skarnet.org/s6-rc </pre> </li>
+ <li> There's also a
+<a href="https://github.com/skarnet/s6-rc">GitHub mirror</a>
+of the s6 git repository. </li>
+</ul>
+
+<h3> Compilation </h3>
+
+<ul>
+ <li> See the enclosed INSTALL file for installation details. </li>
+</ul>
+
+<h3> Upgrade notes </h3>
+
+<ul>
+ <li> <a href="upgrade.html">This page</a> lists the differences to be aware of between
+the previous versions of s6-rc and the current one. </li>
+</ul>
+
+<hr />
+
+<h2> Reference </h2>
+
+<h3> Commands </h3>
+
+<p>
+ All these commands exit 111 if they encounter a temporary error, and
+100 if they encounter a permanent error - such as a misuse.
+</p>
+
+<h4> Offline tools: creating and managing a compiled service database </h4>
+
+<ul>
+ <li> <a href="s6-rc-compile.html">The <tt>s6-rc-compile</tt> program</a> </li>
+ <li> <a href="s6-rc-db.html">The <tt>s6-rc-db</tt> program</a> </li>
+</ul>
+
+<h4> Online tools: managing your live services </h4>
+
+<ul>
+ <li> <a href="s6-rc-init.html">The <tt>s6-rc-init</tt> program</a> </li>
+ <li> <a href="s6-rc.html">The <tt>s6-rc</tt> program</a> </li>
+ <li> <a href="s6-rc-dryrun.html">The <tt>s6-rc-dryrun</tt> internal program</a> </li>
+ <li> <a href="s6-rc-upgrade.html">The <tt>s6-rc-upgrade</tt> program</a> </li>
+</ul>
+
+<h2> Related resources </h2>
+
+<h3> Discussion </h3>
+
+<ul>
+ <li> <tt>s6-rc</tt> is discussed on the
+<a href="http://skarnet.org/lists.html#skaware">skaware</a> mailing-list. </li>
+</ul>
+
+<h3> Similar work </h3>
+
+<ul>
+ <li> <a href="http://jjacky.com/anopa/">anopa</a> is another service manager
+for s6, with a similar design (but no compilation phase). </li>
+ <li> <a href="http://homepage.ntlworld.com/jonathan.deboynepollard/Softwares/nosh.html">nosh</a>
+is a complete init system and service manager for Unix. </li>
+</ul>
+
+<h3> Discussion </h3>
+
+<ul>
+ <li> <tt>s6-rc</tt> is discussed on the
+<a href="http://skarnet.org/lists.html#skaware">skaware</a> mailing-list. </li>
+</ul>
+
+</body>
+</html>
diff --git a/doc/overview.html b/doc/overview.html
new file mode 100644
index 0000000..fd544a7
--- /dev/null
+++ b/doc/overview.html
@@ -0,0 +1,220 @@
+<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: an overview</title>
+ <meta name="Description" content="s6-rc: an overview" />
+ <meta name="Keywords" content="s6-rc overview" />
+ <!-- <link rel="stylesheet" type="text/css" href="http://skarnet.org/default.css" /> -->
+ </head>
+<body>
+
+<p>
+<a href="index.html">s6-rc</a><br />
+<a href="http://skarnet.org/software/">Software</a><br />
+<a href="http://skarnet.org/">skarnet.org</a>
+</p>
+
+<h1> An overview of s6-rc </h1>
+
+<h2> A manager for <em>services</em> </h2>
+
+<p>
+ s6-rc is a service manager, or, in other words, a
+<em>machine state manager</em>: given a database of services,
+with dependencies between them, it can safely bring the
+<em>global machine state</em>, or <em>live state</em>, to
+the desired point, making sure dependencies are never
+broken.
+</p>
+
+<h3> The live state </h3>
+
+<p>
+ The <em>live state</em>, by definition, is the tuple of
+all service states on the machine. Changing the live state
+means bringing services up, or bringing services down.
+</p>
+
+<h3> 2.5 kinds of services </h3>
+
+<p>
+ Supervision suites manage <em>long-lived processes</em>, a.k.a
+<em>daemons</em>, and sometimes call them <em>services</em>.
+With s6-rc, those things are different: a long-lived process is
+also called a <em>longrun</em> and is a service, but a service
+does not have to be a longrun. There is a second kind of service,
+which is called a <em>oneshot</em>, and which represents a change
+of system state that is not embodied by the presence of a
+long-lived process. For instance, "mounting a filesystem" is a
+system state change, but in most cases there is no process hanging
+around while the filesystem is mounted.
+</p>
+
+<p>
+ s6-rc handles both oneshots and longruns.
+</p>
+
+<ul>
+ <li> A <em>longrun</em> is the exact equivalent of a <em>service</em>
+in the supervision sense. It is defined by a
+<a href="http://skarnet.org/software/s6/servicedir.html">service
+directory</a>, with a run script and optional other data. The
+service is considered <em>up</em> as long as the long-lived
+process is alive and, for daemons that support it, has
+<a href="http://skarnet.org/software/s6/notifywhenup.html">notified
+its readiness</a>. It is considered <em>down</em> otherwise. </li>
+ <li> A <em>oneshot</em>, on the other hand, is totally unknown
+from supervision suites, because there is no daemon to manage.
+A oneshot is represented by two short-lived scripts, <em>up</em>
+and <em>down</em>, used to bring the service respectively up and
+down. The service is considered up when the <em>up</em>
+program has exited successfully, and until the <em>down</em>
+program has exited successfully. </li>
+</ul>
+
+<p>
+ Services can depend on one another.
+If service <em>A</em> has been declared as
+depending on service <em>B</em>, then s6-rc will make sure to
+never start <em>A</em> until it knows that <em>B</em> is up,
+and will make sure to never stop <em>B</em> until it knows that
+<em>A</em> is down. This works whether <em>A</em> and <em>B</em>
+are both oneshots, both longruns, or a oneshot and a longrun.
+</p>
+
+<p>
+ s6-rc also handles an additional kind of service: a <em>bundle</em>.
+A bundle is just a collection of oneshots or longruns, described
+under a single name. A bundle definition can even contain other
+bundles, but ultimately a bundle will always represent a set of one
+or more oneshots or longruns. A oneshot or longrun is called an
+<em>atomic service</em>.
+Bundle names can be used anywhere with the s6-rc user
+interface, and they will internally be converted to a set of
+atomic services. An atomic service can depend on a bundle: it will
+simply depend on all the atomic services represented by the bundle.
+A bundle, however, cannot have dependencies.
+</p>
+
+<h2> A two-part operation </h2>
+
+<p>
+ Unlike other service managers such as
+<a href="http://jjacky.com/anopa/">anopa</a>, s6-rc separates the
+work of analyzing a set of service definitions, resolving
+dependencies, and so on, from the work of actually applying the
+dependency graph to perform live state changes. The former is
+the <em>compilation</em> phase, and is done offline; the latter is
+the <em>live</em> phase, and is of course done online - it impacts
+the actual state of the machine.
+</p>
+
+<h3> The compilation phase </h3>
+
+<ul>
+ <li> Users are expected to write their service definitions - be it
+oneshots, longruns or bundles - in one ore more
+<em>source directories</em>, in the s6-rc
+<a href="s6-rc-compile.html#source">source format</a>.
+The source format is simple to parse automatically - which is
+one of the main reasons why it has been designed that way - and
+it is also simple to generate automatically: it is easy to write
+converters from a given service definition format to the s6-rc
+source format. </li>
+ <li> Users then run the
+<a href="s6-rc-compile.html">s6-rc-compile</a> program, that takes
+a set of service definitions in one or more source directories
+and makes a <em>compiled service database</em>, abbreviated as
+<em>compiled</em>. This <em>compiled</em> should be stored by the
+administrator on the root filesystem. </li>
+ <li> The <a href="s6-rc-db.html">s6-rc-db</a> tool can be used
+to examine compiled service databases and extract information from
+them in a human-friendly format. </li>
+</ul>
+
+<h3> The live phase </h3>
+
+<p>
+ When the machine boots up:
+</p>
+
+<ul>
+ <li> First, the chosen init should make sure that a
+<a href="http://skarnet.org/software/s6/">s6</a>
+supervision tree is up and running. s6-rc will only work
+if there is an active
+<a href="http://skarnet.org/software/s6/s6-svscan.html">s6-svscan</a>
+process monitoring a
+<a href="http://skarnet.org/software/s6/scandir.html">scan</a>
+directory. On Linux, for instance, it is possible to achieve such a state
+by using an init created by the
+<a href="http://skarnet.org/software/s6-linux-init/s6-linux-init-maker.html">s6-linux-init-maker</a>
+tool: when control reaches stage 2, s6-svscan is guaranteed to run,
+so using s6-rc in the stage 2 script is the way to go. </li>
+ <li> The boot process, let's name it <em>stage2</em>, should then call the
+<a href="s6-rc-init.html">s6-rc-init</a> program. This program
+will set up an area for s6-rc in a writable directory (which can
+be on a RAM filesystem such as tmpfs) to host its live information
+such as the machine state, a working copy of all service directories
+for longruns, and a link to the current compiled state database.
+<a href="s6-rc-init.html">s6-rc-init</a> initializes the machine state
+as "every declared service is down". </li>
+ <li> <em>stage2</em> should then invoke the
+<a href="s6-rc.html">s6-rc</a> program with the names of the services that
+should be brought up given as arguments. Of course, bundles can be used
+for shortcuts. </li>
+ <li> That's it, the services are up and the initialization should be
+over. If the service database has been properly written, a <em>stage2</em>
+script can actually be really short: an invocation of
+<a href="s6-rc-init.html">s6-rc-init</a> and an invocation of
+<a href="s6-rc.html">s6-rc</a>. </li>
+</ul>
+
+<h3> Other state changes and shutdown </h3>
+
+<p>
+ The administrator can make changes to the live state of the machine
+by manually calling <a href="s6-rc.html">s6-rc</a> again with the
+proper arguments. This is more powerful than the old
+<a href="http://www.tldp.org/LDP/sag/html/run-levels-intro.html">runlevels</a>:
+it is possible to change the live state to <em>any</em> set of
+services, not only predefined ones. The only thing that s6-rc will
+not allow is a state that would break service dependencies; it
+will always respect the dependency graph.
+</p>
+
+<p>
+ The s6-rc command is the central for machine state changes, and it is
+also true for shutdown. When shutting a machine down, all the services
+managed by s6-rc should be brought down in the proper order (via the
+<tt>s6-rc -da change</tt> command). Once all those services have been
+brought down successfully, the final shutdown procedure can take place;
+for instance, if s6-svscan is running as process 1 with the
+<a href="http://skarnet.org/software/s6-linux-init/">s6-linux-init</a>
+defaults, <tt>s6-svscanctl -t /run/service</tt> will kill the
+supervision tree and call <tt>/etc/rc.shutdown reboot</tt>, which should
+reboot the machine.
+</p>
+
+<h2> Live updates to the service database </h2>
+
+<p>
+The s6-rc command is a one-stop shop for service management as long as
+the compiled database doesn't change. If an administrator wishes to
+make a new compiled database the current live one, without rebooting
+the machine, a bit more work is needed, and that's the job of the
+<a href="s6-rc-update.html">s6-rc-update</a> command. This command
+has been specifically written with Unix distributions in mind: when
+new packages ship, they come with new service definitions, or upgraded
+ones, and it is necessary to compile a new service database and update
+the live state so it matches; if source definitions for s6-rc are
+provided in the packages, an invocation of
+<a href="s6-rc-compile.html">s6-rc-compile</a> followed by an invocation of
+<a href="s6-rc-update.html">s6-rc-update</a> should be all it takes to
+keep the live state up to date.
+</p>
+
+</body>
+</html>
diff --git a/doc/s6-rc-compile.html b/doc/s6-rc-compile.html
new file mode 100644
index 0000000..33d8bcd
--- /dev/null
+++ b/doc/s6-rc-compile.html
@@ -0,0 +1,163 @@
+<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-compile program</title>
+ <meta name="Description" content="s6-rc: the s6-rc-compile program" />
+ <meta name="Keywords" content="s6-rc offline database compilation command rc init dependency state management services" />
+ <!-- <link rel="stylesheet" type="text/css" href="http://skarnet.org/default.css" /> -->
+ </head>
+<body>
+
+<p>
+<a href="index.html">s6-rc</a><br />
+<a href="http://skarnet.org/software/">Software</a><br />
+<a href="http://skarnet.org/">skarnet.org</a>
+</p>
+
+<h1> The s6-rc-compile program </h1>
+
+<p>
+ s6-rc is a <em>machine state manager</em>: it brings the machine to a
+desired state, by starting or stopping services as needed.
+</p>
+
+<h2> Interface </h2>
+
+<pre>
+ s6-rc [ -v <em>verbosity</em> ] [ <em>servicenames...</em> ]
+</pre>
+
+<ul>
+ <li> s6-rc expects to find a <em>compiled service database</em>
+in <tt>/etc/s6-rc/compiled</tt> and a <em>live state</em> in
+<tt>/s6/s6-rc</tt>. If it cannot find that data, it complains and
+exits.
+ <ul>
+ <li> The <em>compiled service database</em> is built offline
+via the <a href="s6-rc-compile.html">s6-rc-compile</a> tool. </li>
+ <li> The <em>live state</em> should be initialized at boot time
+via the <a href="s6-rc-init.html">s6-rc-init</a> tool. It is then
+maintained by s6-rc itself. </li>
+ </ul> </li>
+ <li> The command line arguments <em>servicenames...</em> define a set
+of selected services the user wants to act on. </li>
+ <li> s6-rc computes the necessary transitions to bring the machine
+to the desired state - by default a state where all the
+services listed on the command line are up. If asked to, it performs
+those transitions. </li>
+ <li> s6-rc processes services as soon as they can be processed. It
+will wait until a service is up to start a dependent service, but it
+will start two independent services in parallel. </li>
+ <li> If every state transition completes successfully, s6-rc exits 0. </li>
+ <li> If a state transition fails, s6-rc will not perform the transitions
+that depend on it. It will wait until all the other independent transitions
+are done, then exit 1. </li>
+</ul>
+
+<h2> Options </h2>
+
+<h3> s6-rc 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">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 s6-rc invocations will notice
+and correctly update it. </li>
+ <li> <tt>-c&nbsp;<em>compiled</em></tt>&nbsp;: look for the
+compiled service database in <em>compiled</em>. Default is
+<tt>/etc/s6-rc/compiled</tt> </li>
+ <li> <tt>-l&nbsp;<em>live</em></tt>&nbsp;: look for the
+live state in <em>live</em>. Default is
+<tt>/s6/s6-rc</tt> </li>
+</ul>
+
+<h3> Up or down </h3>
+
+<ul>
+ <li> <tt>-u</tt>&nbsp;: selected services are interpreted
+as to be brought <em>up</em>. This is the default. </li>
+ <li> <tt>-d</tt>&nbsp;: selected services are interpreted
+as to be brought <em>down</em>. </li>
+</ul>
+
+<h3> Service selection </h3>
+
+<ul>
+ <li> <tt>-p</tt>&nbsp;: prune. The state will be brought to
+<em>exactly</em> <em>servicenames...</em>, 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 <em>servicenames...</em>. </li>
+ <li> <tt>-a</tt>&nbsp;: all. Add the current set of active services to
+the selected set. This is useful to ensure consistency of the machine
+state, for instance, and also at shutdown time: <tt>s6-rc -da</tt>
+will stop all the currently active services. </li>
+</ul>
+
+<h3> Actions </h3>
+
+<ul>
+ <li> <tt>-C</tt>&nbsp;: check. s6-rc will check the consistency of the
+database, and exit with an error message if it finds errors. </li>
+ <li> <tt>-L</tt>&nbsp;: list. s6-rc will resolve the given names, then
+print the list of corresponding atomic services to stdout, without taking their
+dependencies into account. It will print an empty line afterwards. </li>
+ <li> <tt>-A</tt>&nbsp;: list all. s6-rc will print the list of selected
+atomic services to stdout, after computing dependencies. Note that with
+the <tt>-d</tt> option, it computes reverse dependencies instead. </li>
+ <li> <tt>-S</tt>&nbsp;: state change. A state change will be performed
+for the selected services.
+This is the default if no other action option has been given. </li>
+</ul>
+
+<h2> Usage examples </h2>
+
+<pre> s6-rc <em>myservicebundle</em> </pre>
+<p>
+ Brings up all the services represented by <em>myservicebundle</em>,
+dependencies first.
+</p>
+
+<pre> s6-rc -Sad </pre>
+<p>
+ Brings down all the services in an orderly manner. This is typically
+run at shutdown time.
+</p>
+
+<pre> s6-rc -Au <em>myservicebundle</em> </pre>
+<p>
+ Prints the names of all atomic services represented by
+<em>myservicebundle</em>, as well as everything they depend on.
+</p>
+
+<pre> s6-rc -Ad <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 <em>myservicebundle</em> </pre>
+<p>
+ Prints what s6-rc would do to bring the state to just
+<em>myservicebundle</em> and its dependencies.
+</p>
+
+
+<h2> Internals </h2>
+
+</body>
+</html>
diff --git a/doc/s6-rc-db.html b/doc/s6-rc-db.html
new file mode 100644
index 0000000..9a1cf3b
--- /dev/null
+++ b/doc/s6-rc-db.html
@@ -0,0 +1,134 @@
+<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-db program</title>
+ <meta name="Description" content="s6-rc: the s6-rc-db program" />
+ <meta name="Keywords" content="s6-rc offline database dump command rc init dependency state management services" />
+ <!-- <link rel="stylesheet" type="text/css" href="http://skarnet.org/default.css" /> -->
+ </head>
+<body>
+
+<p>
+<a href="index.html">s6-rc</a><br />
+<a href="http://skarnet.org/software/">Software</a><br />
+<a href="http://skarnet.org/">skarnet.org</a>
+</p>
+
+<h1> The s6-rc-db program </h1>
+
+<p>
+ s6-rc-db is a tool to analyze a compiled service database
+and extract information from it, and print it in a user-friendly
+format.
+</p>
+
+<p>
+ It is an <em>offline tool</em>, i.e. you can run it on any
+compiled service database without actually having a live set
+of services managed by s6-rc. However, if you do have a live
+set, you can still run s6-rc-db on the current database (and
+it is the default); it won't interfere with your normal service
+operation.
+</p>
+
+<h2> Interface </h2>
+
+<pre>
+ s6-rc-db help
+ s6-rc-db [ -l <em>live</em> ] [ -c <em>compiled</em> ] check
+ s6-rc-db [ -l <em>live</em> ] [ -c <em>compiled</em> ] list all|services|oneshots|longruns|bundles
+ s6-rc-db [ -l <em>live</em> ] [ -c <em>compiled</em> ] type <em>servicename</em>
+ s6-rc-db [ -l <em>live</em> ] [ -c <em>compiled</em> ] [ -u | -d ] timeout <em>atomicname</em>
+ s6-rc-db [ -l <em>live</em> ] [ -c <em>compiled</em> ] contents <em>bundlename</em>
+ s6-rc-db [ -l <em>live</em> ] [ -c <em>compiled</em> ] [ -u | -d ] dependencies <em>servicename</em>
+ s6-rc-db [ -l <em>live</em> ] [ -c <em>compiled</em> ] servicedir <em>longrunname</em>
+ s6-rc-db [ -l <em>live</em> ] [ -c <em>compiled</em> ] [ -u | -d ] script <em>oneshotname</em>
+ s6-rc-db [ -l <em>live</em> ] [ -c <em>compiled</em> ] flags <em>atomicname</em>
+ s6-rc-db [ -l <em>live</em> ] [ -c <em>compiled</em> ] atomics <em>servicename...</em>
+ s6-rc-db [ -l <em>live</em> ] [ -c <em>compiled</em> ] [ -u | -d ] all-dependencies <em>servicename...</em>
+</pre>
+
+<ul>
+ <li> s6-rc-db expects to find a <em>compiled service database</em>
+in <em>compiled</em>; by default it uses the service database
+used by the live state in <em>live</em>.
+It reads and parses the compiled database it finds. If the
+database is invalid, it exits 4. </li>
+ <li> Depending on the arguments given, it prints the requested
+information to stdout, then exits 0. </li>
+</ul>
+
+<h2> Options </h2>
+
+<ul>
+ <li> <tt>-c&nbsp;<em>compiled</em></tt>&nbsp;: examine a
+compiled service database in <em>compiled</em> instead of
+the current live one. </li>
+ <li> <tt>-l&nbsp;<em>live</em></tt>&nbsp;: assume the live
+state is in <em>live</em>. Default is
+<tt>/run/s6-rc</tt>. This option is ignored if the
+<tt>-c</tt> option has been given. </li>
+ <li> <tt>-u</tt>&nbsp;: for commands that use different data
+depending on whether it's about bringing the service up or down,
+select the "up" data. This option is ignored when it is irrelevant. </li>
+ <li> <tt>-d</tt>&nbsp;: for commands that use different data
+depending on whether it's about bringing the service up or down,
+select the "down" data. This option is ignored when it is irrelevant. </li>
+</ul>
+
+<h2> Subcommands </h2>
+
+<h3> s6-rc-db help </h3>
+
+<p>
+ Prints a help message on stdout.
+</p>
+
+<h3> s6-rc-db check </h3>
+
+<p>
+ Checks the database consistency. Exits 4 with an error message if
+it finds a problem, such as a mismatch in the direct and reverse
+dependency tables, or a dependency cycle.
+</p>
+
+
+<h2> Usage examples </h2>
+
+<pre> s6-rc <em>myservicebundle</em> </pre>
+<p>
+ Brings up all the services represented by <em>myservicebundle</em>,
+dependencies first.
+</p>
+
+<pre> s6-rc -Sad </pre>
+<p>
+ Brings down all the services in an orderly manner. This is typically
+run at shutdown time.
+</p>
+
+<pre> s6-rc -Au <em>myservicebundle</em> </pre>
+<p>
+ Prints the names of all atomic services represented by
+<em>myservicebundle</em>, as well as everything they depend on.
+</p>
+
+<pre> s6-rc -Ad <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 <em>myservicebundle</em> </pre>
+<p>
+ Prints what s6-rc would do to bring the state to just
+<em>myservicebundle</em> and its dependencies.
+</p>
+
+
+<h2> Internals </h2>
+
+</body>
+</html>
diff --git a/doc/s6-rc-dryrun.html b/doc/s6-rc-dryrun.html
new file mode 100644
index 0000000..0a55fa6
--- /dev/null
+++ b/doc/s6-rc-dryrun.html
@@ -0,0 +1,64 @@
+<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-dryrun program</title>
+ <meta name="Description" content="s6-rc: the s6-rc-dryrun program" />
+ <meta name="Keywords" content="s6-rc dry run s6-rc-dryrun command rc init dependency state management services" />
+ <!-- <link rel="stylesheet" type="text/css" href="http://skarnet.org/default.css" /> -->
+ </head>
+<body>
+
+<p>
+<a href="index.html">s6-rc</a><br />
+<a href="http://skarnet.org/software/">Software</a><br />
+<a href="http://skarnet.org/">skarnet.org</a>
+</p>
+
+<h1> The s6-rc-dryrun internal program </h1>
+
+<p>
+ s6-rc-dryrun is a command wrapper and nullifier, roughly
+equivalent to the Unix <tt>echo</tt> command. When run, it
+simply prints its arguments to stdout.
+</p>
+
+<p>
+ s6-rc-dryrun is not meant to be used directly; it is
+internally called by
+<a href="s6-rc.html">s6-rc</a> when given the <tt>-n</tt>
+option. When a dry-running s6-rc instance wants to change the
+system state by spawning a command <tt><em>cmd</em></tt>, it spawns
+<tt>s6-rc-dryrun <em>cmd</em></tt> instead, which allows the user
+to see what would have been done without actually running the
+command.
+</p>
+
+<h2> Interface </h2>
+
+<pre>
+ s6-rc-dryrun [ -v <em>verbosity</em> ] [ -t <em>timeout</em> ] <em>cmd...</em>
+</pre>
+
+<ul>
+ <li> s6-rc-dryrun prints its name, a colon, a space, and
+the space-separated list of its arguments to stdout. </li>
+ <li> It then waits for <em>timeout</em> milliseconds, then
+exits 0. </li>
+</ul>
+
+<h2> Options </h2>
+
+<ul>
+ <li> <tt>-v&nbsp;<em>verbosity</em></tt>&nbsp;: if <em>verbosity</em>
+is 0, s6-rc-dryrun will not print anything to stdout. Default is 1. </li>
+ <li> <tt>-t&nbsp;<em>timeout</em></tt>&nbsp;: sleep for <em>timeout</em>
+milliseconds before exiting. Default is 1000, but when invoked by
+<a href="s6-rc.html">s6-rc</a>, it will be the value of the
+<em>dryruntimeout</em> argument to the <tt>-n</tt> option. This is
+used to simulate a non-immediate startup or shutdown script. </li>
+</ul>
+
+</body>
+</html>
diff --git a/doc/s6-rc-init.html b/doc/s6-rc-init.html
new file mode 100644
index 0000000..143a0f4
--- /dev/null
+++ b/doc/s6-rc-init.html
@@ -0,0 +1,168 @@
+<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-init program</title>
+ <meta name="Description" content="s6-rc: the s6-rc-init program" />
+ <meta name="Keywords" content="s6-rc command s6-rc-init rc init dependency state management services" />
+ <!-- <link rel="stylesheet" type="text/css" href="http://skarnet.org/default.css" /> -->
+ </head>
+<body>
+
+<p>
+<a href="index.html">s6-rc</a><br />
+<a href="http://skarnet.org/software/">Software</a><br />
+<a href="http://skarnet.org/">skarnet.org</a>
+</p>
+
+<h1> The s6-rc-init program </h1>
+
+<p>
+ s6-rc-init is an initialization tool for the s6-rc
+system. It must be run at boot time, prior to any
+invocation of the
+<a href="s6-rc.html">s6-rc</a> binary.
+</p>
+
+<h2> Requirements </h2>
+
+
+<h2> Interface </h2>
+
+<pre>
+ s6-rc-init [ -v <em>verbosity</em> ] [ <em>servicenames...</em> ]
+</pre>
+
+<ul>
+ <li> s6-rc expects to find a <em>compiled service database</em>
+in <tt>/etc/s6-rc/compiled</tt> and a <em>live state</em> in
+<tt>/s6/s6-rc</tt>. If it cannot find that data, it complains and
+exits.
+ <ul>
+ <li> The <em>compiled service database</em> is built offline
+via the <a href="s6-rc-compile.html">s6-rc-compile</a> tool. </li>
+ <li> The <em>live state</em> should be initialized at boot time
+via the <a href="s6-rc-init.html">s6-rc-init</a> tool. It is then
+maintained by s6-rc itself. </li>
+ </ul> </li>
+ <li> The command line arguments <em>servicenames...</em> define a set
+of selected services the user wants to act on. </li>
+ <li> s6-rc computes the necessary transitions to bring the machine
+to the desired state - by default a state where all the
+services listed on the command line are up. If asked to, it performs
+those transitions. </li>
+ <li> s6-rc processes services as soon as they can be processed. It
+will wait until a service is up to start a dependent service, but it
+will start two independent services in parallel. </li>
+ <li> If every state transition completes successfully, s6-rc exits 0. </li>
+ <li> If a state transition fails, s6-rc will not perform the transitions
+that depend on it. It will wait until all the other independent transitions
+are done, then exit 1. </li>
+</ul>
+
+<h2> Options </h2>
+
+<h3> s6-rc 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">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 s6-rc invocations will notice
+and correctly update it. </li>
+ <li> <tt>-c&nbsp;<em>compiled</em></tt>&nbsp;: look for the
+compiled service database in <em>compiled</em>. Default is
+<tt>/etc/s6-rc/compiled</tt> </li>
+ <li> <tt>-l&nbsp;<em>live</em></tt>&nbsp;: look for the
+live state in <em>live</em>. Default is
+<tt>/s6/s6-rc</tt> </li>
+</ul>
+
+<h3> Up or down </h3>
+
+<ul>
+ <li> <tt>-u</tt>&nbsp;: selected services are interpreted
+as to be brought <em>up</em>. This is the default. </li>
+ <li> <tt>-d</tt>&nbsp;: selected services are interpreted
+as to be brought <em>down</em>. </li>
+</ul>
+
+<h3> Service selection </h3>
+
+<ul>
+ <li> <tt>-p</tt>&nbsp;: prune. The state will be brought to
+<em>exactly</em> <em>servicenames...</em>, 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 <em>servicenames...</em>. </li>
+ <li> <tt>-a</tt>&nbsp;: all. Add the current set of active services to
+the selected set. This is useful to ensure consistency of the machine
+state, for instance, and also at shutdown time: <tt>s6-rc -da</tt>
+will stop all the currently active services. </li>
+</ul>
+
+<h3> Actions </h3>
+
+<ul>
+ <li> <tt>-C</tt>&nbsp;: check. s6-rc will check the consistency of the
+database, and exit with an error message if it finds errors. </li>
+ <li> <tt>-L</tt>&nbsp;: list. s6-rc will resolve the given names, then
+print the list of corresponding atomic services to stdout, without taking their
+dependencies into account. It will print an empty line afterwards. </li>
+ <li> <tt>-A</tt>&nbsp;: list all. s6-rc will print the list of selected
+atomic services to stdout, after computing dependencies. Note that with
+the <tt>-d</tt> option, it computes reverse dependencies instead. </li>
+ <li> <tt>-S</tt>&nbsp;: state change. A state change will be performed
+for the selected services.
+This is the default if no other action option has been given. </li>
+</ul>
+
+<h2> Usage examples </h2>
+
+<pre> s6-rc <em>myservicebundle</em> </pre>
+<p>
+ Brings up all the services represented by <em>myservicebundle</em>,
+dependencies first.
+</p>
+
+<pre> s6-rc -Sad </pre>
+<p>
+ Brings down all the services in an orderly manner. This is typically
+run at shutdown time.
+</p>
+
+<pre> s6-rc -Au <em>myservicebundle</em> </pre>
+<p>
+ Prints the names of all atomic services represented by
+<em>myservicebundle</em>, as well as everything they depend on.
+</p>
+
+<pre> s6-rc -Ad <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 <em>myservicebundle</em> </pre>
+<p>
+ Prints what s6-rc would do to bring the state to just
+<em>myservicebundle</em> and its dependencies.
+</p>
+
+
+<h2> Internals </h2>
+
+</body>
+</html>
diff --git a/doc/s6-rc-upgrade.html b/doc/s6-rc-upgrade.html
new file mode 100644
index 0000000..bdaa090
--- /dev/null
+++ b/doc/s6-rc-upgrade.html
@@ -0,0 +1,174 @@
+<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="http://skarnet.org/default.css" /> -->
+ </head>
+<body>
+
+<p>
+<a href="index.html">s6-rc</a><br />
+<a href="http://skarnet.org/software/">Software</a><br />
+<a href="http://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.
+</p>
+
+<p>
+ Live upgrading a service database is no small feat, 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 you
+give it instructions to handle
+difficult cases; and rather than implement doubtful
+heuristics, it will fail with an error message in
+situations it really cannot solve.
+</p>
+
+<h2> Interface </h2>
+
+<pre>
+ s6-rc [ -v <em>verbosity</em> ] [ <em>servicenames...</em> ]
+</pre>
+
+<ul>
+ <li> s6-rc expects to find a <em>compiled service database</em>
+in <tt>/etc/s6-rc/compiled</tt> and a <em>live state</em> in
+<tt>/s6/s6-rc</tt>. If it cannot find that data, it complains and
+exits.
+ <ul>
+ <li> The <em>compiled service database</em> is built offline
+via the <a href="s6-rc-compile.html">s6-rc-compile</a> tool. </li>
+ <li> The <em>live state</em> should be initialized at boot time
+via the <a href="s6-rc-init.html">s6-rc-init</a> tool. It is then
+maintained by s6-rc itself. </li>
+ </ul> </li>
+ <li> The command line arguments <em>servicenames...</em> define a set
+of selected services the user wants to act on. </li>
+ <li> s6-rc computes the necessary transitions to bring the machine
+to the desired state - by default a state where all the
+services listed on the command line are up. If asked to, it performs
+those transitions. </li>
+ <li> s6-rc processes services as soon as they can be processed. It
+will wait until a service is up to start a dependent service, but it
+will start two independent services in parallel. </li>
+ <li> If every state transition completes successfully, s6-rc exits 0. </li>
+ <li> If a state transition fails, s6-rc will not perform the transitions
+that depend on it. It will wait until all the other independent transitions
+are done, then exit 1. </li>
+</ul>
+
+<h2> Options </h2>
+
+<h3> s6-rc 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">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 s6-rc invocations will notice
+and correctly update it. </li>
+ <li> <tt>-c&nbsp;<em>compiled</em></tt>&nbsp;: look for the
+compiled service database in <em>compiled</em>. Default is
+<tt>/etc/s6-rc/compiled</tt> </li>
+ <li> <tt>-l&nbsp;<em>live</em></tt>&nbsp;: look for the
+live state in <em>live</em>. Default is
+<tt>/s6/s6-rc</tt> </li>
+</ul>
+
+<h3> Up or down </h3>
+
+<ul>
+ <li> <tt>-u</tt>&nbsp;: selected services are interpreted
+as to be brought <em>up</em>. This is the default. </li>
+ <li> <tt>-d</tt>&nbsp;: selected services are interpreted
+as to be brought <em>down</em>. </li>
+</ul>
+
+<h3> Service selection </h3>
+
+<ul>
+ <li> <tt>-p</tt>&nbsp;: prune. The state will be brought to
+<em>exactly</em> <em>servicenames...</em>, 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 <em>servicenames...</em>. </li>
+ <li> <tt>-a</tt>&nbsp;: all. Add the current set of active services to
+the selected set. This is useful to ensure consistency of the machine
+state, for instance, and also at shutdown time: <tt>s6-rc -da</tt>
+will stop all the currently active services. </li>
+</ul>
+
+<h3> Actions </h3>
+
+<ul>
+ <li> <tt>-C</tt>&nbsp;: check. s6-rc will check the consistency of the
+database, and exit with an error message if it finds errors. </li>
+ <li> <tt>-L</tt>&nbsp;: list. s6-rc will resolve the given names, then
+print the list of corresponding atomic services to stdout, without taking their
+dependencies into account. It will print an empty line afterwards. </li>
+ <li> <tt>-A</tt>&nbsp;: list all. s6-rc will print the list of selected
+atomic services to stdout, after computing dependencies. Note that with
+the <tt>-d</tt> option, it computes reverse dependencies instead. </li>
+ <li> <tt>-S</tt>&nbsp;: state change. A state change will be performed
+for the selected services.
+This is the default if no other action option has been given. </li>
+</ul>
+
+<h2> Usage examples </h2>
+
+<pre> s6-rc <em>myservicebundle</em> </pre>
+<p>
+ Brings up all the services represented by <em>myservicebundle</em>,
+dependencies first.
+</p>
+
+<pre> s6-rc -Sad </pre>
+<p>
+ Brings down all the services in an orderly manner. This is typically
+run at shutdown time.
+</p>
+
+<pre> s6-rc -Au <em>myservicebundle</em> </pre>
+<p>
+ Prints the names of all atomic services represented by
+<em>myservicebundle</em>, as well as everything they depend on.
+</p>
+
+<pre> s6-rc -Ad <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 <em>myservicebundle</em> </pre>
+<p>
+ Prints what s6-rc would do to bring the state to just
+<em>myservicebundle</em> and its dependencies.
+</p>
+
+
+<h2> Internals </h2>
+
+</body>
+</html>
diff --git a/doc/s6-rc.html b/doc/s6-rc.html
index eeefe7a..34dfc59 100644
--- a/doc/s6-rc.html
+++ b/doc/s6-rc.html
@@ -26,7 +26,7 @@ desired state, by starting or stopping services as needed.
<h2> Interface </h2>
<pre>
- s6-rc [ -v <em>verbosity</em> ] [<em>servicenames...</em>
+ s6-rc [ -v <em>verbosity</em> ] [ <em>servicenames...</em> ]
</pre>
<ul>
diff --git a/doc/upgrade.html b/doc/upgrade.html
new file mode 100644
index 0000000..9536af8
--- /dev/null
+++ b/doc/upgrade.html
@@ -0,0 +1,28 @@
+<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: how to upgrade</title>
+ <meta name="Description" content="s6-rc: how to upgrade" />
+ <meta name="Keywords" content="s6-rc installation upgrade" />
+ <!-- <link rel="stylesheet" type="text/css" href="http://skarnet.org/default.css" /> -->
+ </head>
+<body>
+
+<p>
+<a href="index.html">s6-rc</a><br />
+<a href="http://skarnet.org/software/">Software</a><br />
+<a href="http://skarnet.org/">skarnet.org</a>
+</p>
+
+<h1> What has changed in s6-rc </h1>
+
+<h2> in 0.0.1.0 </h2>
+
+<ul>
+ <li> Initial release. </li>
+</ul>
+
+</body>
+</html>
diff --git a/doc/why.html b/doc/why.html
new file mode 100644
index 0000000..f544e08
--- /dev/null
+++ b/doc/why.html
@@ -0,0 +1,278 @@
+<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: why?</title>
+ <meta name="Description" content="s6-rc: why?" />
+ <meta name="Keywords" content="s6-rc why reason rationale" />
+ <!-- <link rel="stylesheet" type="text/css" href="http://skarnet.org/default.css" /> -->
+ </head>
+<body>
+
+<p>
+<a href="index.html">s6-rc</a><br />
+<a href="http://skarnet.org/software/">Software</a><br />
+<a href="http://skarnet.org/">skarnet.org</a>
+</p>
+
+<h1> Why s6-rc&nbsp;? </h1>
+
+<h2> The limits of supervision suites </h2>
+
+<p>
+ Supervision suites such as
+<a href="http://skarnet.org/software/s6/">s6</a>,
+<a href="http://smarden.org/runit/">runit</a>,
+<a href="http://b0llix.net/perp/">perp</a> or
+<a href="http://cr.yp.to/daemontools.html">daemontools</a>
+define a <em>service</em> as a long-lived process, a.k.a a
+daemon. They provide tools to run the daemon in a reproducible
+way in a controlled environment and keep it alive if it dies;
+they also provide daemon management tools to, among others,
+send signals to the daemon without knowing its PID. They can
+control individual long-lived process perfectly well, and
+<a href="http://skarnet.org/software/s6/">s6</a> also provides
+tools to manage a whole supervision tree.
+</p>
+
+<p>
+ However, a supervision suite is not a service manager.
+</p>
+
+<p>
+ Relying on a supervision suite to handle all the service
+management is doable on simple systems, where there aren't
+many dependencies, and where most of the one-time initialization
+can take place in stage 1, before any daemons are launched.
+On embedded systems, for instance, this is perfectly reasonable.
+</p>
+
+<p>
+ On bigger systems, though, it is more problematic. Here are a few
+issues encountered:
+</p>
+
+<ul>
+ <li> With a pure supervision tree, all daemons are launched in
+parallel; if their dependencies are not met, daemons just die, and
+are restarted by the supervisors, and so on; so eventually everything
+is brought up. This is okay with lightweight daemons that do not take
+up too many resources when starting; but with heavyweight daemons,
+bringing them up at the wrong time can significantly expend CPU and
+increase the total booting time. </li>
+ <li> The <a href="http://smarden.org/runit/">runit</a> model of
+separating one-time initialization (stage 1) and daemon management
+(stage 2) does not always work: some one-time initialization may
+depend on a daemon being up. Example: udevd on Linux. Such daemons
+then need to be run in stage 1, unsupervised - which defeats the
+purpose of having a supervision suite. </li>
+ <li> More generally, supervision suites do not perform
+<em>dependency management</em>. Their job is to maintain daemons
+alive and ease their administration; dependency across those
+daemons is not their concern, and one-time initialization scripts
+are entirely foreign to them. So a situation like <tt>udevd</tt>
+where it is necessary to interleave daemons and one-time scripts
+is very badly handled by them. </li>
+</ul>
+
+<p>
+ To manage complex systems, pure supervision suites are insufficient,
+and real <em>service managers</em>, starting and stopping services
+in the proper order and handling both <em>oneshots</em> (one-time
+initialization scripts) and <em>longruns</em> (daemons), are needed.
+</p>
+
+<h2> Previous alternatives </h2>
+
+<p>
+ Unix distributions usually come with their own init systems and
+service managers; all of those have flaws one way or another. No
+widely spread init system gets things right, which is the main
+reason for the recent "init wars" - there are strong, valid reasons
+to support such or such init system, but <em>also</em> strong, valid
+reason to dislike it.
+</p>
+
+<p>
+ Non-supervision init systems usually fall in one of two categories,
+both with pros and cons.
+</p>
+
+<h3> Traditional, sequential starters </h3>
+
+<p>
+ Those are either the historical Unix init systems, or newer systems
+that still favor simplicity. Among them, for instance:
+</p>
+
+<ul>
+ <li> <a href="http://savannah.nongnu.org/projects/sysvinit">sysvinit</a>,
+the historical GNU/Linux init system, and its companion set of
+<tt>/etc/rc.d</tt> init scripts that some distributions like to
+call <tt>sysv-rc</tt>. Note that sysvinit <em>does</em> have
+supervision capabilities, but nobody ever bothered to use them
+for anything else than <tt>getty</tt>s, and all the machine
+initialization, including longruns, is done by the <tt>sysv-rc</tt>
+scripts, in a less than elegant way. </li>
+ <li> <a href="https://www.freebsd.org/cgi/man.cgi?query=init(8)">BSD
+init</a>, which is very similar to sysvinit - including the
+supervision abilities that are only ever used for <tt>getty</tt>s.
+The <tt>/etc/rc</tt> script takes care of all the initialization. </li>
+ <li> <a href="https://wiki.gentoo.org/wiki/Project:OpenRC">OpenRC</a>,
+an alternative, dependency-based rc system. </li>
+</ul>
+
+<p>
+ All these systems run sequentially: they will start services, either
+oneshots or longruns, one by one, even when the dependency graph says
+that some services could be started in parallel. Also, the daemons
+they start are always unsupervised, even when the underlying init
+system provides supervision features. There usually is no
+<a href="http://skarnet.org/software/s6/notifywhenup.html">readiness
+notification</a> support on daemons either, daemons are fire-and-forget
+(but that's more on the
+scripts themselves than on the frameworks). Another common criticism
+of those systems is that the amount of shell scripting is so huge
+that it has a significant performance impact.
+</p>
+
+<p>
+ Another, less obvious, but important drawback is that service-launching
+scripts run as scions of the shell that invoked the command, and so
+they may exhibit different behaviours when they're run automatically at
+boot time and when they're run manually by an admin, because the
+environment is different. Scripts usually try to run in a clean
+environment, but it's hard to think of everything (open file
+descriptors!) and every script must protect itself with a gigantic
+boilerplate, which adds to the inefficiency problem.
+</p>
+
+<h3> Monolithic init behemoths </h3>
+
+<p>
+ The other category of service managers is made of attempts to cover
+the flaws of traditional service starters, and provide supervision,
+dependency management and sometimes readiness notification, while
+reducing the amount of scripting needed.
+Unfortunately, the results were tightly integrated, monolithic init
+systems straying very far away from Unix core principles, with
+design flaws that make the historical inits' design flaws look like
+a joke.
+</p>
+
+<ul>
+ <li> <a href="http://upstart.ubuntu.com/">Upstart</a> was the first
+one. On the front page, in the "feature highlights" section:
+"Tasks and Services are started and stopped
+by events. Events are generated as tasks and services are started
+and stopped." Do you understand what that means? I don't. </li>
+ <li> <a href="https://en.wikipedia.org/wiki/Launchd">launchd</a>,
+Darwin's init and service manager. The wikipedia page (linked here
+because Apple doesn't see fit to provide a documentation page for
+launchd) is very clear: it replaces init, rc, init.d/rc.d,
+SystemStarter, inetd, crontd, atd and watchdogd. It does all of this
+in process 1. And it uses XML for daemon configuration, so process 1
+has to link in a XML parsing library. </li>
+ <li> <a href="http://www.freedesktop.org/wiki/Software/systemd/">systemd</a>,
+the main protagonist (or antagonist) in the "init wars". It has the same
+problems as launchd, up by an order of magnitude;
+<a href="http://skarnet.org/software/s6/systemd.html">here is why</a>.
+systemd avowedly aims to replace the whole low-level user-space of
+Linux systems, but its design is horrendous. It doesn't even
+<a href="http://ewontfix.com/15/">get readiness notification right</a>. </li>
+</ul>
+
+<p>
+ The problem of integrated init systems is that:
+</p>
+
+<ul>
+ <li> They have been developed by companies and associations, not
+individuals, and despite the licensing, they are for all intents and
+purposes closer to proprietary software than free software; they also
+suffer from many of the technical flaws of enterprise software
+design. </li>
+ <li> As a result, and despite being backed by tremendous manpower,
+they have been very poorly thought out. The manpower goes into the
+coding of features, not into architecture conception; and the
+architects were obviously not Unix experts, which is a shame when
+it's about creating a process 1 for Unix. This is apparent because: </li>
+ <li> They have been designed like <em>application software</em>, not
+<em>system software</em>, which requires a fairly different set of
+skills, and careful attention to details - such as minimal software
+dependencies and shortness of code paths - that are not as important
+in application software. </li>
+</ul>
+
+<p>
+ Pages and pages could be written about the shortcomings of integrated
+init systems; one fact remains - they are not a satisfying solution
+to the problem of service management under Unix.
+</p>
+
+<h2> The best of both worlds </h2>
+
+<p>
+ s6-rc aims to be such a solution: it is small and modular, but offers
+full functionality. Parallel service startup and shutdown with
+correct dependency management (none of the systemd nonsense where
+services are started before their dependencies are met), correct
+readiness notification support, reproducible script execution, and
+<em>short code paths</em>.
+</p>
+
+<ul>
+ <li> s6-rc is a <em>service manager</em>, i.e. the equivalent of
+<tt>sysv-rc</tt> or OpenRC. It is <em>not</em> an init system.
+<strong>You can run s6-rc with any init system of your choosing.</strong>
+Of course, s6-rc requires a s6 supervision tree to be running on
+the system, since it delegates the management of longrun services
+to that supervision tree, but it does not require that s6 be the
+init system itself. s6-rc will work
+<a href="http://skarnet.org/software/s6/s6-svscan-1.html">when s6-svscan
+runs as process 1</a> (on Linux, such a setup can be easily achieved
+via the help of the
+<a href="http://skarnet.org/software/s6-linux-init/">s6-linux-init</a>
+package), and it will also work
+<a href="http://skarnet.org/software/s6/s6-svscan-not-1.html">when
+s6-svscan runs under another init process</a>. </li>
+ <li> The service manager runs <em>on top of</em> a supervision
+suite. It does not try to make it perform boot/shutdown operations or
+dependency management itself; and it does not substitute itself to it.
+s6-rc uses the functionality provided by s6, but it is still possible
+to run s6 without s6-rc for systems that do not need a service manager.
+It would also be theoretically possible to run s6-rc on top of another
+supervision suite, if said supervision suite provided the hooks that
+s6-rc needs. </li>
+ <li> A significantly time-consuming part of a service manager is
+the analysis of a set of services and computation of a dependency graph
+for that set. At the time of writing this document, s6-rc is the only
+service manager that performs that work <em>offline</em>, eliminating
+the dependency analysis overhead from boot time, shutdown time, or
+any other time where the machine state changes. </li>
+ <li> The <em>source</em> format for the
+<a href="s6-rc-compile.html">s6-rc-compile</a> tool is purposefully
+simple, in order to allow external tools to automatically write
+service definitions for s6-rc - for instance for conversions between
+service manager formats. </li>
+ <li> Like every
+<a href="http://skarnet.org/software/">skarnet.org tool</a>, s6-rc
+is made of very little code, that does its job and nothing else.
+The binaries are small, it is very light in memory usage, and the
+code paths are extremely short. </li>
+</ul>
+
+
+<p>
+ The combination of s6 and s6-rc makes a complete, full-featured and
+performant init system and service manager, with probably the lowest
+total memory footprint of any service manager out there, and all the
+reliability and ease of administration that a supervision suite can
+provide. It is a real, viable alternative to integrated init
+behemoths, providing equivalent functionality while being much
+smaller and much, much more maintainable.
+</p>
+
+</body>
+</html>