Compare commits

...
18 Commits
Author SHA1 Message Date
Joachim Wiberg 5b9cebbfd3 Update ChangeLog and bump version for v4.5-rc4
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-10-03 16:51:03 +02:00
Joachim Wiberg 38791616e0 Add commented-out developer debug for svc_enabled()
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-10-03 16:39:46 +02:00
Joachim Wiberg fede3fd2e1 Fix #370: document conditional loading and execution config options
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-10-03 16:39:46 +02:00
Joachim Wiberg a46a33238d Display 'run' stanza progress only when they've completed
This is a follow-up to 4701ede.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-10-03 16:39:46 +02:00
Joachim Wiberg afe0488bf2 Add support for runtime evaluation of if:<condition> statements
The if: statement, introduced in v4.4, allows for discarding run/task/services
that depend on other services, based on that service's name, or condition.
Discarding in this context means unloading from the configuration.

At runtime, however, it has proven quite useful to be able to conditionally
qualify a run/task/service based on a condition.  Consider this example from
the Infix operating system:

run name:startup log:prio:user.notice \
	[S] <pid/sysrepo> confd -b --load startup-config -- Loading startup-config

run name:failure log:prio:user.critical if:<usr/fail-startup> \
	[S] <pid/sysrepo> confd --load failure-config -- Loading failure-config

The two run statements reside in the same .conf file so Finit runs them in true
sequence.  If loading the file `startup-config` fails confd sets the condition
usr/fail-startup, thus allowing the next run statement to load `failure-config`.

Notice the difference between <pid/sysrepo> condition and if:<usr/fail-startup>.
The former is a condition for starting and the latter is a condition to check if
a run/task/service is qualified to even be considerered.  The best comparison is
with the [runlevel] option, it too is used to qualify.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-10-03 16:39:46 +02:00
Joachim Wiberg ec5e42694d Silence noisy debug messages, useful only to developers
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-10-03 15:14:02 +02:00
Joachim Wiberg 2e73563eea Fix #369: allow runlevel change using initctl during bootstrap
This change opens up the runlevel change API from bootstrap.  The twist
is that the change is only queued, i.e., the call `initctl runlevel 9`
during bootstrap only changes the configured runlevel to go to after
bootstrap has completed.

Effectively, this change allows overriding the `runlevel` directive in
/etc/finit.conf without having to change the file.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-10-03 15:11:33 +02:00
Joachim Wiberg 338521a748 Update ChangeLog and bump for v4.5-rc3
No more changes are expected after -rc3.  Will be used for testing in
Infix and br2-ext-finit before the final v4.5 GA.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-09-24 14:04:28 +02:00
Joachim Wiberg 6ae1083c99 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>
2023-09-24 13:25:35 +02:00
Joachim Wiberg 846806747b Fix #366: document fsck.* command line options and simplify code
As pointed out in #366, the configure options --enable-fastboot and
--enable-fsckfix should just alter the default values of the two fsck
command line options.

This commit simplifies the code and makes it possible to override using
the command line regardless of the two build options.

Finally, add the two command line options to doc/cmdline.md

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-09-24 11:58:07 +02:00
Joachim Wiberg 8904ca993e test: reindent
Standard Emacs shell-mode 4-space indent.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-09-18 06:38:59 +02:00
Joachim Wiberg efed0db16b test: reindent, don't warn on PID 0
PID 0 for a collected task is not a bug, 1 or < 0 is a bug.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-09-16 10:28:48 +02:00
Joachim Wiberg 11946f12d3 contrib: disable bundled watchdog for Alpine builds
In the Alpine reference builds we use 'watchdog' from the BusyBox suite.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-09-16 10:28:48 +02:00
Joachim Wiberg 2ba359ed80 Merge pull request #365 from markand/man-typo 2023-09-15 12:31:14 +02:00
David Demelier fafd524701 doc: fix typo in finit.8 manual page 2023-09-15 10:50:31 +02:00
Joachim Wiberg 1ee6c9f46b watchdogd: drop startup message, leaks to console
We use LOG_CONS to ensure log messages reach the operator, but since
watchdogd starts very early this means non-critical messages like the
initial greeting leaks to console because syslogd has not yet started.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-09-15 09:47:42 +02:00
Joachim Wiberg a88eb82a68 Simplify overly complex description, drop links to older versions
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-09-14 10:03:49 +02:00
Joachim Wiberg a436a1c8cb .github: speed up release job, and support for setting pre-release
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-09-14 09:40:55 +02:00
58 changed files with 682 additions and 451 deletions

No files matched your search

