diff options
author | Laurent Bercot <ska-skaware@skarnet.org> | 2015-10-13 16:05:05 +0000 |
---|---|---|
committer | Laurent Bercot <ska-skaware@skarnet.org> | 2015-10-13 16:05:05 +0000 |
commit | e00d2c4d88c90ccc6d091bde07d412936f8886d3 (patch) | |
tree | 21ccec11c0b36dab9f3284a311193821b3dfc700 | |
parent | 49352128c1a9dfc15a4bd29530d68a4b241909e6 (diff) | |
download | s6-linux-init-e00d2c4d88c90ccc6d091bde07d412936f8886d3.tar.xz |
- added stage2_finish support
- s6 dep bumped to 2.2.2.0
-rw-r--r-- | INSTALL | 2 | ||||
-rw-r--r-- | doc/index.html | 2 | ||||
-rw-r--r-- | doc/s6-linux-init-maker.html | 38 | ||||
-rw-r--r-- | doc/upgrade.html | 3 | ||||
-rwxr-xr-x | examples/rc.init | 4 | ||||
-rwxr-xr-x | examples/rc.shutdown | 19 | ||||
-rwxr-xr-x | examples/rc.tini | 3 | ||||
-rw-r--r-- | src/init/s6-linux-init-maker.c | 67 |
8 files changed, 132 insertions, 6 deletions
@@ -10,7 +10,7 @@ Build Instructions - execline version 2.1.4.1 or later: http://skarnet.org/software/execline/ - s6-portable-utils version 2.0.5.3 or later: http://skarnet.org/software/s6-portable-utils/ - s6-linux-utils version 2.0.2.3 or later: http://skarnet.org/software/s6-linux-utils/ - - s6 version 2.2.1.1 or later: http://skarnet.org/software/s6/ + - s6 version 2.2.2.0 or later: http://skarnet.org/software/s6/ Note that all those are build-time dependencies, and they are *also* run-time dependencies when you use the init binary created diff --git a/doc/index.html b/doc/index.html index 260b286..f328f44 100644 --- a/doc/index.html +++ b/doc/index.html @@ -58,7 +58,7 @@ a small FAQ. <li> <a href="http://skarnet.org/software/s6-linux-utils/">s6-linux-utils</a> version 2.0.2.3 or later </li> <li> <a href="http://skarnet.org/software/s6/">s6</a> version -2.2.1.1 or later </li> +2.2.2.0 or later </li> </ul> <p> diff --git a/doc/s6-linux-init-maker.html b/doc/s6-linux-init-maker.html index 530cd41..95c0101 100644 --- a/doc/s6-linux-init-maker.html +++ b/doc/s6-linux-init-maker.html @@ -50,6 +50,7 @@ machine</em> - else the scripts will crash. [ -g <em>early_getty</em> ] \ [ -2 <em>stage2</em> ] \ [ -r ] \ + [ -Z ] <em>stage2_finish</em> \ [ -3 <em>stage3</em> ] \ [ -p <em>initial_path</em> ] \ [ -m <em>initial_umask</em> ] \ @@ -186,6 +187,37 @@ do not hold any file descriptor to a filesystem that would need to be unmounted. </li> </ul> +<p> + When s6-svscan receives a signal such as SIGINT, typically sent by the +Ctrl-Alt-Del key combination or a <tt>reboot</tt> or <tt>poweroff</tt> +command, it will run the corresponding script in +<tt><em>tmpfsdir</em>/service/.s6-svscan</tt>, which will first run +<em>stage2_finish</em>, then send an exit command to s6-svscan as +described above. This is useful if some commands need to be run before +s6-svscan executes into <em>stage3</em>: for instance, if the machine +state is maintained by a service manager such as +<a href="http://skarnet.org/software/s6-rc/">s6-rc</a>, all the +services can be turned off in <em>stage2_finish</em> while s6-svscan +is still alive, and then the last steps of the shutdown procedure can +be performed in <em>stage3</em>. +</p> + +<p> + Generally speaking, <em>stage2_finish</em> should undo what +<em>stage2</em> has done at boot time, so <em>stage3</em> has very +little work to do. +</p> + +<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> +and <tt>/etc/rc.shutdown</tt> scripts, suitable for +<em>stage2</em>, <em>stage2_finish</em> and <em>stage3</em> +respectively. Those scripts can practically be used as is if the machine +is managed by the <a href="http://skarnet.org/software/s6-rc/">s6-rc</a> +service manager. +</p> + <h2> s6-linux-init-maker options </h2> <ul> @@ -235,6 +267,12 @@ 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> <em>stage2_finish</em> : +<em>stage2_finish</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>. </li> <p /> + <li> <tt>-3</tt> <em>stage3</em> : <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. diff --git a/doc/upgrade.html b/doc/upgrade.html index a5787ed..3118cbf 100644 --- a/doc/upgrade.html +++ b/doc/upgrade.html @@ -30,7 +30,8 @@ dependency bumped to 2.0.5.3. </li> <li> <a href="http://skarnet.org/software/s6-linux-utils/">s6-linux-utils</a> dependency bumped to 2.0.2.3. </li> <li> <a href="http://skarnet.org/software/s6/">s6</a> -dependency bumped to 2.2.1.1. </li> +dependency bumped to 2.2.2.0. </li> + <li> <em>stage2_finish</em> support added. </li> </ul> <h2> in 0.0.1.3 </h2> diff --git a/examples/rc.init b/examples/rc.init new file mode 100755 index 0000000..e0b2b72 --- /dev/null +++ b/examples/rc.init @@ -0,0 +1,4 @@ +#!/bin/execlineb -P + +if { s6-rc-init /run/service } +s6-rc -u change ok-all diff --git a/examples/rc.shutdown b/examples/rc.shutdown new file mode 100755 index 0000000..5589903 --- /dev/null +++ b/examples/rc.shutdown @@ -0,0 +1,19 @@ +#!/bin/execlineb -S0 + +foreground { s6-echo "Syncing disks." } +foreground { s6-sync } +foreground { s6-echo "Sending all processes the TERM signal." } +foreground { s6-nuke -th } +s6-sleep 2 +foreground { s6-echo "Sending all processes the KILL signal." } +foreground { s6-nuke -k } +wait { } + +foreground { s6-echo "Syncing disks." } +foreground { s6-sync } +foreground { s6-echo "Unmounting disks." } +foreground { s6-umount -a } +foreground { s6-mount -o ro,remount /dev/root / } + +foreground { s6-echo "\nPerforming "${1}"." } +s6-${1} diff --git a/examples/rc.tini b/examples/rc.tini new file mode 100755 index 0000000..abefb22 --- /dev/null +++ b/examples/rc.tini @@ -0,0 +1,3 @@ +#!/bin/execlineb -P + +s6-rc -da change diff --git a/src/init/s6-linux-init-maker.c b/src/init/s6-linux-init-maker.c index b0663e2..87d3787 100644 --- a/src/init/s6-linux-init-maker.c +++ b/src/init/s6-linux-init-maker.c @@ -18,7 +18,7 @@ #include <skalibs/sgetopt.h> #include <skalibs/skamisc.h> -#define USAGE "s6-linux-init-maker [ -c basedir ] [ -l tmpfsdir ] [ -b execline_bindir ] [ -u log_user ] [ -g early_getty_cmd ] [ -2 stage2_script ] [ -r ] [ -3 stage3_script ] [ -p initial_path ] [ -m initial_umask ] [ -t timestamp_style ] [ -d dev_style ] [ -e initial_envvar ... ] dir" +#define USAGE "s6-linux-init-maker [ -c basedir ] [ -l tmpfsdir ] [ -b execline_bindir ] [ -u log_user ] [ -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 ] [ -e initial_envvar ... ] dir" #define dieusage() strerr_dieusage(100, USAGE) #define dienomem() strerr_diefu1sys(111, "stralloc_catb") ; @@ -35,6 +35,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 *bindir = "/bin" ; static char const *initial_path = SKALIBS_DEFAULTPATH ; @@ -117,6 +118,57 @@ static int finish_script (buffer *b) return 0 ; } +static int sig_script (buffer *b, char c) +{ + unsigned int sabase = satmp.len ; + if (!put_shebang(b) + || buffer_puts(b, "foreground { ") < 0 + || !string_quote(&satmp, tini_script, str_len(tini_script))) return 0 ; + if (buffer_put(b, satmp.s + sabase, satmp.len - sabase) < 0) goto err ; + satmp.len = sabase ; + if (buffer_puts(b, " }\ns6-svscanctl -") < 0 + || buffer_put(b, &c, 1) < 0 + || buffer_puts(b, " -- ") < 0 + || !string_quote(&satmp, slashrun, str_len(slashrun))) return 0 ; + if (buffer_put(b, satmp.s + sabase, satmp.len - sabase) < 0) goto err ; + satmp.len = sabase ; + if (buffer_puts(b, "/service\n") < 0) return 0 ; + return 1 ; + err: + satmp.len = sabase ; + return 0 ; +} + +static int sigterm_script (buffer *b) +{ + return sig_script(b, 't') ; +} + +static int sighup_script (buffer *b) +{ + return sig_script(b, 'h') ; +} + +static int sigquit_script (buffer *b) +{ + return sig_script(b, 'q') ; +} + +static int sigint_script (buffer *b) +{ + return sig_script(b, '6') ; +} + +static int sigusr1_script (buffer *b) +{ + return sig_script(b, '7') ; +} + +static int sigusr2_script (buffer *b) +{ + return sig_script(b, '0') ; +} + static void cleanup (char const *base) { int e = errno ; @@ -205,6 +257,12 @@ static inline void make_image (char const *base) auto_dir(base, "run-image/service/.s6-svscan", 0, 0, 0755) ; auto_script(base, "run-image/service/.s6-svscan/crash", &crash_script) ; auto_script(base, "run-image/service/.s6-svscan/finish", &finish_script) ; + auto_script(base, "run-image/service/.s6-svscan/SIGTERM", &sigterm_script) ; + auto_script(base, "run-image/service/.s6-svscan/SIGHUP", &sighup_script) ; + auto_script(base, "run-image/service/.s6-svscan/SIGQUIT", &sigquit_script) ; + auto_script(base, "run-image/service/.s6-svscan/SIGINT", &sigint_script) ; + auto_script(base, "run-image/service/.s6-svscan/SIGUSR1", &sigusr1_script) ; + auto_script(base, "run-image/service/.s6-svscan/SIGUSR2", &sigusr2_script) ; auto_dir(base, "run-image/service/s6-svscan-log", 0, 0, 0755) ; auto_fifo(base, "run-image/service/s6-svscan-log/fifo") ; auto_script(base, "run-image/service/s6-svscan-log/run", &s6_svscan_log_script) ; @@ -280,7 +338,7 @@ static inline int make_init_script (buffer *b) || buffer_put(b, satmp.s + pos2, satmp.len - pos2) < 0 || buffer_puts(b, "\n}\nunexport !\ncd ") < 0 || buffer_put(b, satmp.s + sabase, pos - sabase) < 0 - || buffer_puts(b, "/service\nfdmove -c 2 1\ns6-svscan -t0\n") < 0) goto err ; + || buffer_puts(b, "/service\nfdmove -c 2 1\ns6-svscan -st0\n") < 0) goto err ; return 1 ; err: satmp.len = sabase ; @@ -295,7 +353,7 @@ int main (int argc, char const *const *argv) subgetopt_t l = SUBGETOPT_ZERO ; for (;;) { - register int opt = subgetopt_r(argc, argv, "c:l:b:u:g:2:r3:p:m:t:d:e:", &l) ; + register int opt = subgetopt_r(argc, argv, "c:l:b:u:g:2:rZ:3:p:m:t:d:e:", &l) ; if (opt == -1) break ; switch (opt) { @@ -306,6 +364,7 @@ int main (int argc, char const *const *argv) case 'g' : early_getty = l.arg ; break ; 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 ; @@ -327,6 +386,8 @@ int main (int argc, char const *const *argv) strerr_dief3x(100, "initial location for binaries ", bindir, " is not absolute") ; 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") ; if (timestamp_style > 3) |