aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLaurent Bercot <ska-skaware@skarnet.org>2026-01-13 04:16:54 +0000
committerLaurent Bercot <ska-skaware@skarnet.org>2026-01-13 04:16:54 +0000
commit625252d2e88c9a6cb84ecb8731c14d85dd699aa9 (patch)
tree9d40d9a83d5fe3b0699b5974b6515349319c8464
parent12868f261b1e822ae7f132216c2a5a380a163102 (diff)
downloads6-frontend-625252d2e88c9a6cb84ecb8731c14d85dd699aa9.tar.gz
Better live_status and live_stop_everything, more doc
-rw-r--r--doc/s6_live.html30
-rw-r--r--doc/s6_repository.html187
-rw-r--r--doc/s6_system.html147
-rw-r--r--src/s6-frontend/live_status.c45
-rw-r--r--src/s6-frontend/live_stop_everything.c5
5 files changed, 394 insertions, 20 deletions
diff --git a/doc/s6_live.html b/doc/s6_live.html
index b35ba30..cd6aeac 100644
--- a/doc/s6_live.html
+++ b/doc/s6_live.html
@@ -61,7 +61,7 @@ and usage of the <tt>s6 live</tt> command. It is not as detailed as this page.
<h4> Interface </h4>
<pre>
- s6 live status [ <em>servicenames...</em> ]
+ s6 live status [ -e | -E ] [ <em>servicenames...</em> ]
</pre>
<ul>
@@ -75,9 +75,20 @@ then <tt>up</tt> or <tt>down</tt> depending on the current state of the service.
in the generic s6 options, and s6-frontend is built with util-linux support,
then the output is pretty-printed instead of having a slash separate the name
of the service from its state. </li>
- <li> No options are defined. </li>
</ul>
+<h4> Options </h4>
+
+<dl>
+<dt> -e, --without-essentials </dt>
+<dd> Do not list essential services, which can clutter the display with
+irrelevant information and are all supposed to always be up anyway.
+This is the default. </dd>
+
+<dt> -E, --with-essentials </dt>
+<dd> List all services, including essential ones. </dd>
+</dl>
+
<div id="start">
<h3> start </h3>
</div>
@@ -213,7 +224,7 @@ The default is <tt>default</tt>, possibly overridden by the
<h4> Interface </h4>
<pre>
- s6 live stop_everything [ -n ] [ -t <em>timeout</em> ]
+ s6 live stop_everything [ -n ] [ -e | -E ] [ -t <em>timeout</em> ]
</pre>
<ul>
@@ -228,6 +239,19 @@ reboot a machine; for that, check <a href="s6_system.html"><tt>s6 system</tt></a
<dt> -n, --dry-run </dt>
<dd> Only print what would be done; do not actually stop services. </dd>
+<dt> -e, --without-essentials </dt>
+<dd> Do not stop essential services; keep the machine in a state where
+it can more or less run and be interacted with, even if in a completely
+bare state. This is the default. </dd>
+
+<dt> -E, --with-essentials </dt>
+<dd> Also stop essential services. After this command, the machine
+isn't good for much except a reboot. <code>s6 live stop_everything -E</code>
+is the command that should be run right before a shutdown when the
+system is not using s6-linux-init. To that end, the line
+<code>::shutdown:/usr/bin/s6 live stop_everything -E</code> should be
+added to <tt>/etc/inittab</tt>, if that is what the init uses. </dd>
+
<dt> -t <em>timeout</em>, --timeout=<em>timeout</em> </dt>
<dd> If the whole change still hasn't completed after <em>timeout</em>
milliseconds, stop waiting and don't attempt to perform the remaining
diff --git a/doc/s6_repository.html b/doc/s6_repository.html
new file mode 100644
index 0000000..377344f
--- /dev/null
+++ b/doc/s6_repository.html
@@ -0,0 +1,187 @@
+<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-frontend: the s6 repository command</title>
+ <meta name="Description" content="s6-frontend: the s6 repository command" />
+ <meta name="Keywords" content="s6 ecosystem supervision service manager user interface init skarnet.org skarnet software repository repo s6-rc" />
+ <!-- <link rel="stylesheet" type="text/css" href="//skarnet.org/default.css" /> -->
+ </head>
+<body>
+
+<p>
+<a href="s6.html">The s6 command</a><br />
+<a href="index.html">s6-frontend</a><br />
+<a href="//skarnet.org/software/">Software</a><br />
+<a href="//skarnet.org/">skarnet.org</a>
+</p>
+
+<h1> The <tt>s6 repository</tt> command </h1>
+
+<p>
+ <tt>s6 repository</tt> regroups actions that target the repository of source
+definition directories for services managed by the
+<a href="//skarnet.org/software/s6-rc/repodefs.html">repo commands</a> of the
+s6-rc service manager. The repository is hosted in the
+<a href="s6-frontend.conf.html">configured</a> <em>repodir</em>.
+</p>
+
+<p>
+ This set of commands is not intended for day-to-day use, since they involve
+serious actions on the repository which is supposed to be stable. Rather,
+they are likely to be a part of automated procedures written by the distribution
+and triggered by specific events like installation or package updates.
+</p>
+
+<div id="interface">
+<h2> Interface </h2>
+</div>
+
+<pre>
+ s6 repository <em>subcommand</em> [ <em>subcommand_options...</em> ] [ <em>args...</em> ]
+</pre>
+
+<div id="subcommands">
+<h2> Subcommands </h2>
+</div>
+
+<div id="help">
+<h3> help </h3>
+</div>
+
+<p>
+ <tt>s6 repository help</tt> prints a short help message summarizing the options
+and usage of the <tt>s6 repository</tt> command. It is not as detailed as this page.
+</p>
+
+<div id="init">
+<h3> init </h3>
+</div>
+
+<h4> Interface </h4>
+
+<pre>
+ s6 repository init [ -f ] [ -U ] [ -h <em>fdhuser</em> ]
+</pre>
+
+<ul>
+ <li> <tt>s6 repository init</tt> creates the repository at the configured
+location. </li>
+ <li> It links all the stores defined in the configured store list. </li>
+ <li> It syncs the repository with the stores, importing all the services
+and making its reference database. </li>
+ <li> It creates a service set named <tt>current</tt>, which will be the
+working set for all <a href="s6_set.html"><tt>s6 set</tt></a> commands. </li>
+</ul>
+
+<h4> Options </h4>
+
+<dl>
+<dt> -f, --force </dt>
+<dd> If the repository already exists, overwrite it with a new one.
+This is a dangerous option and should only be used as a last resort
+if the repository seems hopelessly broken. </dd>
+
+<dt> -U, --update-stores </dt>
+<dd> Do not recreate the repository from scratch, but update the list
+of stores. This commands needs to be run when the storelist variable
+has changed. </dd>
+
+<dt> -h <em>fdhuser</em>, --fdholder-user=<em>fdhuser</em> </dt>
+<dd> Specify the fdholder user for the reference database. This has
+no impact whatsoever and this option can safely be ignored. </dd>
+</dl>
+
+<div id="list">
+<h3> list </h3>
+</div>
+
+<h4> Interface </h4>
+
+<pre>
+ s6 repository list
+</pre>
+
+<ul>
+ <li> <tt>s6 repository list</tt> lists all the saved sets in the repository,
+printing their names on stdout, one per line. It does not list <tt>current</tt>,
+the current working set, which always exists. </li>
+ <li> No options are defined. </li>
+</ul>
+
+<div id="check">
+<h3> check </h3>
+</div>
+
+<h4> Interface </h4>
+
+<pre>
+ s6 repository check [ -f ] [ -d | -u ] [ -E | -e ]
+</pre>
+
+<ul>
+ <li> <tt>s6 repository check</tt> checks all the services in the set for
+inconsistencies, and prints anything it finds to stdout. </li>
+</ul>
+
+<h4> Options </h4>
+
+<dl>
+<dt> -f, --fix </dt>
+<dd> Also attempt to fix the inconsistencies. </dd>
+
+<dt> -E, --no-force-essential </dt>
+<dd> If fixing a set involves changing a service flagged as essential
+to a sub that is <em>not</em> <tt>always</tt>, or a service <em>not</em>
+flagged as essential to the <tt>always</tt> sub, print an error message
+and exit. This is the default. </dd>
+
+<dt> -e, --force-essential </dt>
+<dd> If fixing a set involves changing a service flagged as essential
+to a sub that is <em>not</em> <tt>always</tt>, or a service <em>not</em>
+flagged as essential to the <tt>always</tt> sub, perform the change
+and continue. This is normally not necessary with a list of stores
+providing consistent services. </dd>
+
+<dt> -d, --down </dt>
+<dd> Fix sets by disabling or masking services. If service <tt>A</tt>
+depends on service <tt>B</tt> and <tt>B</tt> is masked or disabled,
+change <tt>A</tt> to be masked or disabled as well. This is the
+default. </dd>
+
+<dt> -u, --up </dt>
+<dd> Fix sets by enabling or unmasking services. If service <tt>A</tt>
+depends on service <tt>B</tt> and <tt>A</tt> is unmasked or enabled,
+change <tt>B</tt> to be unmasked or enabled as well. </dd>
+</dl>
+
+<div id="sync">
+<h3> sync </h3>
+</div>
+
+<h4> Interface </h4>
+
+<pre>
+ s6 repository sync [ -h <em>fdhuser</em> ]
+</pre>
+
+<ul>
+ <li> <tt>s6 repository sync</tt> synchronizes the repository's view of services
+with the contents of the stores. </li>
+ <li> This command must be run every time the stores change, typically
+when the package manager of the distribution adds or removes a package
+that defines a service. Ideally it should be added to a hook defined by
+the package manager. </li>
+</ul>
+
+<h4> Options </h4>
+
+<dl>
+<dt> -h <em>fdhuser</em>, --fdholder-user=<em>fdhuser</em> </dt>
+<dd> Specify the fdholder user for the reference database. This has
+no impact whatsoever and this option can safely be ignored. </dd>
+</dl>
+
+</body>
+</html>
diff --git a/doc/s6_system.html b/doc/s6_system.html
new file mode 100644
index 0000000..10d52d7
--- /dev/null
+++ b/doc/s6_system.html
@@ -0,0 +1,147 @@
+<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-frontend: the s6 system command</title>
+ <meta name="Description" content="s6-frontend: the s6 system command" />
+ <meta name="Keywords" content="s6 ecosystem supervision service manager user interface init skarnet.org skarnet software boot shutdown system reboot poweroff" />
+ <!-- <link rel="stylesheet" type="text/css" href="//skarnet.org/default.css" /> -->
+ </head>
+<body>
+
+<p>
+<a href="s6.html">The s6 command</a><br />
+<a href="index.html">s6-frontend</a><br />
+<a href="//skarnet.org/software/">Software</a><br />
+<a href="//skarnet.org/">skarnet.org</a>
+</p>
+
+<h1> The <tt>s6 system</tt> command </h1>
+
+<p>
+ <tt>s6 system</tt> regroups actions related to booting or shutting down
+the system.
+</p>
+
+<div id="interface">
+<h2> Interface </h2>
+</div>
+
+<pre>
+ s6 system <em>subcommand</em>
+</pre>
+
+<ul>
+ <li> No subcommand takes any options. </li>
+</ul>
+
+<div id="subcommands">
+<h2> Subcommands </h2>
+</div>
+
+<div id="help">
+<h3> help </h3>
+</div>
+
+<p>
+ <tt>s6 system help</tt> prints a short help message summarizing the options
+and usage of the <tt>s6 system</tt> command. It is not as detailed as this page.
+</p>
+
+<div id="boot">
+<h3> boot </h3>
+</div>
+
+<h4> Interface </h4>
+
+<pre>
+ s6 system boot
+</pre>
+
+<ul>
+ <li> <tt>s6 system boot</tt> initializes the live directory for s6-rc
+then starts all the services defined in the default bundle. In other
+words, it brings the system from a state where nothing is running to
+a state where everything the user wants is running. </li>
+ <li> This is the command that should be called as soon as the init
+program hands off duties.
+ <ul>
+ <li> On a system making use of
+<a href="//skarnet.org/software/s6-linux-init/">s6-linux-init/a>,
+<tt>s6 system boot</tt> should be the sole command defined in the
+<tt>/etc/rc.init</tt> script. </li>
+ <li> On a system using <tt>/etc/inittab</tt>, the first line
+of the inittab should be: <tt>::wait:/usr/bin/s6 system boot</tt> </li>
+ </ul> </li>
+</ul>
+
+<p>
+ The rest of the subcommands are shutdown subcommands, and they
+only work if the machine makes use of
+<a href="//skarnet.org/software/s6-linux-init/">s6-linux-init/a> and
+s6-frontend has been configured to support it. On a machine that
+does not boot via s6-linux-init, a shutdown should be executed via
+the shutdown commands provided by your init system. In order for
+the shutdown to be clean, the <code>s6 live stop_everything -E</code>
+should be run before the init system performs a hard shutdown. For
+instance, if the system uses <tt>/etc/inittab</tt>, then the
+following line should appear in <tt>/etc/inittab</tt>:
+<code>::shutdown:/usr/bin/s6 live stop_everything -E</code>
+</p>
+
+<div id="reboot">
+<h3> reboot </h3>
+</div>
+
+<h4> Interface </h4>
+
+<pre>
+ s6 system reboot
+</pre>
+
+<ul>
+ <li> <tt>s6 system reboot</tt> reboots the machine.
+ <li> This only works if the machine makes use of
+<a href="//skarnet.org/software/s6-linux-init/">s6-linux-init/a> and
+s6-frontend has been configured to support it. </li>
+</ul>
+
+<div id="poweroff">
+<h3> poweroff </h3>
+</div>
+
+<h4> Interface </h4>
+
+<pre>
+ s6 system poweroff
+</pre>
+
+<ul>
+ <li> <tt>s6 system poweroff</tt> halts the system and turns the
+power off. </li>
+ <li> This only works if the machine makes use of
+<a href="//skarnet.org/software/s6-linux-init/">s6-linux-init/a> and
+s6-frontend has been configured to support it. </li>
+</ul>
+
+<div id="halt">
+<h3> halt </h3>
+</div>
+
+<h4> Interface </h4>
+
+<pre>
+ s6 system halt
+</pre>
+
+<ul>
+ <li> <tt>s6 system halt</tt> halts the system without turning
+the power off. </li>
+ <li> This only works if the machine makes use of
+<a href="//skarnet.org/software/s6-linux-init/">s6-linux-init/a> and
+s6-frontend has been configured to support it. </li>
+</ul>
+
+</body>
+</html>
diff --git a/src/s6-frontend/live_status.c b/src/s6-frontend/live_status.c
index a68d99f..dbf9aa6 100644
--- a/src/s6-frontend/live_status.c
+++ b/src/s6-frontend/live_status.c
@@ -17,12 +17,12 @@
#include <s6-frontend/config.h>
#include "s6-frontend-internal.h"
-#define USAGE "s6 live status services..."
+#define USAGE "s6 live status [ -e | -E ] services..."
#define dieusage() strerr_dieusage(100, USAGE)
#define dienomem() strerr_diefu1sys(111, "stralloc_catb")
-static void live_status_all (void) gccattr_noreturn ;
-static void live_status_all (void)
+static void live_status_all (int withe) gccattr_noreturn ;
+static void live_status_all (int withe)
{
char const *argv[23] ;
unsigned int m = 0 ;
@@ -40,7 +40,7 @@ static void live_status_all (void)
argv[m++] = EXECLINE_EXTBINPREFIX "if" ;
argv[m++] = " " EXECLINE_EXTBINPREFIX "pipeline" ;
argv[m++] = " " S6RC_EXTBINPREFIX "s6-rc" ;
- argv[m++] = " -ua" ;
+ argv[m++] = withe ? " -buaE" : " -buae" ;
argv[m++] = " list" ;
argv[m++] = " " ;
argv[m++] = " sed" ;
@@ -48,7 +48,7 @@ static void live_status_all (void)
argv[m++] = "" ;
argv[m++] = EXECLINE_EXTBINPREFIX "pipeline" ;
argv[m++] = " " S6RC_EXTBINPREFIX "s6-rc" ;
- argv[m++] = " -da" ;
+ argv[m++] = withe ? " -bdaE" : " -bdae" ;
argv[m++] = " list" ;
argv[m++] = "" ;
argv[m++] = "sed" ;
@@ -57,13 +57,13 @@ static void live_status_all (void)
xmexec_n(argv, cleanup_modif.s, cleanup_modif.len, cleanup_modif.n) ;
}
-static int get_list_of_up (stralloc *storage)
+static int get_list_of_up (stralloc *storage, int withe)
{
int swasnull = !storage->s ;
size_t sabase = storage->len ;
int fd ;
int wstat ;
- char const *argv[7] = { S6RC_EXTBINPREFIX "s6-rc", "-l", g->dirs.live, "-ba", "--", "list", 0 } ;
+ char const *argv[7] = { S6RC_EXTBINPREFIX "s6-rc", "-l", g->dirs.live, withe ? "-baE" : "-bae", "--", "list", 0 } ;
pid_t pid = child_spawn1_pipe(argv[0], argv, (char const *const *)environ, &fd, 1) ;
if (!pid) { strerr_warnfu2sys("spawn ", argv[0]) ; return 111 ; }
if (!slurpn(fd, storage, 0)) { strerr_warnfu2sys("read output from ", argv[0]) ; return 111 ; }
@@ -88,7 +88,7 @@ static int get_list_of_up (stralloc *storage)
return 111 ;
}
-static int get_atomics (char const *const *services, unsigned int n, stralloc *storage)
+static int get_atomics (char const *const *services, unsigned int n, stralloc *storage, int withe)
{
int swasnull = !storage->s ;
size_t sabase = storage->len ;
@@ -100,7 +100,7 @@ static int get_atomics (char const *const *services, unsigned int n, stralloc *s
argv[m++] = S6RC_EXTBINPREFIX "s6-rc-db" ;
argv[m++] = "-l";
argv[m++] = g->dirs.live ;
- argv[m++] = "-b" ;
+ argv[m++] = withe ? "-bE" : "-be" ;
argv[m++] = "--" ;
argv[m++] = "atomics" ;
for (unsigned int i = 0 ; i < n ; i++) argv[m++] = services[i] ;
@@ -129,8 +129,8 @@ static int get_atomics (char const *const *services, unsigned int n, stralloc *s
return 111 ;
}
-static void live_status_some (char const *const *services) gccattr_noreturn ;
-static void live_status_some (char const *const *services)
+static void live_status_some (char const *const *services, int withe) gccattr_noreturn ;
+static void live_status_some (char const *const *services, int withe)
{
stralloc sa = STRALLOC_ZERO ;
unsigned int m = 0 ;
@@ -138,11 +138,11 @@ static void live_status_some (char const *const *services)
int e ;
char const *argv[59] ;
if (!stralloc_catb(&sa, " ", 1)) dienomem() ;
- e = get_atomics(services, env_len(services), &sa) ;
+ e = get_atomics(services, env_len(services), &sa, withe) ;
if (e) _exit(e) ;
if (!stralloc_catb(&sa, "\0 ", 3)) dienomem() ;
uplistpos = sa.len ;
- e = get_list_of_up(&sa) ;
+ e = get_list_of_up(&sa, withe) ;
if (e) _exit(e) ;
if (!stralloc_0(&sa)) dienomem() ;
@@ -213,10 +213,23 @@ static void live_status_some (char const *const *services)
xmexec_n(argv, cleanup_modif.s, cleanup_modif.len, cleanup_modif.n) ;
}
+enum golb_e
+{
+ GOLB_INCLUDE_ESSENTIALS = 0x01,
+} ;
+
+
void live_status (char const *const *argv)
{
- argv += gol_argv(argv, 0, 0, 0, 0, 0, 0) ;
- if (!argv) live_status_all() ;
- else live_status_some(argv) ;
+ static gol_bool const rgolb[] =
+ {
+ { .so = 'e', .lo = "without-essentials", .clear = GOLB_INCLUDE_ESSENTIALS, .set = 0 },
+ { .so = 'E', .lo = "with-essentials", .clear = 0, .set = GOLB_INCLUDE_ESSENTIALS },
+ } ;
+ uint64_t wgolb = 0 ;
+
+ argv += gol_argv(argv, rgolb, 2, 0, 0, &wgolb, 0) ;
+ if (!argv) live_status_all(wgolb & GOLB_INCLUDE_ESSENTIALS) ;
+ else live_status_some(argv, wgolb & GOLB_INCLUDE_ESSENTIALS) ;
_exit(0) ;
}
diff --git a/src/s6-frontend/live_stop_everything.c b/src/s6-frontend/live_stop_everything.c
index 7d98c70..be9a40a 100644
--- a/src/s6-frontend/live_stop_everything.c
+++ b/src/s6-frontend/live_stop_everything.c
@@ -9,6 +9,7 @@
enum golb_e
{
GOLB_DRYRUN = 0x01,
+ GOLB_INCLUDE_ESSENTIALS = 0x02,
} ;
enum gola_e
@@ -22,6 +23,8 @@ void live_stop_everything (char const *const *argv)
static gol_bool const rgolb[] =
{
{ .so = 'n', .lo = "dry-run", .clear = 0, .set = GOLB_DRYRUN },
+ { .so = 'e', .lo = "without-essentials", .clear = GOLB_INCLUDE_ESSENTIALS, .set = 0 },
+ { .so = 'E', .lo = "with-essentials", .clear = 0, .set = GOLB_INCLUDE_ESSENTIALS },
} ;
static gol_arg const rgola[] =
{
@@ -56,7 +59,7 @@ void live_stop_everything (char const *const *argv)
if (wgolb & GOLB_DRYRUN) newargv[m++] = "-n1" ;
newargv[m++] = "-l" ;
newargv[m++] = g->dirs.live ;
- newargv[m++] = "-bda" ;
+ newargv[m++] = wgolb & GOLB_INCLUDE_ESSENTIALS ? "-bDa" : "-bda" ;
newargv[m++] = "--" ;
newargv[m++] = "change" ;
newargv[m++] = 0 ;