Welcome to little lamb

Code » anopa » commit 500966b

stage0/2..4: Exec $REPODIR/.anopa/post-stageX after aa-start/stop

author Olivier Brunel
2018-01-22 21:06:54 UTC
committer Olivier Brunel
2018-01-23 17:16:51 UTC
parent 3b7a0401879126395e618143bb6f850ada95a14c

stage0/2..4: Exec $REPODIR/.anopa/post-stageX after aa-start/stop

Instead of trying to handle aa-start/aa-stop return code and opening a
shell an error, now we just check if $REPODIR/.anopa/post-stageX (where
X is the corresponding number, ofc) exists, and if so execute it.

doc/aa-stage0.pod +17 -14
doc/aa-stage2.pod +8 -3
doc/aa-stage3.pod +9 -1
doc/aa-stage4.pod +11 -2
src/scripts/aa-stage0 +10 -12
src/scripts/aa-stage2 +17 -27
src/scripts/aa-stage3 +7 -1
src/scripts/aa-stage4 +5 -1

diff --git a/doc/aa-stage0.pod b/doc/aa-stage0.pod
index 8aded55..4d4130e 100644
--- a/doc/aa-stage0.pod
+++ b/doc/aa-stage0.pod
@@ -30,17 +30,20 @@ I</root-fs/sys> and I</root-fs/run>
 
 It is also up to them to load required kernel modules in order to do so.
 
-Once B<aa-start>(1) is done, B<aa-stage0>(1) will mount bind the rootfs (of the
-initramfs) onto I</root-fs/run/initramfs> (so it's possible to pivot back into
-it at the end of stage 3) before doing a mount move of I</root-fs> onto I</> and
-executing (via B<aa-chroot>(1)) into I</sbin/init>, or whatever was specified
-via I<init> on the kernel command line.
-
-If B<aa-start>(1) exits non-zero, e.g. if an essential service failed to be
-started, B<aa-stage0>(1) assumes the root file system couldn't be mounted, and
-tries to open a shell (I<sh -i>) to give you a possibility to fix things.
-Exiting the shell will resume the process.
-
-You can also specify I<break> on the kernel command line to open a shell after
-B<aa-start>(1) succesfully completed, before moving I</root-fs> to I</> (also
-before mount binding the rootfs).
+After B<aa-start>(1) has run, and if it exists, B<aa-stage0>(1) will execute
+I</services/.anopa/post-stage0> with B<aa-start>(1)'s return code as
+argument. This allows to e.g. open a shell if something went terribly wrong.
+
+Note that file descriptor 3 will remain open for writing and connected to the
+logger, so anything written there will be timestamped & logged.
+
+For an example, see B<aa-post-stage0>(1)
+
+If "break" was specified on the kernel command line, an interactive shell will
+be open. Once you "exit" the shell, process continues.
+
+Then B<aa-stage0>(1) will mount bind the rootfs (of the initramfs) onto
+I</root-fs/run/initramfs> (so it's possible to pivot back into it at the end of
+stage 3) before doing a mount move of I</root-fs> onto I</> and executing (via
+B<aa-chroot>(1)) into I</sbin/init>, or whatever was specified via I<init> on
+the kernel command line.
diff --git a/doc/aa-stage2.pod b/doc/aa-stage2.pod
index d57643a..afb4044 100644
--- a/doc/aa-stage2.pod
+++ b/doc/aa-stage2.pod
@@ -19,6 +19,11 @@ It starts all services via B<aa-start>(1) using I</etc/anopa/listdirs/onboot> as
 listdir, unless argument B<aa> was specified on kernel command line, in which
 case I</etc/anopa/listdirs/ARGVALUE> is used as listdir intead.
 
-If B<aa-start>(1) exits non-zero, it assumes there might not even be a getty
-running, and will try to open a shell (I<sh -i>). Else, the system is assumed to
-be ready.
+After B<aa-start>(1) has run, and if it exists, B<aa-stage2>(1) will execute
+I</run/services/.anopa/post-stage2> with B<aa-start>(1)'s return code as
+argument. This allows to e.g. open a shell if something went terribly wrong.
+
+Note that file descriptor 3 will remain open for writing and connected to the
+logger, so anything written there will be timestamped & logged.
+
+For an example, see B<aa-post-stage2>(1)
diff --git a/doc/aa-stage3.pod b/doc/aa-stage3.pod
index e2d8de1..1bdfca4 100644
--- a/doc/aa-stage3.pod
+++ b/doc/aa-stage3.pod
@@ -19,6 +19,13 @@ service I<uncaught-logs> to catch all possible logs as long as possible. The
 B<s6-supervise> process of that service will be sent command 'x' so it simply
 exits when the supervised process will.
 
