summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLaurent Bercot <ska-skaware@skarnet.org>2018-01-13 14:33:25 +0000
committerLaurent Bercot <ska-skaware@skarnet.org>2018-01-13 14:33:25 +0000
commitc2c14b525080203561d9e47d8a10442828342251 (patch)
tree11b5145ae7413ef577ad190315bfa147c23057c6
parent1bd507eda34de6945c18daa916fb64ad810fda5a (diff)
downloads6-linux-init-c2c14b525080203561d9e47d8a10442828342251.tar.xz
Autogenerate final shutdown; rename rc.tini to rc.shutdown
-rw-r--r--.gitignore9
-rw-r--r--COPYING2
-rw-r--r--INSTALL8
-rw-r--r--NEWS10
-rw-r--r--doc/index.html10
-rw-r--r--doc/quickstart.html69
-rw-r--r--doc/s6-linux-init-maker.html99
-rw-r--r--doc/upgrade.html17
-rwxr-xr-xexamples/rc.init12
-rwxr-xr-xexamples/rc.shutdown30
-rwxr-xr-xexamples/rc.tini16
-rw-r--r--package/info2
-rw-r--r--src/init/s6-linux-init-maker.c36
13 files changed, 189 insertions, 131 deletions
diff --git a/.gitignore b/.gitignore
index 5c6415e..6b2e3dd 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,8 @@
*.o
-*.a
*.lo
-*.so
-*.so.*
+/config.mak
+/src/include/s6-linux-init/config.h
+/s6-linux-init-maker
+/s6-halt
+/s6-poweroff
+/s6-reboot
diff --git a/COPYING b/COPYING
index a34920e..ca90f6c 100644
--- a/COPYING
+++ b/COPYING
@@ -1,4 +1,4 @@
-Copyright (c) 2015-2017 Laurent Bercot <ska-skaware@skarnet.org>
+Copyright (c) 2015-2018 Laurent Bercot <ska-skaware@skarnet.org>
Permission to use, copy, modify, and distribute this software for any
purpose with or without fee is hereby granted, provided that the above
diff --git a/INSTALL b/INSTALL
index 5562636..8b11fa8 100644
--- a/INSTALL
+++ b/INSTALL
@@ -6,15 +6,15 @@ Build Instructions
- A Linux-based system with a standard C development environment
- GNU make version 3.81 or later
- - skalibs version 2.6.0.0 or later: http://skarnet.org/software/skalibs/
+ - skalibs version 2.6.3.0 or later: http://skarnet.org/software/skalibs/
The scripts generated by the s6-linux-init-maker program have some
additional dependencies:
- - execline version 2.3.0.2 or later: http://skarnet.org/software/execline/
+ - execline version 2.3.0.4 or later: http://skarnet.org/software/execline/
- s6-portable-utils version 2.2.1.1 or later: http://skarnet.org/software/s6-portable-utils/
- - s6-linux-utils version 2.4.0.0 or later: http://skarnet.org/software/s6-linux-utils/
- - s6 version 2.6.1.0 or later: http://skarnet.org/software/s6/
+ - s6-linux-utils version 2.4.0.2 or later: http://skarnet.org/software/s6-linux-utils/
+ - s6 version 2.7.0.0 or later: http://skarnet.org/software/s6/
This software is Linux-specific. It will run on a Linux kernel,
version 2.6.32 or later. However, it should not be too hard to port to
diff --git a/NEWS b/NEWS
index e84a356..df33cd5 100644
--- a/NEWS
+++ b/NEWS
@@ -1,5 +1,15 @@
Changelog for s6-linux-init.
+In 0.4.0.0
+----------
+
+ - The old /etc/rc.shutdown is now created by s6-linux-init-maker
+and is not the user's responsibility anymore.
+ - /etc/rc.tini is now named /etc/rc.shutdown. In summary:
+now, /etc/rc.shutdown marks the end of stage 2, not stage 3,
+and stage 3 is all automatically generated.
+
+
In 0.3.1.1
----------
diff --git a/doc/index.html b/doc/index.html
index 598b50b..49aed5f 100644
--- a/doc/index.html
+++ b/doc/index.html
@@ -50,15 +50,15 @@ a small FAQ.
<li> A Linux-based system with a standard C development environment </li>
<li> GNU make, version 3.81 or later </li>
<li> <a href="//skarnet.org/software/skalibs/">skalibs</a> version
-2.6.0.0 or later </li>
+2.6.3.0 or later </li>
<li> <a href="//skarnet.org/software/execline/">execline</a> version
-2.3.0.2 or later </li>
+2.3.0.4 or later </li>
<li> <a href="//skarnet.org/software/s6-portable-utils/">s6-portable-utils</a> version
2.2.1.1 or later </li>
<li> <a href="//skarnet.org/software/s6-linux-utils/">s6-linux-utils</a> version
-2.4.0.0 or later </li>
+2.4.0.2 or later </li>
<li> <a href="//skarnet.org/software/s6/">s6</a> version
-2.6.1.0 or later </li>
+2.7.0.0 or later </li>
</ul>
<p>
@@ -87,7 +87,7 @@ against the shared version of the skalibs library, it also becomes a
<ul>
<li> The current released version of s6-linux-init is
-<a href="s6-linux-init-0.3.1.1.tar.gz">0.3.1.1</a>. </li>
+<a href="s6-linux-init-0.4.0.0.tar.gz">0.4.0.0</a>. </li>
<li> Alternatively, you can checkout a copy of the
<a href="//git.skarnet.org/cgi-bin/cgit.cgi/s6-linux-init/">s6-linux-init
git repository</a>:
diff --git a/doc/quickstart.html b/doc/quickstart.html
index 619fbbd..6a0069b 100644
--- a/doc/quickstart.html
+++ b/doc/quickstart.html
@@ -29,17 +29,13 @@
<li> <a href="//skarnet.org/software/s6-linux-utils/">s6-linux-utils</a> </li>
<li> <a href="//skarnet.org/software/s6/">s6</a> </li>
</ul> </li>
- <li> Install <a href="index.html">s6-linux-init</a> itself </li>
- <li> Save your old <tt>/sbin/init</tt> binary </li>
- <li> Save and remove your old <tt>/etc/s6-linux-init</tt> directory, if you have one </li>
- <li> Make sure you have a <tt>/run</tt> directory </li>
+ <li> Install <a href="index.html">s6-linux-init</a> itself. </li>
+ <li> Save your old <tt>/sbin/init</tt> binary. </li>
+ <li> Save and remove your old <tt>/etc/s6-linux-init</tt> directory, if you have one. </li>
+ <li> Make sure you have a <tt>/run</tt> directory. </li>
<li> Write a machine initialization script in <tt>/etc/rc.init</tt> and
- a machine shutdown script in <tt>/etc/rc.shutdown</tt>. Make them executable. </li>
- <li> If, at shutdown time, you need to run a script <em>before</em> the
-supervision tree is torn down (for instance if you're using
-<a href="//skarnet.org/software/s6-rc/">s6-rc</a> and want to
-cleanly stop all your services), write that script in
-<tt>/etc/rc.tini</tt>. </li>
+a machine shutdown script in <tt>/etc/rc.shutdown</tt>. Make sure they are
+executable. See below for more information on how to write these scripts. </li>
<li> Check that your devtmpfs is automounted by your kernel at boot time. If it is not,
add the <tt>-d 1</tt> option to the <tt>s6-linux-init-maker</tt> command line below. </li>
<li> As root, run: <pre>
@@ -53,8 +49,61 @@ add the <tt>-d 1</tt> option to the <tt>s6-linux-init-maker</tt> command line be
<a href="s6-halt.html">s6-halt</a>,
<a href="s6-poweroff.html">s6-poweroff</a> or
<a href="s6-reboot.html">s6-reboot</a> command as appropriate. </li>
+</ol>
+
+<h3> What should go into <tt>/etc/rc.init</tt> and <tt>/etc/rc.shutdown</tt>&nbsp;? </h3>
+
+<h4> <tt>/etc/rc.init</tt> </h4>
+
+<p>
+ This script will be run after s6-linux-init has done is job, i.e.
+<a href="//skarnet.org/software/s6/">s6-svscan</a> is running as process 1, and it
+is now up to <tt>/etc/rc.init</tt> to get the machine to its usable state.
+It normally contains a call to the service manager to bring up all the services;
+for instance, if you're using
+<a href="//skarnet.org/software/s6-rc/">s6-rc</a> as your service manager, and
+your top bundle (containing all the services you want to bring up) is named
+<tt>ok-all</tt>, a proper <tt>/etc/rc.init</tt> could look like this:
+</p>
+
+<pre>#!/bin/sh
+s6-rc-init /run/service &amp;&amp; exec s6-rc -u change ok-all
+</pre>
+
+<p>
+ The script can assume that:
+</p>
+
+<ul>
+ <li> There is a tmpfs partition, only writable by root, mounted on <tt>/run</tt> </li>
+ <li> There is a <a href="//skarnet.org/software/s6/">s6</a> supervision tree
+running on <tt>/run/service</tt> </li>
+ <li> <tt>/dev</tt> is mounted, but <tt>/proc</tt> and <tt>/sys</tt> are not </li>
</ul>
+<h4> <tt>/etc/rc.shutdown</tt> </h4>
+
+<p>
+ This script is spawned by <a href="//skarnet.org/software/s6/">s6-svscan</a>
+when the administrator calls <a href="s6-halt.html">s6-halt</a>,
+<a href="s6-poweroff.html">s6-poweroff</a> or
+<a href="s6-reboot.html">s6-reboot</a>. When this script exits, the final
+shutdown sequence is run, which means that the supervision tree is dismantled,
+all processes are killed, the file systems are umounted and the system
+undergoes a hardware shutdown or reboot. So the goal of this script is to
+bring services down in an orderly fashion and perform all the necessary
+cleanups before all remaining processes are summarily killed.
+</p>
+
+<p>
+ If you're using <a href="//skarnet.org/software/s6-rc/">s6-rc</a> as your
+service manager, a proper <tt>/etc/rc.shutdown</tt> could look like this:
+</p>
+
+<pre>#!/bin/sh
+exec s6-rc -da change
+</pre>
+
<h2> FAQ </h2>
<h4> Why is it so complicated to use s6 as an init process? It's much
diff --git a/doc/s6-linux-init-maker.html b/doc/s6-linux-init-maker.html
index 5ba7326..4c0b51d 100644
--- a/doc/s6-linux-init-maker.html
+++ b/doc/s6-linux-init-maker.html
@@ -53,10 +53,9 @@ machine</em> - else the scripts will crash.
[ -b <em>execline_bindir</em> ] \
[ -u <em>log_uid</em> -g <em>log_gid</em> | -U ] \
[ -G <em>early_getty</em> ] \
- [ -2 <em>stage2</em> ] \
+ [ -2 <em>initscript</em> ] \
[ -r ] \
- [ -Z ] <em>stage2_finish</em> \
- [ -3 <em>stage3</em> ] \
+ [ -Z ] <em>shutdownscript</em> \
[ -p <em>initial_path</em> ] \
[ -m <em>initial_umask</em> ] \
[ -t <em>timestamp_style</em> ] \
@@ -64,6 +63,7 @@ machine</em> - else the scripts will crash.
[ -s <em>env_store</em> ] \
[ -e <em>initial_envvar</em> ] ... \
[ -n ] \
+ [ -q ] <em>finalsleeptime</em>
<em>dir</em>
</pre>
@@ -131,19 +131,19 @@ instead of clogging the system console. </li>
scan directory will also contain a service for an early getty. </li>
<li> s6-svscan starts all the services defined in the scan directory,
and unblocks the child forked by <em>stage 1</em>. </li>
- <li> This child executes into <em>stage2</em>. </li>
+ <li> This child executes into <em>initscript</em>. </li>
</ul>
<p>
- <em>stage2</em> is the responsibility of the administrator - it will
+ <em>initscript</em> is the responsibility of the administrator - it will
not be written automatically!
It should
contain all the necessary initialization sequence to bring up a proper
-system. When <em>stage2</em> is executed, the machine state is as follows:
+system. When <em>initscript</em> is executed, the machine state is as follows:
</p>
<ul>
- <li> <em>stage2</em>'s working directory is <tt>/</tt> and its stdin
+ <li> <em>initscript</em>'s working directory is <tt>/</tt> and its stdin
is <tt>/dev/null</tt>. Its
stdout and stderr both point either to <tt>/dev/console</tt> or to the pipe
to the catch-all logger, depending on the <tt>-r</tt> option. </li>
@@ -159,7 +159,7 @@ into <tt><em>tmpfsdir</em>/service</tt>, then running the command
<tt>s6-svscanctl -a <em>tmpfsdir</em>/service</tt>. Services without a
dedicated logger will send their output to the catch-all logger. </li>
<li> A getty service may already be available. The point of this early
-getty is essentially to make it easier to debug if <em>stage2</em> fails. </li>
+getty is essentially to make it easier to debug if <em>initscript</em> fails. </li>
</ul>
<p>
@@ -167,9 +167,10 @@ getty is essentially to make it easier to debug if <em>stage2</em> fails. </li>
mounted yet, including <tt>/proc</tt> and <tt>/sys</tt>; and no one-time
initialization
has been performed. The point of <em>stage 1</em> is only to make it
-possible to run <em>stage2</em> with a logging infrastructure and a
+possible to run <em>initscript</em> with a logging infrastructure and a
supervision infrastructure already available, and all the
-real machine and service initialization should happen in <em>stage2</em>.
+real machine and service initialization should happen in <em>initscript</em>,
+also known as <em>stage 2</em>.
</p>
<h2> Shutdown sequence </h2>
@@ -189,54 +190,46 @@ s6-linux-init-maker into the
<tt><em>basedir</em>/run-image/service/.s6-svscan</tt> directory (and that
has been copied at boot time to <tt><em>tmpfsdir</em>/service/.s6-svscan</tt>). </li>
- <li> That script first spawns the <em>stage2_finish</em> script, who
+ <li> That script first spawns the <em>shutdownscript</em> script, who
must have been written by the administrator. The purpose of
-<em>stage2_finish</em> is to perform the high-level shutdown sequence
+<em>shutdownscript</em> is to perform the high-level shutdown sequence
while the supervision tree is still alive. Typically, when using a
-service manager, <em>stage2_finish</em> would tell the service manager
+service manager, <em>shutdownscript</em> would tell the service manager
to bring all services down. When using
<a href="//skarnet.org/software/s6-rc/">s6-rc</a>, a typical
<em>stage2_finish</em> script just contains <tt>s6-rc -da change</tt>.
- More generally speaking, <em>stage2_finish</em> should undo what
+ More generally speaking, <em>shutdownscript</em> should undo what
<em>stage2</em> has done at boot time. </li>
<li> The "signal handler" script then tells s6-svscan to exit via an
appropriate <a href="//skarnet.org/software/s6/s6-svscanctl.html">s6-svscanctl</a>
-command: s6-svscan then executes into the <em>stage3</em> script, which, like
-<em>stage2</em> and <em>stage2_finish</em>, is the responsibility of the
-administrator. When <em>stage3</em> runs, the machine is in the following
-state:
+command: s6-svscan then executes into the final shutdown sequence. This
+sequence is made of the following actions:
<ul>
- <li> The supervision tree has been torn down: it is not operational
-anymore. (So, commands such as
-<a href="//skarnet.org/software/s6-rc/s6-rc.html">s6-rc</a>, which
-require a live supervision tree, will not work.)
- <li> <em>stage3</em> runs as process 1. Doing so makes it easier to recover
-after killing all processes by <tt>kill -9 -1</tt> or
-<a href="//skarnet.org/software/s6-portable-utils/s6-nuke.html">s6-nuke</a>. </li>
- <li> Its working directory is <tt>/</tt> and its stdin is <tt>/dev/null</tt> </li>
- <li> Its stdout and stderr are both <tt>/dev/console</tt> </li>
- <li> Depending on the exact configuration and what the administrator has
-written in <em>stage2_finish</em>, there may or may not be
-long-running services that remain alive. The catch-all logger and its
-supervisor will <em>always</em> be alive; this is not a problem because they
-do not hold any file descriptor to a filesystem that would need to be
-unmounted. </li>
+ <li> The supervision tree gets torn down. </li>
+ <li> All data is flushed to disk. </li>
+ <li> All processes get a SIGTERM, a SIGHUP, and a SIGCONT. This should
+allow all processes to die gracefully. Note that most processes should
+already have been killed during the <tt>/etc/rc.shutdown</tt> execution;
+this phase only catches stragglers, background processs, etc. </li>
+ <li> The sequence sleeps for <em>finalsleeptime</em> milliseconds, to
+allow all processes to finish their clean exit routine. </li>
+ <li> All processes get a SIGKILL. </li>
+ <li> All zombies are reaped. </li>
+ <li> All filesystems get unmounted, and the root filesystem is remounted
+read-only. </li>
+ <li> The machine performs a hardware reboot, halt or poweroff, depending
+on the command that has been used. </li>
</ul> </li>
-<li> The last command that <em>stage3</em> executes should be
-<tt>s6-$1 -f</tt>, <tt>$1</tt> being the first argument that has been
-given to it. This command will instantly execute the hard system halt,
-poweroff or reboot that has initially been asked by the admin. </li>
-
</ul>
<p>
The <tt>examples/</tt> subdirectory of the s6-linux-init package
-contains an example of <tt>/etc/rc.init</tt>, <tt>/etc/rc.tini</tt>
+contains an example of <tt>/etc/rc.init</tt>
and <tt>/etc/rc.shutdown</tt> scripts, suitable for
-<em>stage2</em>, <em>stage2_finish</em> and <em>stage3</em>
+<em>initscript</em> and <em>shutdownscript</em>
respectively. Those scripts can practically be used as is if the machine
is managed by the <a href="//skarnet.org/software/s6-rc/">s6-rc</a>
service manager.
@@ -292,7 +285,7 @@ should be a getty, to allow logins even if <em>stage2</em> fails.
<tt>"/sbin/getty 38400 tty1"</tt>. By default, no early service
is defined. </li> <p />
- <li> <tt>-2</tt>&nbsp;<em>stage2</em>&nbsp;: <em>stage2</em> is
+ <li> <tt>-2</tt>&nbsp;<em>initscript</em>&nbsp;: <em>initscript</em> is
the location of the stage 2 script that will be run when the
system has an operational supervision tree. It must be absolute. Default is
<strong><tt>/etc/rc.init</tt></strong>. </li> <p />
@@ -305,21 +298,15 @@ with an early getty, or be undesirable for other reasons. The
to the catch-all logger, so the output will be made available
in the <tt><em>tmpfsdir</em>/uncaught-logs</tt> directory. </li> <p />
- <li> <tt>-Z</tt>&nbsp;<em>stage2_finish</em>&nbsp;:
-<em>stage2_finish</em> is the location of the script that will be
+ <li> <tt>-Z</tt>&nbsp;<em>shutdownscript</em>&nbsp;:
+<em>shutdownscript</em> is the location of the script that will be
run when s6-svscan receives a signal that tells it to stop the
-machine, before it executes into <em>stage3</em>. It must be
-absolute. Default is <strong><tt>/etc/rc.tini</tt></strong>.
+machine, before it executes into the final shutdown sequence. It must be
+absolute. Default is <strong><tt>/etc/rc.shutdown</tt></strong>.
Note that this script is run with its stdout and stderr
redirected to the <tt><em>tmpfsdir</em>/uncaught-logs</tt> logging
directory, so its output will not appear on the system's console. </li> <p />
- <li> <tt>-3</tt>&nbsp;<em>stage3</em>&nbsp;: <em>stage3</em> is
-the location of the stage 3 script that will be run at the end of
-the machine lifetime, when s6-svscan is told to terminate.
-It must be absolute. Default is
-<strong><tt>/etc/rc.shutdown</tt></strong>. </li> <p />
-
<li> <tt>-p</tt>&nbsp;<em>initial_path</em>&nbsp;: the value to
set the PATH environment variable to, for all the starting processes.
This will be done as early as possible in <em>stage 1</em>. It is
@@ -383,6 +370,16 @@ and <tt>.s6-svscan/SIGINT</tt> scripts slightly, in order to provide
adequate functionality when the containerized system is asked to
shutdown. Do not add this option if the init script is going to run
in the root pid namespace. </li> <p />
+
+ <li> <tt>-q</tt>&nbsp;<em>finalsleeptime</em>&nbsp;: when the machine
+shuts down, all processes that have not already been killed during
+<tt>shutdownscript</tt> will receive a SIGTERM or a SIGHUP to allow
+them to exit gracefully; then, after <em>finalsleeptime</em>
+milliseconds, they will receive a SIGKILL and the shutdown sequence
+will go on. This option configures the amount of time that will
+elapse between the SIGTERM/SIGHUP and the SIGKILL.
+Default is <strong>2000</strong>, meaning a grace period of 2 seconds. </li> <p />
+
</ul>
<h2> Notes </h2>
diff --git a/doc/upgrade.html b/doc/upgrade.html
index aa04135..7acdf64 100644
--- a/doc/upgrade.html
+++ b/doc/upgrade.html
@@ -18,6 +18,23 @@
<h1> What has changed in s6-linux-init </h1>
+<h2> in 0.4.0.0 </h2>
+
+<ul>
+ <li> <a href="//skarnet.org/software/skalibs/">skalibs</a>
+dependency bumped to 2.6.3.0. </li>
+ <li> <a href="//skarnet.org/software/execline/">execline</a>
+dependency bumped to 2.3.0.4. </li>
+ <li> <a href="//skarnet.org/software/s6/">s6</a>
+dependency bumped to 2.7.0.0. </li>
+ <li> <a href="s6-linux-init-maker.html">s6-linux-init-maker</a> now
+autogenerates stage 3, which is not the responsibility of the user
+anymore (stage 3 was previously the user-written <tt>/etc/rc.shutdown</tt>
+script). </li>
+ <li> The default user-provided "end of stage 2, bring down services" script
+was named <tt>/etc/rc.tini</tt> before; now it's named <tt>/etc/rc.shutdown</tt>. </li>
+</ul>
+
<h2> in 0.3.1.1 </h2>
<ul>
diff --git a/examples/rc.init b/examples/rc.init
index d71fd1a..afc7735 100755
--- a/examples/rc.init
+++ b/examples/rc.init
@@ -1,17 +1,9 @@
#!/bin/execlineb -P
-
-# Make sure the /dev/urandom entropy pool will be set in
-# a not-too-distant future. Ideally we'd block on this,
-# but it's not critical, so we don't.
-
-background -d { s6-fillurandompool }
-
-
# Set the system clock to something sensible,
-# to get coherent logs until the initial NTP message
+# to get coherent logs until the initial NTP exchange
-if { s6-clock @40000000596c000000000000 }
+if { s6-clock @400000005a58000000000000 }
# Initialize the service manager
diff --git a/examples/rc.shutdown b/examples/rc.shutdown
index 04d7357..14b4692 100755
--- a/examples/rc.shutdown
+++ b/examples/rc.shutdown
@@ -1,20 +1,16 @@
-#!/bin/execlineb -S0
+#!/bin/execlineb -P
-foreground { s6-echo "Giving dying processes some grace time." }
-foreground { s6-sleep 2 }
-foreground { s6-echo "Syncing disks." }
-foreground { s6-sync }
-foreground { s6-echo "Sending all processes the TERM signal." }
-foreground { s6-nuke -th }
-foreground { s6-sleep 2 }
-foreground { s6-echo "Sending all processes the KILL signal." }
-foreground { s6-nuke -k }
-wait { }
-foreground { s6-echo "Syncing and unmounting disks." }
-foreground { s6-sync }
-foreground { s6-umount -a }
-foreground { s6-mount -ro remount /dev/root / }
+# Write a message to /var/log/syslogd
-foreground { s6-echo "\nPerforming "${1}"." }
-s6-${1} -f
+foreground
+{
+ s6-ipcclient -l0 /dev/log
+ fdmove 1 7
+ s6-echo "/etc/rc.shutdown: shutdown requested"
+}
+
+
+# Shut down all services
+
+s6-rc -da change
diff --git a/examples/rc.tini b/examples/rc.tini
deleted file mode 100755
index 02e7ec7..0000000
--- a/examples/rc.tini
+++ /dev/null
@@ -1,16 +0,0 @@
-#!/bin/execlineb -P
-
-
-# Write a message to /var/log/syslogd
-
-foreground
-{
- s6-ipcclient -l0 /dev/log
- fdmove 1 7
- s6-echo "/etc/rc.tini: shutdown requested"
-}
-
-
-# Shut down all services
-
-s6-rc -da change
diff --git a/package/info b/package/info
index bf53f22..f7c3758 100644
--- a/package/info
+++ b/package/info
@@ -1,4 +1,4 @@
package=s6-linux-init
-version=0.3.1.1
+version=0.4.0.0
category=admin
package_macro_name=S6_LINUX_INIT
diff --git a/src/init/s6-linux-init-maker.c b/src/init/s6-linux-init-maker.c
index 71d82cb..30866fe 100644
--- a/src/init/s6-linux-init-maker.c
+++ b/src/init/s6-linux-init-maker.c
@@ -16,7 +16,7 @@
#include <skalibs/sgetopt.h>
#include <skalibs/skamisc.h>
-#define USAGE "s6-linux-init-maker [ -c basedir ] [ -l tmpfsdir ] [ -b execline_bindir ] [ -u log_uid -g log_gid | -U ] [ -G early_getty_cmd ] [ -2 stage2_script ] [ -r ] [ -Z finish_script ] [ -3 stage3_script ] [ -p initial_path ] [ -m initial_umask ] [ -t timestamp_style ] [ -d dev_style ] [ -s env_store ] [ -e initial_envvar ... ] [ -n ] dir"
+#define USAGE "s6-linux-init-maker [ -c basedir ] [ -l tmpfsdir ] [ -b execline_bindir ] [ -u log_uid -g log_gid | -U ] [ -G early_getty_cmd ] [ -2 stage2_script ] [ -r ] [ -Z shutdownscript ] [ -p initial_path ] [ -m initial_umask ] [ -t timestamp_style ] [ -d dev_style ] [ -s env_store ] [ -e initial_envvar ... ] [ -n ] [ -q final_sleep_time ] dir"
#define dieusage() strerr_dieusage(100, USAGE)
#define dienomem() strerr_diefu1sys(111, "stralloc_catb") ;
@@ -34,8 +34,7 @@
static char const *slashrun = "/run" ;
static char const *robase = "/etc/s6-linux-init" ;
static char const *init_script = "/etc/rc.init" ;
-static char const *tini_script = "/etc/rc.tini" ;
-static char const *shutdown_script = "/etc/rc.shutdown" ;
+static char const *tini_script = "/etc/rc.shutdown" ;
static char const *bindir = "/bin" ;
static char const *initial_path = "/usr/bin:/usr/sbin:/bin:/sbin" ;
static char const *env_store = 0 ;
@@ -45,6 +44,7 @@ static gid_t uncaught_logs_gid = 0 ;
static unsigned int initial_umask = 022 ;
static unsigned int timestamp_style = 1 ;
static unsigned int slashdev_style = 2 ;
+static unsigned int finalsleep = 2000 ;
static int redirect_stage2 = 0 ;
static int in_namespace = 0 ;
@@ -101,6 +101,8 @@ static int s6_svscan_log_script (buffer *b)
static int finish_script (buffer *b)
{
size_t sabase = satmp.len ;
+ char fmt[UINT_FMT] ;
+ fmt[uint_fmt(fmt, finalsleep)] = 0 ;
if (buffer_puts(b, "#!") < 0
|| buffer_puts(b, bindir) < 0
|| buffer_puts(b, "/execlineb -S0\n\n") < 0
@@ -120,11 +122,21 @@ static int finish_script (buffer *b)
if (buffer_puts(b, "cd /\nredirfd -w 2 /dev/console\nfdmove -c 1 2\nforeground { s6-svc -X -- ") < 0
|| buffer_put(b, satmp.s + sabase, satmp.len - sabase) < 0) goto err ;
satmp.len = sabase ;
- if (buffer_puts(b, "/service/s6-svscan-log }\nunexport ?\nwait -r -- { }\n") < 0
- || !string_quote(&satmp, shutdown_script, strlen(shutdown_script))) return 0 ;
- if (buffer_put(b, satmp.s + sabase, satmp.len - sabase) < 0) goto err ;
- satmp.len = sabase ;
- if (buffer_puts(b, " ${@}\n") < 0) return 0 ;
+ if (buffer_puts(b, "/service/s6-svscan-log }\n"
+ "unexport ?\nwait -r -- { }\n"
+ "foreground { s6-echo \"Syncing disks.\" }\n"
+ "foreground { s6-sync }\n"
+ "foreground { s6-echo \"Sending all processes the TERM signal.\" }\n"
+ "foreground { s6-nuke -th }\n"
+ "s6-sleep -m -- ") < 0
+ || buffer_puts(b, fmt) < 0
+ || buffer_puts(b, "\nforeground { s6-echo \"Sending all processes the KILL signal.\" }\n"
+ "foreground { s6-nuke -k }\n"
+ "wait { }\n"
+ "foreground { s6-echo \"Unmounting disks.\" }\n"
+ "foreground { s6-umount -a }\n"
+ "foreground { s6-mount -ro remount /dev/root / }\n"
+ "s6-${1} -f\n") < 0) return 0 ;
return 1 ;
err:
satmp.len = sabase ;
@@ -394,7 +406,7 @@ int main (int argc, char const *const *argv, char const *const *envp)
subgetopt_t l = SUBGETOPT_ZERO ;
for (;;)
{
- int opt = subgetopt_r(argc, argv, "c:l:b:u:g:UG:2:rZ:3:p:m:t:d:s:e:n", &l) ;
+ int opt = subgetopt_r(argc, argv, "c:l:b:u:g:UG:2:rZ:p:m:t:d:s:e:nq:", &l) ;
if (opt == -1) break ;
switch (opt)
{
@@ -416,7 +428,6 @@ int main (int argc, char const *const *argv, char const *const *envp)
case '2' : init_script = l.arg ; break ;
case 'r' : redirect_stage2 = 1 ; break ;
case 'Z' : tini_script = l.arg ; break ;
- case '3' : shutdown_script = l.arg ; break ;
case 'p' : initial_path = l.arg ; break ;
case 'm' : if (!uint0_oscan(l.arg, &initial_umask)) dieusage() ; break ;
case 't' : if (!uint0_scan(l.arg, &timestamp_style)) dieusage() ; break ;
@@ -424,6 +435,7 @@ int main (int argc, char const *const *argv, char const *const *envp)
case 's' : env_store = l.arg ; break ;
case 'e' : if (!stralloc_catb(&satmp, l.arg, strlen(l.arg) + 1)) dienomem() ; break ;
case 'n' : in_namespace = 1 ; break ;
+ case 'q' : if (!uint0_scan(l.arg, &finalsleep)) dieusage() ; break ;
default : dieusage() ;
}
}
@@ -440,9 +452,7 @@ int main (int argc, char const *const *argv, char const *const *envp)
if (init_script[0] != '/')
strerr_dief3x(100, "stage 2 script location ", init_script, " is not absolute") ;
if (tini_script[0] != '/')
- strerr_dief3x(100, "stage 2 finish script location ", tini_script, " is not absolute") ;
- if (shutdown_script[0] != '/')
- strerr_dief3x(100, "stage 3 script location ", shutdown_script, " is not absolute") ;
+ strerr_dief3x(100, "shutdown script location ", tini_script, " is not absolute") ;
if (timestamp_style > 3)
strerr_dief1x(100, "-t timestamp_style must be 0, 1, 2 or 3") ;
if (slashdev_style > 2)