Invoking ‘init’ from an init.d script (Wheezy)
The short question:
Is it acceptable to boot a server into runlevel 1, and then invoke
"init 2" from an /etc/rc1.d script to interrupt the execution of any
further scripts in that runlevel and continue in RL2?
The long story:
We have a setup with multiple servers (running Wheezy). When booting,
the servers check whether updates are available on a master server. If
available, they are pulled in through a dist-upgrade. This
check/update needs to happen before any of the normal services are
started, to avoid the need of taking down everything and then starting
it back up after the update.
The most sane thing to do would be to perform this check/update as the
very first init script in runlevel 2. This however seems impossible to
guarantee, aside from the unmaintainable practice of adding every
possible service to the Required-Start field of this script. There is
a way to make a script run last (Required-Start: $all), but as you may
have guessed, "X-Start-Before: $all" does not work.
The next most sane thing to do would be to run the script at the end
of runlevel S. When we do this however, the dist-upgrade will often
hang indefinitely after the unpacking stage. Any attempt to perform
the upgrade while we're still in level S, results in the same hang.
Therefore to both avoid this hang and guarantee that the update is
performed before any runlevel 2 service, we boot the servers into
runlevel 1 and check the update there. The init script is configured
as "X-Start-Before: killprocs", because we do not want anything to be
killed at boot. /etc/rc1.d therefore looks like this:
To allow runlevel 1 to be used normally, the script does nothing if
this is not the first runlevel after boot. Otherwise it does its
thing, and when done invokes "init 2" to replace the entire shell and
therefore (in theory) prevent S02killprocs and S03single from being
executed. This works fine in most cases.
On one particular server however, we noticed that killprocs was
sometimes (in about 20% of all boots) still being executed even though
the 'runlevel' command already reports the current level to be 2.
We managed to work around this by adding an extra check to the
killprocs script that skips it if the runlevel is not 1.
However, we realize that what we're doing might not be perfectly sane
and wonder whether it might have other risks.
We could avoid this 'init-inside-an-initscript' hack if someone had a
foolproof way of guaranteeing that the init script is always executed
as the very first in runlevel 2.