summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLaurent Bercot <ska-skaware@skarnet.org>2015-07-07 14:39:16 +0000
committerLaurent Bercot <ska-skaware@skarnet.org>2015-07-07 14:39:16 +0000
commita491c627e09aa1149196dd40cb377d181db0580a (patch)
tree9bbf2ce30a73385e46714c23c7973bda97184da3
parent96fbd74d6d70b562f45e327eeb0f625b54899bcc (diff)
downloads6-rc-a491c627e09aa1149196dd40cb377d181db0580a.tar.xz
- Minor fixes to s6-rc
- More doc
-rw-r--r--doc/s6-rc-db.html151
-rw-r--r--doc/s6-rc-init.html168
-rw-r--r--doc/s6-rc.html304
-rw-r--r--src/s6-rc/s6-rc.c19
4 files changed, 417 insertions, 225 deletions
diff --git a/doc/s6-rc-db.html b/doc/s6-rc-db.html
index 9a1cf3b..280f98a 100644
--- a/doc/s6-rc-db.html
+++ b/doc/s6-rc-db.html
@@ -94,41 +94,158 @@ it finds a problem, such as a mismatch in the direct and reverse
dependency tables, or a dependency cycle.
</p>
+<h3> s6-rc-db list </h3>
-<h2> Usage examples </h2>
+<p>
+ Lists all services of a given type. This subcommand takes a second subcommand:
+</p>
+
+<h4> s6-rc-db list all </h4>
+
+<p>
+ Lists everything - atomic services and bundles - contained in the database.
+</p>
+
+<h4> s6-rc-db list services </h4>
+
+<p>
+ Lists all atomic services.
+</p>
+
+<h4> s6-rc-db list oneshots </h4>
+
+<p>
+ Lists oneshots.
+</p>
+
+<h4> s6-rc-db list longruns </h4>
+
+<p>
+ Lists longruns.
+</p>
+
+<h4> s6-rc-db list bundles </h4>
+
+<p>
+ Lists all bundles.
+</p>
+
+<h3> s6-rc-db type <em>servicename</em> </h3>
+
+<p>
+ Prints the type of <em>servicename</em>: <tt>oneshot</tt>, <tt>longrun</tt>
+or <tt>bundle</tt>. Exits 1 if
+<em>servicename</em> is not a valid identifier in the database.
+</p>
+
+<h3> s6-rc-db timeout <em>atomicname</em> </h3>
+
+<p>
+ Prints the timeout value, in milliseconds, after which bringing
+<em>atomicname</em> up or down is considered a failure if the
+called script still has not succeeded. Exits 1 if <em>atomicname</em>
+isn't a valid atomic service. By default, or if the <tt>-u</tt>
+option has been given to s6-rc-db, the timeout for <em>up</em> is
+printed; the timeout for <em>down</em> is printed instead if the
+<tt>-d</tt> option has been given.
+</p>
+
+<h3> s6-rc-db contents <em>bundlename</em> </h3>
+
+<p>
+ Lists the atomic services represented by bundle <em>bundlename</em>.
+Exits 1 if <em>bundlename</em> is not a valid bundle.
+</p>
+
+<h3> s6-rc-db dependencies <em>servicename</em> </h3>
+
+<p>
+ Prints the list of direct dependencies for <em>servicename</em>.
+Exits 1 if <em>servicename</em> isn't a valid identifier. If
+<em>servicename</em> is a bundle, its set of direct dependencies
+is the union of the direct dependencies of all the atomic services
+contained in the bundle.
+</p>
+
+<p>
+ If the <tt>-d</tt> option has been given to s6-rc-db, the
+reverse dependencies are given instead: services that directly
+depend on <em>servicename</em>, or on one of its components if it
+is a bundle.
+</p>
+
+<h3> s6-rc-db servicedir <em>longrunname</em> </h3>
-<pre> s6-rc <em>myservicebundle</em> </pre>
<p>
- Brings up all the services represented by <em>myservicebundle</em>,
-dependencies first.
+ Prints the service directory for longrun service <em>longrunname</em>;
+this value is <em>relative to the scandir</em>. Exits 1 if
+<em>longrunname</em> is not a valid longrun.
</p>
-<pre> s6-rc -Sad </pre>
+<h3> s6-rc-db script <em>oneshotname</em> </h3>
+
+<p>
+ Prints the <em>up</em> script for <em>oneshotname</em>, which is
+an <em>argv</em>, i.e. a Unix command line. Each component of this
+command line is
+<strong>terminated by a null character</strong>, so to print it in
+a human-readable format, pipe the output into something like
+<tt>xargs -0 echo</tt>. The command exits 1 if <em>oneshotname</em>
+is not a valid oneshot.
+</p>
+
+<p>
+ If the <tt>-d</tt> option has been given to s6-rc-db, the
+<em>down</em> script is printed instead.
+</p>
+
+<h3> s6-rc-db flags <em>atomicname</em> </h3>
+
<p>
- Brings down all the services in an orderly manner. This is typically
-run at shutdown time.
+ Prints a hexadecimal number that is the list of all binary flags
+for atomic service <em>atomicname</em>. Exits 1 if <em>atomicname</em>
+is not a valid atomic service.
</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.
+ Those binary flags are currently unused, but this may change in a
+future version of s6-rc.
</p>
-<pre> s6-rc -Ad <em>myservicebundle</em> </pre>
+<h3> s6-rc-db atomics <em>servicename...</em> </h3>
+
<p>
- Prints the names of all atomic services represented by
-<em>myservicebundle</em>, as well as everything that depends on them.
+ Prints the fully resolved list of services represented by the
+<em>servicename...</em> arguments, i.e. the union of all
+atomic services contained in <em>servicename...</em>. Each
+argument in <em>servicename...</em> can be an atomic service or
+a bundle. If an argument isn't a valid identifier, the command
+exits 1.
</p>
-<pre> s6-rc -pun0 <em>myservicebundle</em> </pre>
+<h3> s6-rc-db all-dependencies <em>servicename...</em> </h3>
+
<p>
- Prints what s6-rc would do to bring the state to just
-<em>myservicebundle</em> and its dependencies.
+ Prints the list of all atomic services needed to bring up
+all of the <em>servicename...</em> arguments, with all their
+dependencies, recursively. In other words: for
+<em>servicename...</em> to be up, every single service listed
+in the output will need to be up. The output includes the
+atomic services represented by the
+<em>servicename...</em> arguments themselves. If one of those
+arguments isn't a valid identifier, the command exits 1.
</p>
+<p>
+ The list is not topologically sorted.
+</p>
-<h2> Internals </h2>
+<p>
+ If the <tt>-d</tt> option has been given to s6-rc-db, the
+recursive list of reverse dependencies is printed: for
+<em>servicename...</em> to be down, every single service listed
+in the output will need to be down.
+</p>
</body>
</html>
diff --git a/doc/s6-rc-init.html b/doc/s6-rc-init.html
index 143a0f4..f2bd8e1 100644
--- a/doc/s6-rc-init.html
+++ b/doc/s6-rc-init.html
@@ -20,149 +20,75 @@
<p>
s6-rc-init is an initialization tool for the s6-rc
-system. It must be run at boot time, prior to any
+system. It must be run as root, 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> ]
+ s6-rc-init [ -c <em>compiled</em> ] [ -l <em>live</em> ] [ -t <em>timeout</em> ] <em>scandir</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>
+ <li> <em>compiled</em>, <em>live</em> and <em>scandir</em> must be
+absolute paths. </li>
+ <li> s6-rc-init expects to find a <em>compiled service database</em>
+in <em>compiled</tt>. It expects to be able to create a directory
+at <em>live</em>. It also expects that an instance of
+<a href="http://skarnet.org/software/s6/s6-svscan.html">s6-svscan</a>
+is running on <em>scandir</em>. </li>
+ <li> s6-rc-init initializes the live state in <em>live</em>. It
+declares <em>compiled</em> as the current service database and
+sets the state as "all services down". </li>
+ <li> It then copies verbatim all
+the service directories declared by <em>compiled</em> into a
+subdirectory of <em>live</em>, adds down files to the live copies
+and links them into <em>scandir</em>. It then triggers
+<a href="http://skarnet.org/software/s6/s6-svscan.html">s6-svscan</a>,
+which will pick up the new service directories and start
+http://skarnet.org/software/s6/s6-supervise.html">s6-supervise</a>
+processes on them - but the service themselves will not be started
+right away, because of the down files. </li>
+ <li> s6-rc-init waits for all s6-supervise processes to be
+operational, then exits 0. </li>
<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>
+ <li> <tt>-t&nbsp;<em>timeout</em></tt>&nbsp;: if all
+s6-supervise processes are not up and running after <em>timeout</em>
+milliseconds, s6-rc-init will complain and exit 111. This is a
+safety feature so s6-rc-init doesn't hang indefinitely on a
+nonworking installation; normally this initialization should not take
+more than a few milliseconds. </li>
+ <li> <tt>-c&nbsp;<em>compiled</em></tt>&nbsp;: declare <em>compiled</em>
+as the current compiled service database for the upcoming live state.
+Default is <tt>/etc/s6-rc/compiled</tt>. </li>
+ <li> <tt>-l&nbsp;<em>live</em></tt>&nbsp;: Store the live state into
+the <em>live</em> directory, which should not exist prior to running
+s6-rc-init, but should be under a writable filesystem - likely a RAM
+filesystem. Default is
+<tt>/run/s6-rc</tt>. </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>
+<h2> Typical usage </h2>
-<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.
+ Administrators should invoke <tt>s6-rc-init</tt> once, in their
+early boot scripts, after s6-svscan is functional but before any
+other initialization. (The rest of the initialization can be
+written as a set of s6-rc services, and performed by just one
+invocation of the <a href="s6-rc.html">s6-rc change</a> command.)
</p>
-<pre> s6-rc -Sad </pre>
<p>
- Brings down all the services in an orderly manner. This is typically
-run at shutdown time.
+ For instance, when using an init created by
+<a href="http://skarnet.org/software/s6-linux-init/">s6-linux-init</a>,
+<tt>s6-rc-init</tt> should be the first command in the
+<em>stage2</em> (by default <tt>/etc/rc.init</tt>) script.
</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 34dfc59..ff18362 100644
--- a/doc/s6-rc.html
+++ b/doc/s6-rc.html
@@ -19,46 +19,85 @@
<h1> The s6-rc 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.
+ 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>
+ s6-rc should only be run as root, especially when asking for a state
+change.
</p>
<h2> Interface </h2>
<pre>
- s6-rc [ -v <em>verbosity</em> ] [ <em>servicenames...</em> ]
+ s6-rc help
+ s6-rc [ -l live ] [ -a ] list <em>servicenames...</em>
+ s6-rc [ -l live ] [ -a ] [ -u | -d ] listall <em>servicenames...</em>
+ s6-rc [ -l live ] [ -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 <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>
+ <li> s6-rc expects to find a functional <em>live state</em> in
+<em>live</em> (by default <tt>/run/s6-rc</tt>). 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> 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 <em>up</em> services is added to the selection.
+The s6-rc command operates on the selection.
+</p>
+
<h2> Options </h2>
-<h3> s6-rc control </h3>
+<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>. </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>
+</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
@@ -68,83 +107,197 @@ 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
+<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 s6-rc invocations will notice
+not be updated; in that case, subsequent <tt>s6-rc change</tt>
+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>
+ <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>
-<h3> Up or down </h3>
+<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.
+</p>
+
+<p>
+ This is mostly useful as <tt>s6-rc -a list</tt>, which simply prints
+the list of currently active services.
+</p>
+
+<h3> s6-rc listall <em>servicenames...</em> </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>
+ <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> Service selection </h3>
+<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>-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>
+ <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>
-<h3> Actions </h3>
+<p>
+ To do so:
+</p>
<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>
+ <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 create
+a down file, 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 down 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="http://skarnet.org/software/s6/notifywhenup.html">ready</a>
+(for up transitions). If a longrun service does not support
+readiness notification, the
+<a href="http://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.
+</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 involve 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> Usage examples </h2>
-<pre> s6-rc <em>myservicebundle</em> </pre>
+<pre> s6-rc change <em>myservicebundle</em> </pre>
<p>
Brings up all the services represented by <em>myservicebundle</em>,
-dependencies first.
+bringing up all its dependencies first (recursively).
</p>
-<pre> s6-rc -Sad </pre>
+<pre> s6-rc -ad change </pre>
<p>
- Brings down all the services in an orderly manner. This is typically
-run at shutdown time.
+ Brings down all the currently running services in an orderly manner.
+This is typically run at shutdown time.
</p>
-<pre> s6-rc -Au <em>myservicebundle</em> </pre>
+<pre> s6-rc -l /zork -ua listall <em>myservicebundle</em> </pre>
<p>
Prints the names of all atomic services represented by
-<em>myservicebundle</em>, as well as everything they depend on.
+<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 -Ad <em>myservicebundle</em> </pre>
+<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.
@@ -152,12 +305,11 @@ run at shutdown time.
<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.
+ 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. Do not wait any extra time
+between simulated transitions.
</p>
-
-<h2> Internals </h2>
-
</body>
</html>
diff --git a/src/s6-rc/s6-rc.c b/src/s6-rc/s6-rc.c
index eb01789..377a7d4 100644
--- a/src/s6-rc/s6-rc.c
+++ b/src/s6-rc/s6-rc.c
@@ -67,6 +67,8 @@ static void print_services (void)
buffer_puts(buffer_1, db->string + db->services[i].name) ;
buffer_put(buffer_1, "\n", 1) ;
}
+ if (!buffer_flush(buffer_1))
+ strerr_diefu1sys(111, "write to stdout") ;
}
static pid_t start_oneshot (unsigned int i, int h)
@@ -111,7 +113,7 @@ static pid_t start_longrun (unsigned int i, int h)
char fmt[UINT32_FMT] ;
char vfmt[UINT_FMT] ;
char servicefn[livelen + svdlen + 19] ;
- char const *newargv[11 + !!dryrun[0] * 6] ;
+ char const *newargv[7 + !!dryrun[0] * 6] ;
byte_copy(servicefn, livelen, live) ;
byte_copy(servicefn + livelen, 13, "/servicedirs/") ;
byte_copy(servicefn + livelen + 13, svdlen, db->string + db->services[i].x.longrun.servicedir) ;
@@ -127,16 +129,12 @@ static pid_t start_longrun (unsigned int i, int h)
newargv[m++] = dryrun ;
newargv[m++] = "--" ;
}
- newargv[m++] = S6_EXTBINPREFIX "s6-svlisten1" ;
- newargv[m++] = h ? "-U" : "-d" ;
+ newargv[m++] = S6_EXTBINPREFIX "s6-svc" ;
+ newargv[m++] = h ? "-Uu" : "-Dd" ;
newargv[m++] = "-t" ;
newargv[m++] = fmt ;
newargv[m++] = "--" ;
newargv[m++] = servicefn ;
- newargv[m++] = S6_EXTBINPREFIX "s6-svc" ;
- newargv[m++] = h ? "-u" : "-d" ;
- newargv[m++] = "--" ;
- newargv[m++] = servicefn ;
newargv[m++] = 0 ;
if (!dryrun[0])
@@ -292,7 +290,6 @@ static int doit (int spfd, int h)
for (;;)
{
register int r ;
- buffer_flush(buffer_1) ;
if (!npids) break ;
r = iopause_g(&x, 1, &deadline) ;
if (r < 0) strerr_diefu1sys(111, "iopause") ;
@@ -334,9 +331,9 @@ static inline void print_help (void)
{
static char const *help =
"s6-rc help\n"
-"s6-rc [ -l live ] [ -u | -d ] [ -a ] list [ servicenames... ]\n"
-"s6-rc [ -l live ] [ -u | -d ] [ -a ] listall [ servicenames... ]\n"
-"s6-rc [ -l live ] [ -u | -d ] [ -a ] [ -p ] [ -v verbosity ] [ -t timeout ] [ -n dryrunthrottle ] change [ servicenames... ]\n" ;
+"s6-rc [ -l live ] [ -a ] list [ servicenames... ]\n"
+"s6-rc [ -l live ] [ -a ] [ -u | -d ] listall [ servicenames... ]\n"
+"s6-rc [ -l live ] [ -a ] [ -u | -d ] [ -p ] [ -v verbosity ] [ -t timeout ] [ -n dryrunthrottle ] change [ servicenames... ]\n" ;
if (buffer_putsflush(buffer_1, help) < 0)
strerr_diefu1sys(111, "write to stdout") ;
}