+13
View File
@@ -10,12 +10,24 @@ jobs:
name: Build and upload release tarball name: Build and upload release tarball
if: startsWith(github.ref, 'refs/tags/') if: startsWith(github.ref, 'refs/tags/')
runs-on: ubuntu-latest runs-on: ubuntu-latest
env:
MAKEFLAGS: -j3
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- name: Installing dependencies ... - name: Installing dependencies ...
run: | run: |
sudo apt-get -y update sudo apt-get -y update
sudo apt-get -y install pkg-config jq libuev-dev libite-dev sudo apt-get -y install pkg-config jq libuev-dev libite-dev
- name: Setting release variables ...
id: build
run: |
ver=${GITHUB_REF#refs/tags/}
echo "ver=${ver}" >> $GITHUB_OUTPUT
if echo $ver | grep -qE '[0-9.]+(-alpha|-beta|-rc)[0-9]*'; then
echo "pre=true" >> $GITHUB_OUTPUT
else
echo "pre=false" >> $GITHUB_OUTPUT
fi
- name: Creating Makefiles ... - name: Creating Makefiles ...
run: | run: |
./autogen.sh ./autogen.sh
@@ -36,5 +48,6 @@ jobs:
- uses: ncipollo/release-action@v1 - uses: ncipollo/release-action@v1
with: with:
name: Finit v${{ github.ref_name }} name: Finit v${{ github.ref_name }}
prerelease: ${{ needs.build.outputs.pre }}
bodyFile: "release.md" bodyFile: "release.md"
artifacts: "artifacts/*" artifacts: "artifacts/*"
+18 -5
View File
@@ -4,19 +4,21 @@ Change Log
All relevant changes are documented in this file. All relevant changes are documented in this file.
[4.5][] - 2023-09-15 [4.5][] - 2023-10-03
-------------------- --------------------
### Changes ### Changes
- Refactor `runparts` and `/etc/rc.local` to no longer block the main - Refactor `runparts` and `/etc/rc.local` to no longer block the main
loop, allowing these scripts to call `initctl` to interact with Finit. loop, allowing `initctl` calls to interact with Finit. Issue #356
Still in a limited way due to them being used at bootstrap, issue #356
- Refactor the `run` stanza to no longer block the main loop, issue #362 - Refactor the `run` stanza to no longer block the main loop, issue #362
- Allow `sulogin` with a user different from `root`, issue #357 - Allow `sulogin` with a user different from `root`, issue #357
- Allow disabling invocation of rescue mode from kernel command line - Allow disabling invocation of rescue mode from kernel command line
- Add `initctl -f` to force-skip asking Finit for existing services - Add `initctl -f` to force-skip asking Finit for existing services
when creating new services during bootstrap, e.g. `/etc/rc.local` when creating new services during bootstrap, e.g. `/etc/rc.local`
- `initctl runlevel` now returns `N S` instead of `N 10` in bootstrap - `initctl runlevel` now returns `N S` instead of `N 10` in bootstrap
- `initctl runlevel N` during bootstrap is now allowed. It changes
the next runlevel to go to when bootstrap has completed. Effectively
overriding the `runlevel N` statement in `/etc/finit.conf`
- Improved logging on failure to `execvp()` a run/task/service, now - Improved logging on failure to `execvp()` a run/task/service, now
with `errno`, e.g., "No such file or directory" when the command with `errno`, e.g., "No such file or directory" when the command
is missing from `$PATH` is missing from `$PATH`
@@ -25,20 +27,31 @@ All relevant changes are documented in this file.
- Update `finit.conf(5)` man page with the recommended directory - Update `finit.conf(5)` man page with the recommended directory
hierarchy in `/etc/finit.d/` hierarchy in `/etc/finit.d/`
- The `runparts` code has been split into `/libexec/finit/runparts` - The `runparts` code has been split into `/libexec/finit/runparts`
- The `runparts` command now takes two options: `sysv` and `progress`.
The former ensures only `SNNfoo` and `KNNfoo` scripts are run.
- Add SysV Init Compatibility section to documentation - Add SysV Init Compatibility section to documentation
- Increased MAX path for commands, and arguments: 64 -> 256 - Increased MAX path for commands, and arguments: 64 -> 256
- The bundled watchdog daemon no longer tries to log at startup, because
syslog is not available yet, any startup message leak to console
- Extend `if:` option with runtime evaluation of conditions. E.g., start
a task only `if:<run/foo/failure>` (here the run task 'foo' failed)
- Document new `if:`, `conflict:`, `nowarn` options for run/task/service
first introduced in v4.4
### Fixes ### Fixes
- Fix #227: believed to have been fixed in [4.3][], the root cause was - Fix #227: believed to have been fixed in v4.3, the root cause was
actually that Finit was waiting for a process that was no longer in actually that Finit was waiting for a process that was no longer in
the system. The fix is to ask the kernel on process-stop-timeout and the system. The fix is to ask the kernel on process-stop-timeout and
replay the lost PID so that Finit can continue with reboot/shutdown replay the lost PID so that Finit can continue with reboot/shutdown
- Fix #358: fix inotify events for `/etc/finit.conf`, improved log - Fix #358: fix inotify events for `/etc/finit.conf`, improved log
messages and error handling messages and error handling
- Fix #361: cgroup move fail if run/task/services start as non-root. - Fix #361: cgroup move fail if run/task/services start as non-root.
Regression in the [4.4][] release cycle while adding support for the Regression in the v4.4 release cycle while adding support for the
pre:/post:/ready: scripts. Now the latter scripts also properly run pre:/post:/ready: scripts. Now the latter scripts also properly run
in their correct cgroup in their correct cgroup
- Fix #366: document `fsck.*` kernel command line options and simplify
the configure flags `--enable-fsckfix` and `--enable-fastboot` to
only adjust the default values for the `fsck.*` options.
- The `runparts` executor now skips backup files (`foo~`) - The `runparts` executor now skips backup files (`foo~`)
- The `runparts` stanza now properly appends ` start` to scripts that - The `runparts` stanza now properly appends ` start` to scripts that
start with `S[0-9]+`. This has been broken for a very long time. start with `S[0-9]+`. This has been broken for a very long time.
+2 -1
View File
@@ -1,4 +1,5 @@
AC_INIT([Finit],[4.5-rc2],[https://github.com/troglobit/finit/issues],[finit],[https://troglobit.com/projects/finit/]) AC_INIT([Finit], [4.5-rc4], [https://github.com/troglobit/finit/issues],
[finit], [https://troglobit.com/projects/finit/])
AC_CONFIG_AUX_DIR(aux) AC_CONFIG_AUX_DIR(aux)
AM_INIT_AUTOMAKE([1.11 foreign dist-xz subdir-objects]) AM_INIT_AUTOMAKE([1.11 foreign dist-xz subdir-objects])
AM_SILENT_RULES([yes]) AM_SILENT_RULES([yes])
+1 -1
View File
@@ -17,7 +17,7 @@ PKG_CONFIG_LIBDIR=/usr/lib/pkgconfig:/usr/local/lib/pkgconfig ./configure \
--prefix=/usr --exec-prefix= \ --prefix=/usr --exec-prefix= \
--sysconfdir=/etc --localstatedir=/var \ --sysconfdir=/etc --localstatedir=/var \
--enable-dbus-plugin --enable-x11-common-plugin \ --enable-dbus-plugin --enable-x11-common-plugin \
--enable-alsa-utils-plugin --with-watchdog \ --enable-alsa-utils-plugin --without-watchdog \
--with-keventd --with-sulogin --with-keventd --with-sulogin
echo echo
-10
View File
@@ -9,16 +9,6 @@ value in the project turned out to be:
> systems, container, and dedicated server applications. > 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 Misc TODOs
---------- ----------
+9
View File
@@ -12,6 +12,15 @@ The `bool` setting is one of `on, off, true false, 1, 0`.
* `debug`: Enable kernel debug. Debug messages are printed to the * `debug`: Enable kernel debug. Debug messages are printed to the
console until Finit starts up, unless `loglevel=7` (below) is used. console until Finit starts up, unless `loglevel=7` (below) is used.
* `fsck.mode=<auto,force,skip>`, default: `auto`, unless built with
`configure --enable-fastboot`, in which case the default is `skip`
* `fsck.repair=<preen,yes,no>`, default: `preen`, unless built with
`configure --enable-fsckfix`, in which case the default is `yes`.
This configure option also sets `fsck.mode=force`, unless fastboot
is selected at the same time. I.e., the `--enable-fastboot` build
option overrides the `fsck.mode` default value.
* `finit.cond=foo[,bar[,baz]]`: set `<boot/foo>` condition, optionally * `finit.cond=foo[,bar[,baz]]`: set `<boot/foo>` condition, optionally
multiple conditions can be set using the same option, separated with a multiple conditions can be set using the same option, separated with a
comma. Alternatively, multiple `foo.cond=arg` can be given. Each will comma. Alternatively, multiple `foo.cond=arg` can be given. Each will
+97 -27
View File
@@ -164,14 +164,19 @@ everything is OK.
task [S] /lib/console-setup/console-setup.sh task [S] /lib/console-setup/console-setup.sh
service [S12345] env:-/etc/default/rsyslog rsyslogd -n $RSYSLOGD_ARGS service [S12345] env:-/etc/default/rsyslog rsyslogd -n $RSYSLOGD_ARGS
After runlevel S, Finit proceeds to runlevel 2. (This can be changed in After runlevel S, Finit proceeds to runlevel 2. This can be changed in
`/etc/finit.conf` using the `runlevel N` directive.) Before starting `/etc/finit.conf` using the `runlevel N` directive, or by a script
the services in runlevel 2, Finit first stops everything that is not running in runlevel S that calls, e.g., `initctl runlevel 9`. The
allowed to run in 2, and then brings up networking. Networking is latter is useful if startup scripts detect problems outside of Finit's
expected to be available in all runlevels except: S, 1 (single user control, e.g., critical services/devices missing or hardware problems.
level), 6, and 0. Networking is enabled either by the `network script`
directive, or if you have an `/etc/network/interfaces` file, Finit calls Before starting the services in runlevel 2, Finit first stops everything
`ifup -a` -- at the very least the loopback interface is brought up. that is not allowed to run in 2, and then brings up networking.
Networking is expected to be available in all runlevels except: S, 1
(single user level), 6, and 0. Networking is enabled either by the
`network script` directive, or if you have an `/etc/network/interfaces`
file, Finit calls `ifup -a` -- at the very least the loopback interface
is brought up.
> **Note:** when moving from runlevel S to 2, all run/task/services that > **Note:** when moving from runlevel S to 2, all run/task/services that
> were constrained to runlevel S only are dropped from bookkeeping. So > were constrained to runlevel S only are dropped from bookkeeping. So
@@ -839,10 +844,75 @@ These script actions *must terminate*, so they have a default execution
time of 3 seconds before they are SIGKILLed, this can be adjusted using time of 3 seconds before they are SIGKILLed, this can be adjusted using
the above `kill:SEC` syntax. the above `kill:SEC` syntax.
#### Conditional Loading
Finit support conditional loading of stanzas. The following example is
take from the `system/hotplug.conf` file in the Finit distribution.
Here we only show a simplified subset.
Starting with the `nowarn` option.
service nowarn name:udevd pid:udevd /lib/systemd/systemd-udevd
service nowarn name:udevd pid:udevd udevd
When loading the .conf file Finit looks for `/lib/systemd/systemd-udevd`
if that is not found Finit automatically logs a warning. The `nowarn`
option disables this warning so that the second line can be evaluated,
which also provides a service named `udevd`.
run nowarn if:udevd <pid/udevd> udevadm settle -t 0
This line is only loaded if we know of a service named `udevd`. Again,
we do not warn if `udevadm` is not found, Execution will also stop here
until the PID condition is asserted, i.e., Finit detecting udevd has
started.
run nowarn conflict:udevd [S] mdev -s -- Populating device tree
If `udevd` is not available, we try to run `mdev`, but if that is not
found, again we do not warn.
Conditional loading statements can also be negated, so the previous stanza
can also be written as:
run nowarn if:!udevd [S] mdev -s -- Populating device tree
The reason for using `confict` in this example is that a conflict can be
resolved. Stanzas marked with `conflict:foo` are rechecked at runtime.
#### Conditional Execution
Similar to conditional loading of stanzas there is conditional runtime
execution. This can be confusing at first, since Finit already has a
condition subsystem, but this is more akin to the qualification to a
runlevel. E.g., a `task [123]` is qualified to run only in runlevel 1,
2, and 3. It is not considered for other runlevels.
Conditional execution qualify a run/task/service based on a condition.
Consider this (simplified) example from the Infix operating system:
run [S] name:startup <pid/sysrepo> confd -b --load startup-config
run [S] if:<usr/fail-startup> name:failure <pid/sysrepo> confd --load failure-config
The two run statements reside in the same .conf file so Finit runs them
in true sequence. If loading the file `startup-config` fails confd sets
the condition `usr/fail-startup`, thus allowing the next run statement
to load `failure-config`.
Notice critical the difference between `<pid/sysrepo>` condition and
`if:<usr/fail-startup>`. The former is a condition for starting and the
latter is a condition to check if a run/task/service is qualified to
even be considered.
Conditional execution statements can also be negated, so provided the
file loaded did the opposite, i.e., set a condition on success, the
previous stanza can also be written as:
run [S] if:<!usr/startup-ok> name:failure <pid/sysrepo> confd ...
### Run-parts Scripts ### Run-parts Scripts
**Syntax:** `runparts <DIR>` **Syntax:** `runparts [progress] [sysv] <DIR>`
Call [run-parts(8)][] on `DIR` to run start scripts. All executable Call [run-parts(8)][] on `DIR` to run start scripts. All executable
files, or scripts, in the directory are called, in alphabetic order. files, or scripts, in the directory are called, in alphabetic order.
@@ -854,25 +924,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 whatever the next runlevel is set to be (default 2). E.g., generate a
`/etc/chrony.conf` and call `initctl enable chronyd`. `/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:** **Limitations:**
Scripts called from `runparts`, or hook scripts (see below), are limited Scripts called from `runparts`, or hook scripts (see below), are limited
in what they can do and expect from Finit: in their interaction with Finit. Like the standalone `run` stanza and
the `/etc/rc.local` shell script, Finit waits for their completion
1. Finit is single threaded and all scripts executed from these two before continuing. None of them can issue commands to start, stop, or
mechanisms are limited to file system operations (early or late restart other services. Also, ensure all your services and programs
hooks may not have write access!) and standard UNIX programs. either terminate or start in the background or you will block Finit.
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.
> **Note:** `runparts` scrips are only read and executed in runlevel S > **Note:** `runparts` scrips are only read and executed in runlevel S
> ([bootstrap][]). See [hook scripts](plugins.md#hooks) for other ways > ([bootstrap][]). See [hook scripts](plugins.md#hooks) for other ways
@@ -1073,8 +1141,10 @@ sync(2) has been called, twice.
SysV Init Compatibility SysV Init Compatibility
----------------------- -----------------------
Finit comes with a few SysV Init compatibility features to ease the It is not possible to run unmodified SysV init systems with Finit. This
transition from a serialized boot process. 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` ### `runparts DIRECTORY`
+1 -1
View File
@@ -275,7 +275,7 @@ The following condition families are available today:
Linux netlink events, e.g. net/route/default, net/eth0/up, and Linux netlink events, e.g. net/route/default, net/eth0/up, and
net/et0/running net/et0/running
.It Cm pid .It Cm pid
PID files basd on the service declaration PID files based on the service declaration
.Cm name:id , .Cm name:id ,
gives the condition pid/name:id gives the condition pid/name:id
.It Cm service .It Cm service
+5
View File
@@ -240,6 +240,11 @@ Show top-like listing based on cgroups.
List installed plugins. List installed plugins.
.It Nm Ar runlevel Op Ar 0-9 .It Nm Ar runlevel Op Ar 0-9
Show or set runlevel: 0 halt, 6 reboot. Show or set runlevel: 0 halt, 6 reboot.
.Pp
If called at boot (runlevel S) to set the runlevel, Finit only schedules
the change, effectively overriding the configured runlevel from
.Pa /etc/finit.conf .
Useful to trigger a fail-safe mode, or similar.
.It Nm Ar reboot .It Nm Ar reboot
Reboot system, default if Reboot system, default if
.Cm reboot .Cm reboot
+1 -1
View File
@@ -45,7 +45,7 @@ static void setup(void *arg)
touch("/etc/resolvconf/run/enable-updates"); touch("/etc/resolvconf/run/enable-updates");
chdir("/etc/resolvconf/run/interface"); 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("/"); chdir("/");
} }
+15 -3
View File
@@ -367,7 +367,6 @@ static void api_cb(uev_t *w, void *arg, int events)
} }
switch (rq.cmd) { switch (rq.cmd) {
case INIT_CMD_RUNLVL:
case INIT_CMD_RELOAD: case INIT_CMD_RELOAD:
case INIT_CMD_START_SVC: case INIT_CMD_START_SVC:
case INIT_CMD_RESTART_SVC: case INIT_CMD_RESTART_SVC:
@@ -378,7 +377,7 @@ static void api_cb(uev_t *w, void *arg, int events)
case INIT_CMD_POWEROFF: case INIT_CMD_POWEROFF:
case INIT_CMD_SUSPEND: case INIT_CMD_SUSPEND:
if (IS_RESERVED_RUNLEVEL(runlevel)) { if (IS_RESERVED_RUNLEVEL(runlevel)) {
warnx("Unsupported command in runlevel S and 6."); warnx("Unsupported command in runlevel S and 6/0.");
goto leave; goto leave;
} }
default: default:
@@ -387,6 +386,14 @@ static void api_cb(uev_t *w, void *arg, int events)
switch (rq.cmd) { switch (rq.cmd) {
case INIT_CMD_RUNLVL: case INIT_CMD_RUNLVL:
/* Allow changing cfglevel in runlevel S */
if (IS_RESERVED_RUNLEVEL(runlevel)) {
if (runlevel != INIT_LEVEL) {
warnx("Cannot abort runlevel 6/0.");
break;
}
}
switch (rq.runlevel) { switch (rq.runlevel) {
case 's': case 's':
case 'S': case 'S':
@@ -400,7 +407,12 @@ static void api_cb(uev_t *w, void *arg, int events)
halt = SHUT_OFF; halt = SHUT_OFF;
if (lvl == 6) if (lvl == 6)
halt = SHUT_REBOOT; halt = SHUT_REBOOT;
service_runlevel(lvl);
/* User requested change in next runlevel */
if (runlevel == INIT_LEVEL)
cfglevel = lvl;
else
service_runlevel(lvl);
break; break;
default: default:
+38 -1
View File
@@ -62,8 +62,29 @@ static TAILQ_HEAD(, env_entry) env_list = TAILQ_HEAD_INITIALIZER(env_list);
struct rlimit initial_rlimit[RLIMIT_NLIMITS]; struct rlimit initial_rlimit[RLIMIT_NLIMITS];
struct rlimit global_rlimit[RLIMIT_NLIMITS]; struct rlimit global_rlimit[RLIMIT_NLIMITS];
/*
* --enable-fastboot => fsck_mode: NULL => no fsck by default
* --enable-fsckfix => fsck_mode: "-f" + fsck_repair: "y"
*/
#ifdef FSCK_FIX
# ifdef FAST_BOOT
char *fsck_mode = NULL;
# else
char *fsck_mode = "-f";
# endif
char *fsck_repair = "-y";
#else
# ifdef FAST_BOOT
char *fsck_mode = NULL;
# else
char *fsck_mode = ""; char *fsck_mode = "";
# endif
char *fsck_repair = "-p"; 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 */ char cgroup_current[16]; /* cgroup.NAME sets current cgroup for a set of services */
@@ -778,6 +799,15 @@ static int parse_static(char *line, int is_rcsd)
if (BOOTSTRAP && MATCH_CMD(line, "runparts ", x)) { if (BOOTSTRAP && MATCH_CMD(line, "runparts ", x)) {
if (runparts) free(runparts); 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)); runparts = strdup(strip_line(x));
return 0; return 0;
} }
@@ -1463,7 +1493,14 @@ int conf_init(uev_ctx_t *ctx)
*/ */
if (runparts && fisdir(runparts) && !rescue) { if (runparts && fisdir(runparts) && !rescue) {
char conf[sizeof(_PATH_RUNPARTS) + strlen(runparts) + 100]; 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" snprintf(conf, sizeof(conf), "[S] <int/bootstrap> log:console %s %s %s"
" -- Calling runparts %s in the background", " -- Calling runparts %s in the background",
+1 -1
View File
@@ -237,7 +237,7 @@ static void devmon_cb(uev_t *w, void *arg, int events)
continue; continue;
} }
dbg("Got %s", ev->name); // dbg("Got %s", ev->name);
if (ev->mask & (IN_CREATE | IN_DELETE)) if (ev->mask & (IN_CREATE | IN_DELETE))
devmon_update_conds(iwp->path, ev->name, ev->mask); devmon_update_conds(iwp->path, ev->name, ev->mask);
} }
+1 -7
View File
@@ -75,7 +75,6 @@ char *fstab = NULL;
char *sdown = NULL; char *sdown = NULL;
char *network = NULL; char *network = NULL;
char *hostname = NULL; char *hostname = NULL;
char *runparts = NULL;
char *osheading = NULL; char *osheading = NULL;
uev_ctx_t *ctx = NULL; /* Main loop context */ uev_ctx_t *ctx = NULL; /* Main loop context */
@@ -255,11 +254,7 @@ static int fsck(int pass)
continue; continue;
} }
#ifdef FSCK_FIX
snprintf(cmd, sizeof(cmd), "fsck -yf %s", dev);
#else
snprintf(cmd, sizeof(cmd), "fsck %s %s %s", fsck_mode, fsck_repair, dev); snprintf(cmd, sizeof(cmd), "fsck %s %s %s", fsck_mode, fsck_repair, dev);
#endif
dbg("Running pass %d fsck command %s", pass, cmd); dbg("Running pass %d fsck command %s", pass, cmd);
fsck_rc = run_interactive(cmd, "Checking filesystem %s", dev); fsck_rc = run_interactive(cmd, "Checking filesystem %s", dev);
/* /*
@@ -282,7 +277,6 @@ static int fsck(int pass)
static int fsck_all(void) static int fsck_all(void)
{ {
int rc = 0; int rc = 0;
#ifndef FAST_BOOT
int pass; int pass;
if (!fsck_mode) if (!fsck_mode)
@@ -293,7 +287,7 @@ static int fsck_all(void)
if (rc) if (rc)
break; break;
} }
#endif
return rc; return rc;
} }
+1 -1
View File
@@ -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_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_sh (char *tty, int noclear, int nowait, struct rlimit rlimit[]);
pid_t run_bg (char *cmd, char *args[]); 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: * Defaults to user "root" and group "wheel" (root) if:
+2 -2
View File
@@ -230,7 +230,7 @@ void plugin_script_run(hook_point_t no)
} else } else
env[2] = NULL; env[2] = NULL;
run_parts(path, NULL, env, 0); run_parts(path, NULL, env, 0, 0);
} }
#else #else
void plugin_script_run(hook_point_t no) void plugin_script_run(hook_point_t no)
@@ -288,7 +288,7 @@ static void generic_io_cb(uev_t *w, void *arg, int events)
/* Stop watcher, callback may close descriptor on us ... */ /* Stop watcher, callback may close descriptor on us ... */
uev_io_stop(w); uev_io_stop(w);
dbg("Calling I/O %s from runloop...", basename(p->name)); // dbg("Calling I/O %s from runloop...", basename(p->name));
p->io.cb(p->io.arg, w->fd, events); p->io.cb(p->io.arg, w->fd, events);
/* Update fd, may be changed by plugin callback, e.g., if FIFO */ /* Update fd, may be changed by plugin callback, e.g., if FIFO */
+13 -5
View File
@@ -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"); size_t cmdlen = cmd ? strlen(cmd) : strlen("start");
struct dirent **d; struct dirent **d;
@@ -127,6 +127,11 @@ int run_parts(char *dir, char *cmd, const char *env[], int progress)
continue; 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 the callee didn't supply a run_parts() argument */
if (!cmd) { if (!cmd) {
/* Check if S<NUM>service or K<NUM>service notation is used */ /* 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__ #ifndef __FINIT__
static int usage(int rc) static int usage(int rc)
{ {
warnx("usage: runparts [-dh?] DIRECTORY"); warnx("usage: runparts [-dhps?] DIRECTORY");
return rc; return rc;
} }
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
int rc, c, progress = 0; int rc, c, progress = 0, sysv = 0;
char *dir; char *dir;
while ((c = getopt(argc, argv, "dh?p")) != EOF) { while ((c = getopt(argc, argv, "dh?ps")) != EOF) {
switch(c) { switch(c) {
case 'd': case 'd':
debug = 1; debug = 1;
@@ -199,6 +204,9 @@ int main(int argc, char *argv[])
case 'p': case 'p':
progress = 1; progress = 1;
break; break;
case 's':
sysv = 1;
break;
default: default:
return usage(1); return usage(1);
} }
@@ -213,7 +221,7 @@ int main(int argc, char *argv[])
prctl(PR_SET_CHILD_SUBREAPER, 1); prctl(PR_SET_CHILD_SUBREAPER, 1);
rc = run_parts(dir, NULL, NULL, progress); rc = run_parts(dir, NULL, NULL, progress, sysv);
if (rc == -1) if (rc == -1)
err(1, "failed run-parts %s", dir); err(1, "failed run-parts %s", dir);
+11 -7
View File
@@ -836,7 +836,7 @@ static int service_start(svc_t *svc)
fail: fail:
sigprocmask(SIG_SETMASK, &omask, NULL); sigprocmask(SIG_SETMASK, &omask, NULL);
if (do_progress) if (do_progress && !run_block_pid)
print_result(result); print_result(result);
return result; return result;
@@ -1847,11 +1847,6 @@ void service_monitor(pid_t lost, int status)
return; return;
} }
if (lost == run_block_pid) {
svc_mark_clean(svc); /* done, regardless of exit status */
run_block_pid = 0;
}
switch (svc->state) { switch (svc->state) {
case SVC_CLEANUP_STATE: case SVC_CLEANUP_STATE:
case SVC_SETUP_STATE: case SVC_SETUP_STATE:
@@ -1900,6 +1895,13 @@ done:
/* No longer running, update books. */ /* No longer running, update books. */
svc->start_time = svc->pid = 0; svc->start_time = svc->pid = 0;
cont: cont:
if (lost == run_block_pid) {
svc_mark_clean(svc); /* done, regardless of exit status */
run_block_pid = 0;
if (svc->desc[0])
print_result(WIFEXITED(status) ? WEXITSTATUS(status) : 1);
}
if (!service_step(svc)) { if (!service_step(svc)) {
/* Clean out any bootstrap tasks, they've had their time in the sun. */ /* Clean out any bootstrap tasks, they've had their time in the sun. */
if (svc_clean_bootstrap(svc)) if (svc_clean_bootstrap(svc))
@@ -1955,7 +1957,7 @@ void service_mark_unavail(void)
if (!svc->ifstmt[0]) if (!svc->ifstmt[0])
continue; continue;
if (!svc_ifthen(svc_ident(svc, buf, sizeof(buf)), svc->ifstmt)) if (!svc_ifthen(1, svc_ident(svc, buf, sizeof(buf)), svc->ifstmt))
svc_mark(svc); svc_mark(svc);
} }
} }
@@ -2294,9 +2296,11 @@ restart:
svc_set_state(svc, SVC_WAITING_STATE); svc_set_state(svc, SVC_WAITING_STATE);
else { else {
if (svc_is_conflict(svc)) { if (svc_is_conflict(svc)) {
#if 0
logit(svc->nowarn ? LOG_DEBUG : LOG_INFO, logit(svc->nowarn ? LOG_DEBUG : LOG_INFO,
"%s in conflict with %s, checking again ...", "%s in conflict with %s, checking again ...",
svc_ident(svc, NULL, 0), svc->conflict); svc_ident(svc, NULL, 0), svc->conflict);
#endif
if (!svc_conflicts(svc)) if (!svc_conflicts(svc))
svc_unblock(svc); svc_unblock(svc);
} }
+27 -11
View File
@@ -634,17 +634,30 @@ int svc_enabled(svc_t *svc)
if (!svc) if (!svc)
return 0; return 0;
if (!svc_in_runlevel(svc, runlevel)) if (!svc_in_runlevel(svc, runlevel)) {
// dbg("Not in runlevel");
return 0; return 0;
}
if (svc_is_removed(svc) || svc_is_blocked(svc)) if (svc_is_removed(svc) || svc_is_blocked(svc)) {
// dbg("removed (%d) / blocked (%d)", svc->removed, svc->block);
return 0; return 0;
}
if (svc_is_missing(svc)) if (svc_is_missing(svc)) {
// dbg("missing");
return 0; return 0;
}
if (svc_is_tty(svc) && bootstrap) if (!svc_ifthen(0, NULL, svc->ifstmt)) {
// dbg("ifthen:%s>", svc->ifstmt[0] ? svc->ifstmt : "<");
return 0; return 0;
}
if (svc_is_tty(svc) && bootstrap) {
// dbg("is tty in bootstrap");
return 0;
}
return 1; return 1;
} }
@@ -688,13 +701,14 @@ int svc_conflicts(svc_t *svc)
/** /**
* svc_ifthen - Check if: statement in declaration * svc_ifthen - Check if: statement in declaration
* @is_conf: Set when called by service_mark_unavail()
* @ident: svc_t identififcation (name:id) * @ident: svc_t identififcation (name:id)
* @stmt: if: statement from .conf file * @stmt: if: statement from .conf file
* *
* Returns: * Returns:
* %TRUE(1) yes, use this svc_t, %FALSE(0) prune * %TRUE(1) yes, use this svc_t, %FALSE(0) prune
*/ */
int svc_ifthen(const char *ident, char *stmt) int svc_ifthen(int is_conf, const char *ident, char *stmt)
{ {
int not = 0; int not = 0;
svc_t *svc; svc_t *svc;
@@ -707,6 +721,9 @@ int svc_ifthen(const char *ident, char *stmt)
char *ptr = ++stmt; char *ptr = ++stmt;
int i = 0; int i = 0;
if (is_conf)
return 1;
if (stmt[0] == '!') { if (stmt[0] == '!') {
stmt++; stmt++;
not++; not++;
@@ -717,17 +734,16 @@ int svc_ifthen(const char *ident, char *stmt)
ptr[i] = 0; ptr[i] = 0;
cond = cond_get(stmt); cond = cond_get(stmt);
if (not && cond == COND_ON) { if (not && cond == COND_ON)
logit(LOG_NOTICE, "skipping %s, cond %s is on.", ident, stmt);
return 0; return 0;
} if (!not && cond == COND_OFF)
if (!not && cond == COND_OFF) {
logit(LOG_NOTICE, "skipping %s, cond %s is off.", ident, stmt);
return 0; return 0;
}
return 1; return 1;
} }
if (!is_conf)
return 1;
if (stmt[0] == '!') { if (stmt[0] == '!') {
stmt++; stmt++;
not++; not++;
+1 -1
View File
@@ -241,7 +241,7 @@ void svc_prune_bootstrap (void);
void svc_enable (svc_t *svc); void svc_enable (svc_t *svc);
int svc_enabled (svc_t *svc); int svc_enabled (svc_t *svc);
int svc_conflicts (svc_t *svc); int svc_conflicts (svc_t *svc);
int svc_ifthen (const char *ident, char *ifstm); int svc_ifthen (int is_conf, const char *ident, char *stmt);
int svc_parse_jobstr (char *str, size_t len, void *user_data, int (*found)(svc_t *, void *), int (not_found)(char *, char *, void *)); int svc_parse_jobstr (char *str, size_t len, void *user_data, int (*found)(svc_t *, void *), int (not_found)(char *, char *, void *));
-1
View File
@@ -60,7 +60,6 @@ static int init(char *progname, char *devnode)
signal(SIGPWR, sighandler); signal(SIGPWR, sighandler);
openlog(&progname[1], LOG_CONS | LOG_PID, LOG_DAEMON); openlog(&progname[1], LOG_CONS | LOG_PID, LOG_DAEMON);
syslog(LOG_INFO, "Finit v%s watchdog %s starting ...", VERSION, devnode);
fd = open(devnode, O_WRONLY); fd = open(devnode, O_WRONLY);
if (fd == -1) if (fd == -1)
+6 -1
View File
@@ -2,9 +2,12 @@ SUBDIRS = lib src
EXTRA_DIST = skel/bin/busybox-x86_64.sha256 skel/sbin/service.sh skel/etc/env \ 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/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/foo.sh skel/etc/rc.d/S01abc.sh \
skel/etc/rc.d/test.sh skel/etc/rc.d/S02def.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/cdrom/.empty skel/dev/shm/.empty skel/dev/pts/.empty \
skel/etc/inittab skel/etc/hostname skel/etc/fstab \ skel/etc/inittab skel/etc/hostname skel/etc/fstab \
skel/etc/init.d/rcS skel/etc/init.d/rcK skel/tmp/.empty \ 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-restart-forever.sh
EXTRA_DIST += run-task-tricks.sh EXTRA_DIST += run-task-tricks.sh
EXTRA_DIST += runparts.sh EXTRA_DIST += runparts.sh
EXTRA_DIST += sysvparts.sh
EXTRA_DIST += start-stop-service.sh EXTRA_DIST += start-stop-service.sh
EXTRA_DIST += start-stop-service-sub-config.sh EXTRA_DIST += start-stop-service-sub-config.sh
EXTRA_DIST += start-kill-service.sh EXTRA_DIST += start-kill-service.sh
@@ -80,6 +84,7 @@ TESTS += rclocal.sh
TESTS += ready-serv.sh TESTS += ready-serv.sh
TESTS += restart-self.sh TESTS += restart-self.sh
TESTS += runlevel.sh TESTS += runlevel.sh
TESTS += sysvparts.sh
TESTS += run-restart-forever.sh TESTS += run-restart-forever.sh
TESTS += run-task-tricks.sh TESTS += run-task-tricks.sh
TESTS += runparts.sh TESTS += runparts.sh
@@ -6,10 +6,10 @@ TEST_DIR=$(dirname "$0")
test_teardown() test_teardown()
{ {
say "Test done $(date)" say "Test done $(date)"
say "Running test teardown." say "Running test teardown."
run "rm -f $FINIT_RCSD/service.conf" run "rm -f $FINIT_RCSD/service.conf"
} }
# shellcheck source=/dev/null # shellcheck source=/dev/null
+3 -3
View File
@@ -6,10 +6,10 @@ TEST_DIR=$(dirname "$0")
test_teardown() test_teardown()
{ {
say "Test done $(date)" say "Test done $(date)"
say "Running test teardown." say "Running test teardown."
run "rm -f $FINIT_CONF" run "rm -f $FINIT_CONF"
} }
# shellcheck source=/dev/null # shellcheck source=/dev/null
+53 -53
View File
@@ -9,77 +9,77 @@ TEST_DIR=$(dirname "$0")
test_setup() test_setup()
{ {
say "Test start $(date)" say "Test start $(date)"
} }
test_teardown() test_teardown()
{ {
say "Test done $(date)" say "Test done $(date)"
say "Running test teardown." say "Running test teardown."
run "rm -f $TEST_CONF" run "rm -f $TEST_CONF"
} }
test_one() test_one()
{ {
cond=$1 cond=$1
stanza=$2 stanza=$2
sleep 5 sleep 5
say 'Enable finit debug, try to figure out what is going on ...' say 'Enable finit debug, try to figure out what is going on ...'
run "initctl debug" run "initctl debug"
say "Add stanza '$stanza' to $TEST_CONF ..." say "Add stanza '$stanza' to $TEST_CONF ..."
run "echo '$stanza' > $TEST_CONF" run "echo '$stanza' > $TEST_CONF"
run "ls -l /run/ /run/finit/" run "ls -l /run/ /run/finit/"
say 'Reload Finit' say 'Reload Finit'
run "initctl ls" run "initctl ls"
run "initctl reload" run "initctl reload"
run "initctl status" run "initctl status"
run "ps" run "ps"
date date
sleep 2 sleep 2
date date
run "ls -l /run/ /run/finit/" run "ls -l /run/ /run/finit/"
say 'Asserting condition' say 'Asserting condition'
run "initctl cond set $cond" run "initctl cond set $cond"
date date
sleep 2 sleep 2
date date
run "ls -l /run/ /run/finit/" run "ls -l /run/ /run/finit/"
run "initctl status" run "initctl status"
run "ps" run "ps"
run "initctl status task.sh" run "initctl status task.sh"
sleep 1 sleep 1
run "echo Hej; cat /run/task.state" run "echo Hej; cat /run/task.state"
assert_file_contains /run/task.state 1 assert_file_contains /run/task.state 1
say 'Reload Finit' say 'Reload Finit'
run "initctl reload" run "initctl reload"
sleep 1 sleep 1
say 'Ensure task has not run again ...' say 'Ensure task has not run again ...'
assert_file_contains /run/task.state 1 assert_file_contains /run/task.state 1
say 'Switch to another runlevel ...' say 'Switch to another runlevel ...'
run "initctl runlevel 3" run "initctl runlevel 3"
sleep 1 sleep 1
say 'Ensure task has run again ...' say 'Ensure task has run again ...'
assert_file_contains /run/task.state 2 assert_file_contains /run/task.state 2
say 'Touch task.sh .conf file and reload Finit ...' say 'Touch task.sh .conf file and reload Finit ...'
run "touch $TEST_CONF" run "touch $TEST_CONF"
run "initctl reload" run "initctl reload"
sleep 1 sleep 1
# run "initctl status task.sh" # run "initctl status task.sh"
assert_file_contains /run/task.state 3 assert_file_contains /run/task.state 3
say "Done, drop stanza from $TEST_CONF ..." say "Done, drop stanza from $TEST_CONF ..."
run "rm $TEST_CONF" run "rm $TEST_CONF"
run "initctl reload" run "initctl reload"
} }
+33 -33
View File
@@ -7,57 +7,57 @@ TEST_DIR=$(dirname "$0")
test_setup() test_setup()
{ {
say "Test start $(date)" say "Test start $(date)"
} }
test_teardown() test_teardown()
{ {
say "Test done $(date)" say "Test done $(date)"
say "Running test teardown." say "Running test teardown."
run "rm -f $FINIT_CONF" "/tmp/post" run "rm -f $FINIT_CONF" "/tmp/post"
} }
crashit() crashit()
{ {
nm=$1 nm=$1
say 'Simulate service crash (kill -9 ..)' say 'Simulate service crash (kill -9 ..)'
i=0 i=0
laps=100 laps=100
while [ $i -lt $laps ]; do while [ $i -lt $laps ]; do
i=$((i + 1)) i=$((i + 1))
say "Lap $i/$laps, killing service $nm ..." # we have this, no sleep needed say "Lap $i/$laps, killing service $nm ..." # we have this, no sleep needed
if ! run "slay $nm"; then if ! run "slay $nm"; then
break; break;
fi fi
done done
} }
test_one() test_one()
{ {
type=$1 type=$1
shift shift
nm=$1 nm=$1
shift shift
args=$* args=$*
say "Add service stanza in $FINIT_CONF" say "Add service stanza in $FINIT_CONF"
run "echo service log:stderr oncrash:script post:/bin/post.sh $nm $args > $FINIT_CONF" run "echo service log:stderr oncrash:script post:/bin/post.sh $nm $args > $FINIT_CONF"
say 'Reload Finit' say 'Reload Finit'
run "initctl reload" run "initctl reload"
if [ "$type" = "sig" ]; then if [ "$type" = "sig" ]; then
retry "assert_num_children 1 $nm" retry "assert_num_children 1 $nm"
run "initctl status $nm" run "initctl status $nm"
crashit "$nm" crashit "$nm"
fi fi
retry "assert_status $nm crashed" 500 retry "assert_status $nm crashed" 500
run "cat /tmp/post" run "cat /tmp/post"
assert_file_contains "/tmp/post" "POST" assert_file_contains "/tmp/post" "POST"
run "rm -f /tmp/post" run "rm -f /tmp/post"
} }
# shellcheck source=/dev/null # shellcheck source=/dev/null
+30 -30
View File
@@ -16,15 +16,15 @@ TEST_DIR=$(dirname "$0")
test_setup() test_setup()
{ {
say "Test start $(date)" say "Test start $(date)"
} }
test_teardown() test_teardown()
{ {
say "Test done $(date)" say "Test done $(date)"
say "Running test teardown." say "Running test teardown."
run "rm -f $FINIT_CONF" "/tmp/post" run "rm -f $FINIT_CONF" "/tmp/post"
} }
# shellcheck source=/dev/null # shellcheck source=/dev/null
@@ -35,36 +35,36 @@ test_teardown()
test_one() test_one()
{ {
cond=$1 cond=$1
say "Verifying foo -> <$cond> bar ..." say "Verifying foo -> <$cond> bar ..."
run "echo service log:stderr name:foo serv -np -i foo -f /tmp/arrakis > $FINIT_CONF" run "echo service log:stderr name:foo serv -np -i foo -f /tmp/arrakis > $FINIT_CONF"
run "echo service log:stderr name:bar \<!$cond\> serv -np -i bar -F /tmp/arrakis >> $FINIT_CONF" run "echo service log:stderr name:bar \<!$cond\> serv -np -i bar -F /tmp/arrakis >> $FINIT_CONF"
run "cat $FINIT_CONF" run "cat $FINIT_CONF"
say 'Reload Finit' say 'Reload Finit'
run "initctl reload" run "initctl reload"
run "initctl status" run "initctl status"
assert_status "foo" "running" assert_status "foo" "running"
assert_cond "$cond" assert_cond "$cond"
assert_status "bar" "running" assert_status "bar" "running"
say "Verify bar is restarted when foo is ..." say "Verify bar is restarted when foo is ..."
pid=$(texec initctl |grep bar | awk '{print $1;}') pid=$(texec initctl |grep bar | awk '{print $1;}')
run "initctl restart foo" run "initctl restart foo"
run "initctl status" run "initctl status"
assert "bar is restarted" "$(texec initctl |grep bar | awk '{print $1;}')" != "$pid" assert "bar is restarted" "$(texec initctl |grep bar | awk '{print $1;}')" != "$pid"
# Wait for spice to be stolen by the Harkonnen # Wait for spice to be stolen by the Harkonnen
sleep 3 sleep 3
# bar should now have detected the loss of spice and be in restart # bar should now have detected the loss of spice and be in restart
run "initctl status" run "initctl status"
assert_status "bar" "restart" assert_status "bar" "restart"
# verify bar is stopped->waiting and no longer in restart after stopping foo # verify bar is stopped->waiting and no longer in restart after stopping foo
run "initctl stop foo" run "initctl stop foo"
run "initctl status" run "initctl status"
run "initctl status bar" run "initctl status bar"
assert_status "bar" "waiting" assert_status "bar" "waiting"
} }
sep sep
+22 -22
View File
@@ -9,52 +9,52 @@ TEST_DIR=$(dirname "$0")
test_setup() test_setup()
{ {
say "Test start $(date)" say "Test start $(date)"
} }
test_teardown() test_teardown()
{ {
say "Test done $(date)" say "Test done $(date)"
say "Running test teardown." say "Running test teardown."
run "rm -f $FINIT_CONF /tmp/post" run "rm -f $FINIT_CONF /tmp/post"
} }
# Cannot run mknod as non-root even in a chroot # Cannot run mknod as non-root even in a chroot
# touch is close enough for our needs # touch is close enough for our needs
mkdev() mkdev()
{ {
dir=$(dirname "$1") dir=$(dirname "$1")
run "mkdir -p $dir" run "mkdir -p $dir"
run "touch $1" run "touch $1"
} }
rmdev() rmdev()
{ {
run "rm $1" run "rm $1"
} }
test_one() test_one()
{ {
cond="$1" cond="$1"
node="/$cond" node="/$cond"
say "Checking cond $cond and device $node ..." say "Checking cond $cond and device $node ..."
run "echo service log:null \<$cond\> serv -np >> $FINIT_CONF" run "echo service log:null \<$cond\> serv -np >> $FINIT_CONF"
run "cat $FINIT_CONF" run "cat $FINIT_CONF"
run "initctl reload" run "initctl reload"
assert_status "serv" "waiting" assert_status "serv" "waiting"
mkdev "$node" mkdev "$node"
assert_status "serv" "running" assert_status "serv" "running"
rmdev "$node" rmdev "$node"
assert_status "serv" "waiting" assert_status "serv" "waiting"
say "Cleaning up ..." say "Cleaning up ..."
run "rm $FINIT_CONF" run "rm $FINIT_CONF"
run "initctl reload" run "initctl reload"
} }
# shellcheck source=/dev/null # shellcheck source=/dev/null
+5 -5
View File
@@ -8,16 +8,16 @@ TEST_DIR=$(dirname "$0")
test_setup() test_setup()
{ {
say "Test start $(date)" say "Test start $(date)"
run "mkdir -p /etc/default" run "mkdir -p /etc/default"
} }
test_teardown() test_teardown()
{ {
say "Test done $(date)" say "Test done $(date)"
say "Running test teardown." say "Running test teardown."
run "rm -f $FINIT_CONF" run "rm -f $FINIT_CONF"
} }
# shellcheck source=/dev/null # shellcheck source=/dev/null
+4 -4
View File
@@ -5,15 +5,15 @@ TEST_DIR=$(dirname "$0")
test_setup() test_setup()
{ {
say "Test start $(date)" say "Test start $(date)"
} }
test_teardown() test_teardown()
{ {
say "Test done $(date)" say "Test done $(date)"
say "Running test teardown." say "Running test teardown."
run "rm -f $FINIT_CONF" run "rm -f $FINIT_CONF"
} }
# shellcheck source=/dev/null # shellcheck source=/dev/null
+8 -8
View File
@@ -9,28 +9,28 @@ TEST_DIR=$(dirname "$0")
test_setup() test_setup()
{ {
say "Test start $(date)" say "Test start $(date)"
} }
test_teardown() test_teardown()
{ {
say "Test done $(date)" say "Test done $(date)"
say "Running test teardown." say "Running test teardown."
run "rm -f $FINIT_CONF" run "rm -f $FINIT_CONF"
} }
test_init() test_init()
{ {
run "echo '# Three foo and one bar enter Finit' > $FINIT_CONF" run "echo '# Three foo and one bar enter Finit' > $FINIT_CONF"
} }
test_add_one() test_add_one()
{ {
service=$1 service=$1
say "Add service stanza '$service' to $FINIT_CONF ..." say "Add service stanza '$service' to $FINIT_CONF ..."
run "echo '$service' >> $FINIT_CONF" run "echo '$service' >> $FINIT_CONF"
} }
# shellcheck source=/dev/null # shellcheck source=/dev/null
+7 -7
View File
@@ -4,10 +4,10 @@ set -eu
cmd="" cmd=""
if [ "$#" -lt 1 ]; then if [ "$#" -lt 1 ]; then
cmd="/bin/sh" cmd="/bin/sh"
else else
cmd=$1 cmd=$1
shift shift
fi fi
TEST_DIR=$(dirname "$0")/.. TEST_DIR=$(dirname "$0")/..
@@ -15,11 +15,11 @@ SYSROOT="${SYSROOT:-$(pwd)/${TEST_DIR}/sysroot}"
PID_FILE="$SYSROOT/running_test.pid" PID_FILE="$SYSROOT/running_test.pid"
if [ -f "$PID_FILE" ] ; then if [ -f "$PID_FILE" ] ; then
target=$(cat "$PID_FILE") target=$(cat "$PID_FILE")
target=$(pgrep -P "$target") target=$(pgrep -P "$target")
else else
echo "No test running!" echo "No test running!"
exit 1 exit 1
fi fi
# shellcheck disable=SC1091 # shellcheck disable=SC1091
+12 -12
View File
@@ -24,9 +24,9 @@
set -eu set -eu
if [ "$#" -lt 2 ]; then if [ "$#" -lt 2 ]; then
echo "Usage:" echo "Usage:"
echo " $0 [target-pid] [command [arguments]]" echo " $0 [target-pid] [command [arguments]]"
exit 1 exit 1
fi fi
target="$1" target="$1"
shift shift
@@ -46,12 +46,12 @@ PATH="$TESTENV_PATH"
export PATH export PATH
"$nsenter" \ "$nsenter" \
--preserve-credentials \ --preserve-credentials \
--user \ --user \
--mount \ --mount \
--uts \ --uts \
--ipc \ --ipc \
--net \ --net \
--pid \ --pid \
-w -t "$target" \ -w -t "$target" \
"$chroot" "$SYSROOT" "$@" "$chroot" "$SYSROOT" "$@"
+8 -8
View File
@@ -342,17 +342,17 @@ echo "Finit running as PID $finit_pid"
i=0 i=0
set +u set +u
while [ -z "$BOOTSTRAP" ] && [ $i -lt 10 ]; do while [ -z "$BOOTSTRAP" ] && [ $i -lt 10 ]; do
lvl=$(texec sh -c "initctl runlevel | awk '{print \$2;}'") lvl=$(texec sh -c "initctl runlevel | awk '{print \$2;}'")
if [ "$lvl" = "$FINIT_RUNLEVEL" ]; then if [ "$lvl" = "$FINIT_RUNLEVEL" ]; then
say "Reached runlevel $FINIT_RUNLEVEL, releasing test." say "Reached runlevel $FINIT_RUNLEVEL, releasing test."
break; break;
fi fi
i=$((i + 1)) i=$((i + 1))
sleep 1 sleep 1
done done
set -u set -u
if type test_setup > /dev/null 2>&1 ; then if type test_setup > /dev/null 2>&1 ; then
test_setup test_setup
fi fi
wdstart $TEST_TIMEOUT wdstart $TEST_TIMEOUT
+18 -18
View File
@@ -8,16 +8,16 @@ TEST_DIR=$(dirname "$0")
test_setup() test_setup()
{ {
say "Test start $(date)" say "Test start $(date)"
run "mkdir -p /etc/default" run "mkdir -p /etc/default"
} }
test_teardown() test_teardown()
{ {
say "Test done $(date)" say "Test done $(date)"
say "Running test teardown." say "Running test teardown."
run "rm -f $FINIT_CONF" run "rm -f $FINIT_CONF"
} }
test_one() test_one()
@@ -37,11 +37,11 @@ test_one()
run "initctl reload" run "initctl reload"
sleep 1 sleep 1
# run "initctl status serv" # run "initctl status serv"
assert_status "serv" "running" assert_status "serv" "running"
sleep 2 sleep 2
# run "initctl cond dump" # run "initctl cond dump"
assert_cond "service/serv/ready" assert_cond "service/serv/ready"
say "Verify 'ready' is set after SIGHUP ..." say "Verify 'ready' is set after SIGHUP ..."
@@ -52,7 +52,7 @@ test_one()
# Issue #343 # Issue #343
say "Verify 'ready' is reasserted if service crashes and is restarted ..." say "Verify 'ready' is reasserted if service crashes and is restarted ..."
# run "initctl status serv" # run "initctl status serv"
run "initctl signal serv 9" run "initctl signal serv 9"
retry 'assert_status "serv" "running"' 2 1 retry 'assert_status "serv" "running"' 2 1
retry 'assert_cond "service/serv/ready"' 3 1 retry 'assert_cond "service/serv/ready"' 3 1
@@ -67,7 +67,7 @@ test_one()
say "Verify 'ready' is reasserted on 'initctl reload' ..." say "Verify 'ready' is reasserted on 'initctl reload' ..."
run "initctl reload" run "initctl reload"
sleep 1 sleep 1
# run "initctl; initctl cond dump" # run "initctl; initctl cond dump"
assert_status "serv" "running" assert_status "serv" "running"
assert_cond "service/serv/ready" assert_cond "service/serv/ready"
@@ -75,12 +75,12 @@ test_one()
# 'started' when they created their PID file. The serv test daemon # 'started' when they created their PID file. The serv test daemon
# waits 3 sec between pidfile and notify to trigger this bug. # waits 3 sec between pidfile and notify to trigger this bug.
if [ "$type" != "native" ]; then if [ "$type" != "native" ]; then
say "Verify 'ready' is *not* asserted immediately on restart + reload" say "Verify 'ready' is *not* asserted immediately on restart + reload"
run "initctl restart serv" run "initctl restart serv"
run "initctl reload" run "initctl reload"
sleep 1 sleep 1
assert_nocond "service/serv/ready" assert_nocond "service/serv/ready"
retry 'assert_cond "service/serv/ready"' 5 0.5 retry 'assert_cond "service/serv/ready"' 5 0.5
fi fi
say "Verify 'ready' is deasserted on stop ..." say "Verify 'ready' is deasserted on stop ..."
@@ -93,9 +93,9 @@ test_one()
run "rm -f $FINIT_CONF" run "rm -f $FINIT_CONF"
run "initctl reload" run "initctl reload"
# sleep 2 # sleep 2
# num=$(run "find /proc/1/fd |wc -l") # num=$(run "find /proc/1/fd |wc -l")
# say "finit: number of open file descriptors after test: $num" # say "finit: number of open file descriptors after test: $num"
} }
# shellcheck source=/dev/null # shellcheck source=/dev/null
+14 -14
View File
@@ -7,32 +7,32 @@ TEST_DIR=$(dirname "$0")
test_setup() test_setup()
{ {
say "Test start $(date)" say "Test start $(date)"
} }
test_teardown() test_teardown()
{ {
say "Test done $(date)" say "Test done $(date)"
say "Running test teardown." say "Running test teardown."
run "rm -f $FINIT_CONF" "/tmp/post" run "rm -f $FINIT_CONF" "/tmp/post"
} }
test_one() test_one()
{ {
pidfn=$1 pidfn=$1
service=$2 service=$2
sep sep
say "Add service stanza '$service' to $FINIT_CONF ..." say "Add service stanza '$service' to $FINIT_CONF ..."
run "echo '$service' > $FINIT_CONF" run "echo '$service' > $FINIT_CONF"
run "initctl reload" run "initctl reload"
assert_is_pidfile "serv" "$pidfn" assert_is_pidfile "serv" "$pidfn"
say "Done, drop service from $FINIT_CONF ..." say "Done, drop service from $FINIT_CONF ..."
run "rm $FINIT_CONF" run "rm $FINIT_CONF"
run "initctl reload" run "initctl reload"
} }
# shellcheck source=/dev/null # shellcheck source=/dev/null
+28 -28
View File
@@ -5,49 +5,49 @@ TEST_DIR=$(dirname "$0")
test_setup() test_setup()
{ {
say "Test start $(date)" say "Test start $(date)"
} }
test_teardown() test_teardown()
{ {
say "Test done $(date)" say "Test done $(date)"
say "Running test teardown." say "Running test teardown."
run "rm -f $FINIT_CONF" run "rm -f $FINIT_CONF"
} }
test_one() test_one()
{ {
pre=$1 pre=$1
precont=$2 precont=$2
service=$3 service=$3
post=$4 post=$4
postcont=$5 postcont=$5
say "Add service stanza '$service' to $FINIT_CONF ..." say "Add service stanza '$service' to $FINIT_CONF ..."
run "echo '$service' > $FINIT_CONF" run "echo '$service' > $FINIT_CONF"
say 'Reload Finit' say 'Reload Finit'
run "initctl reload" run "initctl reload"
retry 'assert_num_children 1 serv' retry 'assert_num_children 1 serv'
if [ -n "$pre" ]; then if [ -n "$pre" ]; then
assert_file_contains "$pre" "$precont" assert_file_contains "$pre" "$precont"
run "rm -f $pre" run "rm -f $pre"
fi fi
say 'Stop the service' say 'Stop the service'
run "initctl stop serv" run "initctl stop serv"
retry 'assert_num_children 0 serv' retry 'assert_num_children 0 serv'
if [ -n "$post" ]; then if [ -n "$post" ]; then
assert_file_contains "$post" "$postcont" assert_file_contains "$post" "$postcont"
run "rm -f $post" run "rm -f $post"
fi fi
say "Done, drop service from $FINIT_CONF ..." say "Done, drop service from $FINIT_CONF ..."
run "rm $FINIT_CONF" run "rm $FINIT_CONF"
run "initctl reload" run "initctl reload"
} }
# shellcheck source=/dev/null # shellcheck source=/dev/null
+2 -2
View File
@@ -12,12 +12,12 @@ RCLOCAL="echo 'KILROY WAS HERE' > /tmp/rclocal"
test_setup() test_setup()
{ {
say "Test start $(date)" say "Test start $(date)"
} }
test_teardown() test_teardown()
{ {
say "Test done $(date)" say "Test done $(date)"
} }
sleep 1 sleep 1
+19 -19
View File
@@ -6,39 +6,39 @@ TEST_DIR=$(dirname "$0")
test_setup() test_setup()
{ {
say "Test start $(date)" say "Test start $(date)"
} }
test_teardown() test_teardown()
{ {
say "Test done $(date)" say "Test done $(date)"
say "Running test teardown." say "Running test teardown."
run "rm -f $FINIT_CONF" run "rm -f $FINIT_CONF"
} }
test_one() test_one()
{ {
service=$1 service=$1
file=/tmp/ready file=/tmp/ready
say "Add service stanza '$service' to $FINIT_CONF ..." say "Add service stanza '$service' to $FINIT_CONF ..."
run "echo '$service' > $FINIT_CONF" run "echo '$service' > $FINIT_CONF"
say 'Reload Finit' say 'Reload Finit'
run "initctl reload" run "initctl reload"
retry 'assert_num_children 1 serv' retry 'assert_num_children 1 serv'
assert_file_contains "$file" "READY" assert_file_contains "$file" "READY"
run "rm -f $file" run "rm -f $file"
say 'Stop the service' say 'Stop the service'
run "initctl stop serv" run "initctl stop serv"
retry 'assert_num_children 0 serv' retry 'assert_num_children 0 serv'
say "Done, drop service from $FINIT_CONF ..." say "Done, drop service from $FINIT_CONF ..."
run "rm $FINIT_CONF" run "rm $FINIT_CONF"
run "initctl reload" run "initctl reload"
} }
# shellcheck source=/dev/null # shellcheck source=/dev/null
+6 -6
View File
@@ -6,21 +6,21 @@ TEST_DIR=$(dirname "$0")
test_setup() test_setup()
{ {
say "Test start $(date)" say "Test start $(date)"
run "mkdir -p /etc/default" run "mkdir -p /etc/default"
} }
test_teardown() test_teardown()
{ {
say "Test done $(date)" say "Test done $(date)"
say "Running test teardown." say "Running test teardown."
run "rm -f $FINIT_CONF" run "rm -f $FINIT_CONF"
} }
check_restarts() check_restarts()
{ {
assert "serv restarts" "$(texec cat "$1" | awk '{print $1;}')" -ge "$2" assert "serv restarts" "$(texec cat "$1" | awk '{print $1;}')" -ge "$2"
} }
+6 -6
View File
@@ -9,17 +9,17 @@ TEST_DIR=$(dirname "$0")
test_setup() test_setup()
{ {
say "Test start $(date)" say "Test start $(date)"
run "mkdir -p /etc/default" run "mkdir -p /etc/default"
export TEST_TIMEOUT=5 export TEST_TIMEOUT=5
} }
test_teardown() test_teardown()
{ {
say "Test done $(date)" say "Test done $(date)"
say "Running test teardown." say "Running test teardown."
run "rm -f $FINIT_CONF" run "rm -f $FINIT_CONF"
} }
# shellcheck source=/dev/null # shellcheck source=/dev/null
+3 -3
View File
@@ -9,12 +9,12 @@ FINIT_RUNLEVEL=9
test_setup() test_setup()
{ {
say "Test start $(date)" say "Test start $(date)"
} }
test_teardown() test_teardown()
{ {
say "Test done $(date)" say "Test done $(date)"
} }
# shellcheck source=/dev/null # shellcheck source=/dev/null
@@ -23,7 +23,7 @@ test_teardown()
say 'Check runlevel' say 'Check runlevel'
lvl=$(run "initctl runlevel | awk '{print \$2;}'") lvl=$(run "initctl runlevel | awk '{print \$2;}'")
if [ "$lvl" -eq "9" ]; then if [ "$lvl" -eq "9" ]; then
return 0 return 0
fi fi
return 1 return 1
+2 -2
View File
@@ -37,5 +37,5 @@ while true; do
sleep 1 sleep 1
done done
texec diff -u /usr/share/runlevel/ref.log /tmp/runparts.log texec diff -u /usr/share/runparts/ref.log /tmp/runparts.log
texec cmp /usr/share/runlevel/ref.log /tmp/runparts.log || fail "runparts in wrong order" texec cmp /usr/share/runparts/ref.log /tmp/runparts.log || fail "runparts in wrong order"
+2 -2
View File
@@ -13,11 +13,11 @@ FINITBIN="$(pwd)/$top_builddir/src/finit" DEST="$SYSROOT" make -f "$srcdir/lib/s
# Drop plugins we don't need in test, only causes confusing FAIL in logs. # Drop plugins we don't need in test, only causes confusing FAIL in logs.
for plugin in tty.so urandom.so rtc.so modprobe.so hotplug.so; do for plugin in tty.so urandom.so rtc.so modprobe.so hotplug.so; do
find "$SYSROOT" -name $plugin -delete find "$SYSROOT" -name $plugin -delete
done done
# Drop system .conf files we don't need in test, same as above # Drop system .conf files we don't need in test, same as above
for conf in hotplug.conf; do for conf in hotplug.conf; do
find "$SYSROOT" -name $conf -delete find "$SYSROOT" -name $conf -delete
done done
+3 -3
View File
@@ -7,10 +7,10 @@ TEST_DIR=$(dirname "$0")
test_teardown() test_teardown()
{ {
say "Test done $(date)" say "Test done $(date)"
say "Running test teardown." say "Running test teardown."
run "rm -f $FINIT_CONF" run "rm -f $FINIT_CONF"
} }
# shellcheck source=/dev/null # shellcheck source=/dev/null
+32 -31
View File
@@ -2,50 +2,51 @@
nm=$1 nm=$1
# shellcheck disable=SC2046
getpid() getpid()
{ {
initctl status "$1" |awk '/PID :/{ print $3; }' initctl status "$1" |awk '/PID :/{ print $3; }'
} }
pid=$(getpid "$nm") pid=$(getpid "$nm")
if [ -f oldpid ]; then if [ -f oldpid ]; then
oldpid=$(cat oldpid) oldpid=$(cat oldpid)
if [ "$oldpid" = "$pid" ]; then
echo "Looks bad, wait for it ..."
sleep 3
pid=$(getpid "$nm")
if [ "$oldpid" = "$pid" ]; then if [ "$oldpid" = "$pid" ]; then
echo "Looks bad, wait for it ..." echo "Finit did not deregister old PID $oldpid vs $pid"
sleep 3 initctl status "$nm"
pid=$(getpid "$nm") ps
if [ "$oldpid" = "$pid" ]; then echo "Reloading finit ..."
echo "Finit did not deregister old PID $oldpid vs $pid" initctl reload
initctl status "$nm" sleep 1
ps initctl status "$nm"
echo "Reloading finit ..." exit 1
initctl reload
sleep 1
initctl status "$nm"
exit 1
fi
fi fi
fi
fi fi
timeout=50 timeout=50
while [ "$pid" -le 1 ]; do while [ "$pid" -le 1 ]; do
sleep 0.1 sleep 0.1
pid=$(getpid "$nm") pid=$(getpid "$nm")
if [ "$pid" -le 1 ]; then if [ "$pid" -le 1 ]; then
timeout=$((timeout - 1)) timeout=$((timeout - 1))
if [ "$timeout" -gt 0 ]; then if [ "$timeout" -gt 0 ]; then
continue continue
fi
echo "Got a bad PID: $pid, aborting ..."
ps
sleep 1
initctl status "$nm"
ps
exit 1
fi fi
break
if [ $pid -ne 0 ]; then
echo "Got a bad PID: $pid, aborting ..."
ps
sleep 1
initctl status "$nm"
ps
fi
exit 1
fi
break
done done
echo "$pid" > /tmp/oldpid echo "$pid" > /tmp/oldpid
+3
View File
@@ -0,0 +1,3 @@
#!/bin/sh
echo "$0 $*" >> /tmp/sysv.log
+1
View File
@@ -0,0 +1 @@
S01abc.sh
+3
View File
@@ -0,0 +1,3 @@
#!/bin/sh
echo "$0" >> /tmp/sysv.log
+3
View File
@@ -0,0 +1,3 @@
#!/bin/sh
echo "$0" >> /tmp/sysv.log
File renamed without changes.
+2
View File
@@ -0,0 +1,2 @@
/etc/rcS.d/S01abc.sh start
/etc/rcS.d/S02def.sh start
+6 -6
View File
@@ -8,10 +8,10 @@ TEST_DIR=$(dirname "$0")
test_teardown() test_teardown()
{ {
say "Test done $(date)" say "Test done $(date)"
say "Running test teardown." say "Running test teardown."
run "rm -f $FINIT_CONF" run "rm -f $FINIT_CONF"
} }
# shellcheck source=/dev/null # shellcheck source=/dev/null
@@ -35,9 +35,9 @@ say 'Simulate service crash (kill -9 ..)'
i=0 i=0
laps=1000 laps=1000
while [ $i -lt $laps ]; do while [ $i -lt $laps ]; do
i=$((i + 1)) i=$((i + 1))
say "Lap $i/$laps, killing service ..." # we have this, no sleep needed say "Lap $i/$laps, killing service ..." # we have this, no sleep needed
run "slay service.sh" run "slay service.sh"
done done
retry 'assert_new_pid service.sh /run/service.pid' retry 'assert_new_pid service.sh /run/service.pid'
+27 -27
View File
@@ -5,51 +5,51 @@ TEST_DIR=$(dirname "$0")
test_setup() test_setup()
{ {
say "Test start $(date)" say "Test start $(date)"
} }
test_teardown() test_teardown()
{ {
say "Test done $(date)" say "Test done $(date)"
say "Running test teardown." say "Running test teardown."
run "rm -f $FINIT_CONF" run "rm -f $FINIT_CONF"
} }
test_one() test_one()
{ {
pidfn=$1 pidfn=$1
service=$2 service=$2
say "Add service stanza '$service' to $FINIT_CONF ..." say "Add service stanza '$service' to $FINIT_CONF ..."
run "echo '$service' > $FINIT_CONF" run "echo '$service' > $FINIT_CONF"
say 'Reload Finit' say 'Reload Finit'
#run "initctl debug" #run "initctl debug"
run "initctl reload" run "initctl reload"
#run "initctl status" #run "initctl status"
#run "ps" #run "ps"
#run "initctl status" #run "initctl status"
#run "ps" #run "ps"
#run "initctl status serv" #run "initctl status serv"
retry 'assert_num_children 1 serv' retry 'assert_num_children 1 serv'
retry "assert_has_pidfile $pidfn" 1 retry "assert_has_pidfile $pidfn" 1
say 'Stop the service' say 'Stop the service'
run "initctl stop serv" run "initctl stop serv"
retry 'assert_num_children 0 serv' retry 'assert_num_children 0 serv'
say 'Start the service again' say 'Start the service again'
run "initctl start serv" run "initctl start serv"
retry 'assert_num_children 1 serv' retry 'assert_num_children 1 serv'
say "Done, drop service from $FINIT_CONF ..." say "Done, drop service from $FINIT_CONF ..."
run "rm $FINIT_CONF" run "rm $FINIT_CONF"
run "initctl reload" run "initctl reload"
} }
# shellcheck source=/dev/null # shellcheck source=/dev/null
+3 -3
View File
@@ -6,10 +6,10 @@ TEST_DIR=$(dirname "$0")
test_teardown() test_teardown()
{ {
say "Test done $(date)" say "Test done $(date)"
say "Running test teardown." say "Running test teardown."
run "rm -f $FINIT_RCSD/service.conf" run "rm -f $FINIT_RCSD/service.conf"
} }
# shellcheck source=/dev/null # shellcheck source=/dev/null
+3 -3
View File
@@ -6,10 +6,10 @@ TEST_DIR=$(dirname "$0")
test_teardown() test_teardown()
{ {
say "Test done $(date)" say "Test done $(date)"
say "Running test teardown." say "Running test teardown."
run "rm -f $FINIT_CONF" run "rm -f $FINIT_CONF"
} }
# shellcheck source=/dev/null # shellcheck source=/dev/null
+3 -3
View File
@@ -6,10 +6,10 @@ TEST_DIR=$(dirname "$0")
test_teardown() test_teardown()
{ {
say "Test done $(date)" say "Test done $(date)"
say "Running test teardown." say "Running test teardown."
run "rm -f $FINIT_CONF" run "rm -f $FINIT_CONF"
} }
# shellcheck source=/dev/null # shellcheck source=/dev/null
+42
View File
@@ -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"