+After B<aa-stop>(1) has run, and if it exists, B<aa-stage3>(1) will execute
+I</run/services/.anopa/post-stage3> with B<aa-stop>(1)'s return code as
+argument. This allows to e.g. open a shell if something went terribly wrong.
+
+Note that file descriptor 3 will remain open for writing and connected to the
+logger, so anything written there will be timestamped & logged.
+
 Signal SIGTERM is then sent to (almost) all processes, using B<aa-kill>(1) with
 option B<--skip>; Then SIGKILL is sent similarly.
 
@@ -27,4 +34,5 @@ exec into I</shutdown> will the same argument it received from B<s6-svscan>, so
 either "halt", "reboot" or "poweroff".
 
 If B<aa-pivot>(1) fails, it will try to open a shell (I<sh -i>) to let you deal
-with things manually.
+with things manually. Again, fd 3 will be still be opened to the logger at this
+point.
diff --git a/doc/aa-stage4.pod b/doc/aa-stage4.pod
index 1cdcc6f..ab0bf56 100644
--- a/doc/aa-stage4.pod
+++ b/doc/aa-stage4.pod
@@ -21,6 +21,15 @@ Services are meant to unmount the root file system from I</root-fs> as well as
 all API file systems in there: I</root-fs/dev>, I</root-fs/proc>,
 I</root-fs/sys> and I</root-fs/run>
 
+After B<aa-stop>(1) has run, and if it exists, B<aa-stage4>(1) will execute
+I</services/.anopa/post-stage4> with B<aa-stop>(1)'s return code as
+argument. This allows to e.g. open a shell if something went terribly wrong.
+
+Note that obviously by this point there's no more logger, and unlike at other
+stages file descriptor 3 isn't open anymore.
+
 Then it will mount I</dev> and I</proc> in order to run B<aa-terminate>(1) to
-make sure everything is closed/unmounted. It then performs the requested action
-(on stage 3) via B<aa-reboot>(1).
+make sure everything is closed/unmounted. If B<aa-terminate>(1) exits non-zero,
+an interactive shell (I<sh -i>) is opened.
+
+It then performs the requested action (on stage 3) via B<aa-reboot>(1).
diff --git a/src/scripts/aa-stage0 b/src/scripts/aa-stage0
index 92264c2..d2046ca 100755
--- a/src/scripts/aa-stage0
+++ b/src/scripts/aa-stage0
@@ -43,24 +43,22 @@ cd /
 umask 022
 
 # Start services
