mirror of
https://github.com/troglobit/finit.git
synced 2026-10-15 10:29:35 +00:00
Add support for SysV-only scripts in runparts
This patch extens the SysV compatibility support in Finit by adding support for limiting `runparts` to run only SNNfoo, or KNNfoo, style scripts from a directory. Additionally, by default `runparts` now runs entirely in the background without any progress. To enable progress, an optional argument has been added to the runparts command line. Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
This commit is contained in:
1 parent
846806747b
commit
6ae1083c99
17 files changed
+118
-42
No files matched your search
-10
@@ -9,16 +9,6 @@ value in the project turned out to be:
|
||||
> systems, container, and dedicated server applications.
|
||||
|
||||
|
||||
Before Next Release
|
||||
-------------------
|
||||
|
||||
* When did runparts +arg break?
|
||||
* Should we update the =runparts DIR= syntax to =runparts [progress] [debug] DIR=?
|
||||
* Add SNN-only option top runparts, for Buildroot
|
||||
* Calling `initctl runlevel` at bootstrap => N 10, what should it be?
|
||||
* Reindent all shell scripts in true emacs shell-script-mode (4 chars)
|
||||
|
||||
|
||||
Misc TODOs
|
||||
----------
|
||||
|
||||
|
||||
+19
-19
@@ -842,7 +842,7 @@ the above `kill:SEC` syntax.
|
||||
|
||||
### Run-parts Scripts
|
||||
|
||||
**Syntax:** `runparts <DIR>`
|
||||
**Syntax:** `runparts [progress] [sysv] <DIR>`
|
||||
|
||||
Call [run-parts(8)][] on `DIR` to run start scripts. All executable
|
||||
files, or scripts, in the directory are called, in alphabetic order.
|
||||
@@ -854,25 +854,23 @@ services, which Finit will then apply when changing runlevel from S to
|
||||
whatever the next runlevel is set to be (default 2). E.g., generate a
|
||||
`/etc/chrony.conf` and call `initctl enable chronyd`.
|
||||
|
||||
**Options:**
|
||||
|
||||
- `progress`: display the progress of each script being executed
|
||||
- `sysv`: run only SysV style scripts, i.e., `SNNfoo`, or `KNNbar`,
|
||||
where `NN` is a number (0-99).
|
||||
|
||||
If global debug mode is enabled, the `runparts` program is also called
|
||||
with the debug flag.
|
||||
|
||||
**Limitations:**
|
||||
|
||||
Scripts called from `runparts`, or hook scripts (see below), are limited
|
||||
in what they can do and expect from Finit:
|
||||
|
||||
1. Finit is single threaded and all scripts executed from these two
|
||||
mechanisms are limited to file system operations (early or late
|
||||
hooks may not have write access!) and standard UNIX programs.
|
||||
2. Thus, it is *not possible* to call `initctl` to query status of
|
||||
services since that calls Finit over the `/run/finit/socket`.
|
||||
3. Confusingly enough, there are some commands to `initctl` that are
|
||||
available; `ls`, `enable`, `disable`, `touch`, `create`, `delete`,
|
||||
and all the `cond` commands. Because all these are basically just
|
||||
wrappers for manipulating files (again, write access for early/late
|
||||
hooks may not be available).
|
||||
|
||||
Also, similar to the `/etc/rc.local` shell script, make sure that all
|
||||
your services and programs either terminate or start in the background
|
||||
or you will block Finit.
|
||||
in their interaction with Finit. Like the standalone `run` stanza and
|
||||
the `/etc/rc.local` shell script, Finit waits for their completion
|
||||
before continuing. None of them can issue commands to start, stop, or
|
||||
restart other services. Also, ensure all your services and programs
|
||||
either terminate or start in the background or you will block Finit.
|
||||
|
||||
> **Note:** `runparts` scrips are only read and executed in runlevel S
|
||||
> ([bootstrap][]). See [hook scripts](plugins.md#hooks) for other ways
|
||||
@@ -1073,8 +1071,10 @@ sync(2) has been called, twice.
|
||||
SysV Init Compatibility
|
||||
-----------------------
|
||||
|
||||
Finit comes with a few SysV Init compatibility features to ease the
|
||||
transition from a serialized boot process.
|
||||
It is not possible to run unmodified SysV init systems with Finit. This
|
||||
was never the intention and is not the strength of Finit. However, it
|
||||
comes with a few SysV Init compatibility features to ease the transition
|
||||
from a serialized boot process.
|
||||
|
||||
### `runparts DIRECTORY`
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@ static void setup(void *arg)
|
||||
|
||||
touch("/etc/resolvconf/run/enable-updates");
|
||||
chdir("/etc/resolvconf/run/interface");
|
||||
run_parts("/etc/resolvconf/update.d", "-i", NULL, 0);
|
||||
run_parts("/etc/resolvconf/update.d", "-i", NULL, 0, 0);
|
||||
chdir("/");
|
||||
}
|
||||
|
||||
|
||||
+21
-1
@@ -82,6 +82,10 @@ char *fsck_mode = "";
|
||||
char *fsck_repair = "-p";
|
||||
#endif
|
||||
|
||||
char *runparts = NULL;
|
||||
int runparts_progress;
|
||||
int runparts_sysv;
|
||||
|
||||
char cgroup_current[16]; /* cgroup.NAME sets current cgroup for a set of services */
|
||||
|
||||
struct conf_change {
|
||||
@@ -795,6 +799,15 @@ static int parse_static(char *line, int is_rcsd)
|
||||
|
||||
if (BOOTSTRAP && MATCH_CMD(line, "runparts ", x)) {
|
||||
if (runparts) free(runparts);
|
||||
runparts_progress = runparts_sysv = 0;
|
||||
while (x) {
|
||||
if (MATCH_CMD(x, "progress", x))
|
||||
runparts_progress = 1;
|
||||
else if (MATCH_CMD(x, "sysv", x))
|
||||
runparts_sysv = 1;
|
||||
else
|
||||
break;
|
||||
}
|
||||
runparts = strdup(strip_line(x));
|
||||
return 0;
|
||||
}
|
||||
@@ -1480,7 +1493,14 @@ int conf_init(uev_ctx_t *ctx)
|
||||
*/
|
||||
if (runparts && fisdir(runparts) && !rescue) {
|
||||
char conf[sizeof(_PATH_RUNPARTS) + strlen(runparts) + 100];
|
||||
char *args = debug ? "-d" : "-p";
|
||||
char args[10] = { 0 };
|
||||
|
||||
if (debug)
|
||||
strlcat(args, "-d ", sizeof(args));
|
||||
if (runparts_progress)
|
||||
strlcat(args, "-p ", sizeof(args));
|
||||
if (runparts_sysv)
|
||||
strlcat(args, "-s ", sizeof(args));
|
||||
|
||||
snprintf(conf, sizeof(conf), "[S] <int/bootstrap> log:console %s %s %s"
|
||||
" -- Calling runparts %s in the background",
|
||||
|
||||
@@ -75,7 +75,6 @@ char *fstab = NULL;
|
||||
char *sdown = NULL;
|
||||
char *network = NULL;
|
||||
char *hostname = NULL;
|
||||
char *runparts = NULL;
|
||||
char *osheading = NULL;
|
||||
|
||||
uev_ctx_t *ctx = NULL; /* Main loop context */
|
||||
|
||||
+1
-1
@@ -89,7 +89,7 @@ int exec_runtask (char *cmd, char *args[]);
|
||||
pid_t run_getty (char *tty, char *cmd, char *args[], int noclear, int nowait, struct rlimit rlimit[]);
|
||||
pid_t run_sh (char *tty, int noclear, int nowait, struct rlimit rlimit[]);
|
||||
pid_t run_bg (char *cmd, char *args[]);
|
||||
int run_parts (char *dir, char *cmd, const char *env[], int progress);
|
||||
int run_parts (char *dir, char *cmd, const char *env[], int progress, int sysv);
|
||||
|
||||
/*
|
||||
* Defaults to user "root" and group "wheel" (root) if:
|
||||
|
||||
+1
-1
@@ -230,7 +230,7 @@ void plugin_script_run(hook_point_t no)
|
||||
} else
|
||||
env[2] = NULL;
|
||||
|
||||
run_parts(path, NULL, env, 0);
|
||||
run_parts(path, NULL, env, 0, 0);
|
||||
}
|
||||
#else
|
||||
void plugin_script_run(hook_point_t no)
|
||||
|
||||
+13
-5
@@ -83,7 +83,7 @@ static void run_env(const char *env[])
|
||||
}
|
||||
}
|
||||
|
||||
int run_parts(char *dir, char *cmd, const char *env[], int progress)
|
||||
int run_parts(char *dir, char *cmd, const char *env[], int progress, int sysv)
|
||||
{
|
||||
size_t cmdlen = cmd ? strlen(cmd) : strlen("start");
|
||||
struct dirent **d;
|
||||
@@ -127,6 +127,11 @@ int run_parts(char *dir, char *cmd, const char *env[], int progress)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (sysv && name[0] != 'S' && name[0] != 'K') {
|
||||
dbg("S-only flag set, skipping non-SysV script: %s", name);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* If the callee didn't supply a run_parts() argument */
|
||||
if (!cmd) {
|
||||
/* Check if S<NUM>service or K<NUM>service notation is used */
|
||||
@@ -179,16 +184,16 @@ int run_parts(char *dir, char *cmd, const char *env[], int progress)
|
||||
#ifndef __FINIT__
|
||||
static int usage(int rc)
|
||||
{
|
||||
warnx("usage: runparts [-dh?] DIRECTORY");
|
||||
warnx("usage: runparts [-dhps?] DIRECTORY");
|
||||
return rc;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int rc, c, progress = 0;
|
||||
int rc, c, progress = 0, sysv = 0;
|
||||
char *dir;
|
||||
|
||||
while ((c = getopt(argc, argv, "dh?p")) != EOF) {
|
||||
while ((c = getopt(argc, argv, "dh?ps")) != EOF) {
|
||||
switch(c) {
|
||||
case 'd':
|
||||
debug = 1;
|
||||
@@ -199,6 +204,9 @@ int main(int argc, char *argv[])
|
||||
case 'p':
|
||||
progress = 1;
|
||||
break;
|
||||
case 's':
|
||||
sysv = 1;
|
||||
break;
|
||||
default:
|
||||
return usage(1);
|
||||
}
|
||||
@@ -213,7 +221,7 @@ int main(int argc, char *argv[])
|
||||
|
||||
prctl(PR_SET_CHILD_SUBREAPER, 1);
|
||||
|
||||
rc = run_parts(dir, NULL, NULL, progress);
|
||||
rc = run_parts(dir, NULL, NULL, progress, sysv);
|
||||
if (rc == -1)
|
||||
err(1, "failed run-parts %s", dir);
|
||||
|
||||
|
||||
+6
-1
@@ -2,9 +2,12 @@ SUBDIRS = lib src
|
||||
|
||||
EXTRA_DIST = skel/bin/busybox-x86_64.sha256 skel/sbin/service.sh skel/etc/env \
|
||||
skel/bin/pre.sh skel/bin/post.sh skel/bin/ready.sh skel/bin/slay \
|
||||
skel/sbin/fail.sh skel/usr/share/runlevel/ref.log \
|
||||
skel/sbin/fail.sh skel/usr/share/runparts/ref.log \
|
||||
skel/usr/share/runparts/sysv.log \
|
||||
skel/etc/rc.d/foo.sh skel/etc/rc.d/S01abc.sh \
|
||||
skel/etc/rc.d/test.sh skel/etc/rc.d/S02def.sh \
|
||||
skel/etc/rcS.d/foo.sh skel/etc/rcS.d/test.sh \
|
||||
skel/etc/rcS.d/S01abc.sh skel/etc/rcS.d/S02def.sh \
|
||||
skel/cdrom/.empty skel/dev/shm/.empty skel/dev/pts/.empty \
|
||||
skel/etc/inittab skel/etc/hostname skel/etc/fstab \
|
||||
skel/etc/init.d/rcS skel/etc/init.d/rcK skel/tmp/.empty \
|
||||
@@ -41,6 +44,7 @@ EXTRA_DIST += runlevel.sh
|
||||
EXTRA_DIST += run-restart-forever.sh
|
||||
EXTRA_DIST += run-task-tricks.sh
|
||||
EXTRA_DIST += runparts.sh
|
||||
EXTRA_DIST += sysvparts.sh
|
||||
EXTRA_DIST += start-stop-service.sh
|
||||
EXTRA_DIST += start-stop-service-sub-config.sh
|
||||
EXTRA_DIST += start-kill-service.sh
|
||||
@@ -80,6 +84,7 @@ TESTS += rclocal.sh
|
||||
TESTS += ready-serv.sh
|
||||
TESTS += restart-self.sh
|
||||
TESTS += runlevel.sh
|
||||
TESTS += sysvparts.sh
|
||||
TESTS += run-restart-forever.sh
|
||||
TESTS += run-task-tricks.sh
|
||||
TESTS += runparts.sh
|
||||
|
||||
+2
-2
@@ -37,5 +37,5 @@ while true; do
|
||||
sleep 1
|
||||
done
|
||||
|
||||
texec diff -u /usr/share/runlevel/ref.log /tmp/runparts.log
|
||||
texec cmp /usr/share/runlevel/ref.log /tmp/runparts.log || fail "runparts in wrong order"
|
||||
texec diff -u /usr/share/runparts/ref.log /tmp/runparts.log
|
||||
texec cmp /usr/share/runparts/ref.log /tmp/runparts.log || fail "runparts in wrong order"
|
||||
Executable
+3
@@ -0,0 +1,3 @@
|
||||
#!/bin/sh
|
||||
|
||||
echo "$0 $*" >> /tmp/sysv.log
|
||||
Symlink
+1
@@ -0,0 +1 @@
|
||||
S01abc.sh
|
||||
Executable
+3
@@ -0,0 +1,3 @@
|
||||
#!/bin/sh
|
||||
|
||||
echo "$0" >> /tmp/sysv.log
|
||||
Executable
+3
@@ -0,0 +1,3 @@
|
||||
#!/bin/sh
|
||||
|
||||
echo "$0" >> /tmp/sysv.log
|
||||
File renamed without changes.
@@ -0,0 +1,2 @@
|
||||
/etc/rcS.d/S01abc.sh start
|
||||
/etc/rcS.d/S02def.sh start
|
||||
Executable
+42
@@ -0,0 +1,42 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Verifies SysV runparts behavior: to run all scripts in a directory at
|
||||
# the end of system bootstrap, right before calling /etc/rc.local:
|
||||
#
|
||||
# - only SNNfoo or KNNfoo executable scripts should be called
|
||||
# - always in alphabetical order
|
||||
# - SNNfoo should be called with a 'start' argument
|
||||
# - KNNfoo should be called with a 'stop' argument
|
||||
#
|
||||
|
||||
TEST_DIR=$(dirname "$0")
|
||||
#DEBUG=1
|
||||
|
||||
# shellcheck disable=SC2034
|
||||
BOOTSTRAP="runparts sysv /etc/rcS.d"
|
||||
|
||||
# shellcheck source=/dev/null
|
||||
. "$TEST_DIR/lib/setup.sh"
|
||||
|
||||
test_setup()
|
||||
{
|
||||
say "Test start $(date)"
|
||||
}
|
||||
|
||||
test_teardown()
|
||||
{
|
||||
say "Test done $(date)"
|
||||
}
|
||||
|
||||
while true; do
|
||||
lvl=$(texec initctl runlevel)
|
||||
say "Current runlevel $lvl"
|
||||
if [ "$lvl" = "N 2" ]; then
|
||||
break;
|
||||
fi
|
||||
sleep 1
|
||||
done
|
||||
|
||||
texec cat /tmp/sysv.log
|
||||
texec diff -u /usr/share/runparts/sysv.log /tmp/sysv.log
|
||||
texec cmp /usr/share/runparts/sysv.log /tmp/sysv.log || fail "runparts sysv in wrong order"
|
||||
Reference in new issue
Block a user