-foreground { if -n
-{
-  if { emptyenv -c s6-setsid aa-ctty -O3 -s aa-start -O3 -r /services -l onboot }
-  foreground {
-    # if "break" was specified on kernel cmdline, let's open a shell
+foreground {
+    foreground {
+        emptyenv -c s6-setsid aa-ctty -O3 -s aa-start -O3 -r /services -l onboot
+    }
+    if { aa-test -e /services/.anopa/post-stage0 }
+    importas -u RC ? emptyenv -c /services/.anopa/post-stage0 $RC
+}
+
+# if "break" was specified on kernel cmdline, let's open a shell
+foreground {
     if -t { aa-incmdline -O3 -qf /root-fs/proc/cmdline break }
     foreground { aa-echo -O3 -B "Break requested" }
     foreground { aa-echo -O3 -t "Trying to open a shell; " +g exit +w " to continue" }
     emptyenv -c sh -i
-  }
 }
 
-# aa-start failed (i.e. an essential service failed to be started), so we assume
-# the root fs wasn't mounted: try a shell so user has a chance to fix things
-foreground { aa-echo -O3 -Be "Mouting root file system failed" }
-foreground { aa-echo -O3 -t "Trying to open a shell; " +g exit +w " to continue" }
-emptyenv -c sh -i
-}
 
 if { aa-echo -O3 -B "Moving /root-fs to /..." }
 # First we mount bind the rootfs (initramfs) onto /run/initramfs so we can come
diff --git a/src/scripts/aa-stage2 b/src/scripts/aa-stage2
index 3d13a90..fe66e18 100755
--- a/src/scripts/aa-stage2
+++ b/src/scripts/aa-stage2
@@ -33,32 +33,22 @@ background
 fdclose 3
 fdmove 3 4
 
-if -n -t
-{
-  # We want the actual tty on stdin
-  backtick -n TTY { aa-tty }
-  importas -u TTY TTY
-  redirfd -r 0 ${TTY}
-  # Reopen the console
-  redirfd -w 1 /dev/console
-  fdmove -c 2 1
-  # And start everything
-  foreground { aa-echo -O3 -B "Stage 2: Initializing system..." }
-  backtick -n -D onboot LISTDIR { aa-incmdline -rs aa }
-  importas -u LISTDIR LISTDIR
-  # We have a tty in stdin, become session leader and set controlling terminal.
-  # This is so Ctrl+C will trigger a SIGINT to aa-start, so one can manually
-  # timeout a service.
-  if { emptyenv -c s6-setsid aa-ctty -O3 aa-start -O3 -l /etc/anopa/listdirs/${LISTDIR} }
-  aa-echo -O3 -B "System ready."
-}
-
-# Something went wrong, likely aa-start failed (i.e. an essential service failed
-# to be started), so we assume there's not event a getty: try a shell so user
-# has a chance to fix things
-redirfd -r 0 /dev/console
+# We want the actual tty on stdin
+backtick -n TTY { aa-tty }
+importas -u TTY TTY
+redirfd -r 0 ${TTY}
+# Reopen the console
 redirfd -w 1 /dev/console
 fdmove -c 2 1
-foreground { aa-echo -O3 -Be "System initialization failed" }
-foreground { aa-echo -O3 -t "Trying to open a shell..." }
-emptyenv -c sh -i
+# And start everything
+foreground { aa-echo -O3 -B "Stage 2: Initializing system..." }
+backtick -n -D onboot LISTDIR { aa-incmdline -rs aa }
+importas -u LISTDIR LISTDIR
+# We have a tty in stdin, become session leader and set controlling terminal.
+# This is so Ctrl+C will trigger a SIGINT to aa-start, so one can manually
+# timeout a service.
+foreground {
+    emptyenv -c s6-setsid aa-ctty -O3 aa-start -O3 -l /etc/anopa/listdirs/${LISTDIR}
+}
+if { aa-test -e /run/services/.anopa/post-stage2 }
+importas -u RC ? emptyenv -c /run/services/.anopa/post-stage2 $RC
diff --git a/src/scripts/aa-stage3 b/src/scripts/aa-stage3
index d129269..fdf91d1 100755
--- a/src/scripts/aa-stage3
+++ b/src/scripts/aa-stage3
@@ -47,7 +47,13 @@ foreground { aa-echo -O3 -B "Stage 3: Preparing ${1}..." }
 # Stop all running services -- s6-svscan did only exec into us, leaving the
 # whole supervised tree intact. Here we stop everything (longrun & oneshot) in
 # order, save for the catch-all (it will get an 'x' though).
-foreground { emptyenv -c s6-setsid aa-ctty -O3 -s aa-stop -O3 -aak uncaught-logs -t20 }
+foreground {
+    foreground {
+        emptyenv -c s6-setsid aa-ctty -O3 -s aa-stop -O3 -aak uncaught-logs -t20
+    }
+    if { aa-test -e /run/services/.anopa/post-stage3 }
+    importas -u RC ? emptyenv -c /run/services/.anopa/post-stage3 $RC
+}
 # Now stop the catch-all logger (its supervisor will then exit)
 foreground { emptyenv -c s6-setsid aa-stop -O3 uncaught-logs }
 
diff --git a/src/scripts/aa-stage4 b/src/scripts/aa-stage4
index 85f8c5a..8e09547 100755
--- a/src/scripts/aa-stage4
+++ b/src/scripts/aa-stage4
@@ -24,7 +24,11 @@
 /bin/emptyenv /bin/s6-envdir /etc/anopa/env /bin/exec
 
 foreground { aa-echo -B "Stage 4: Unmounting root file system..." }
-foreground { emptyenv -c aa-stop -r /services -a }
+foreground {
+    foreground { emptyenv -c aa-stop -r /services -a }
+    if { aa-test -e /services/.anopa/post-stage4 }
+    importas -u RC ? emptyenv -c /services/.anopa/post-stage4 $RC
+}
 
 # At this point everything should be unmounted, so we need to remount what's
 # needed for aa-terminate to work. We can't not umount /proc & /dev in aa-stop