Compare commits

..
38 Commits
Author SHA1 Message Date
Joachim Wiberg d38c333e04 Bump version for final candidate, v4.5-rc5
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-10-05 08:19:24 +02:00
Joachim Wiberg 095f6b645c Update ChangeLog, should be final changes for v4.5 GA
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-10-04 19:01:38 +02:00
Joachim Wiberg b4d10cbade Always ensure /run/finit/system exists before saving runtime service
This fixes the regression in the tests, which runs in a very stripped
down world without tmpfiles.d etc.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-10-04 18:48:13 +02:00
Joachim Wiberg 5d703fd39e Support delayed load of services from plugins and bundled services
This adds a new function conf_save_service() replacing service_register() for
plugins and bundled services like watchdogd, keventd, runparts, etc.

The benefits to this change are several:

 - Plugin/Bundled services no longer risk starting before udev or other
   critical services/task have started
 - Definitions can be overridden by an administrator (see docs)
 - Increases visibility (user: where are all these services coming from?)
   Previously the origin (file the service was loaded from) was NULL.
 - Adds another level of extensibility to Finit

The most notable change is that dbus is no longer started before udevd.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-10-04 18:37:43 +02:00
Joachim Wiberg eaaf8d862e Minor, append _ to PATH constant
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-10-04 18:25:09 +02:00
Joachim Wiberg 2468f11cd8 plugins: fix dbus pidfile locator
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-10-04 18:20:50 +02:00
Joachim Wiberg f8a6a119ac system: new name for testserv.conf -> 90-testserv.conf
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-10-04 17:30:08 +02:00
Joachim Wiberg 1889b88aab Log execution order at bootstrap to /run/finit/exec.order
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-10-04 17:21:11 +02:00
Joachim Wiberg 0d70023bfe Log conf file evaluation order at bootstrap to /run/finit/conf.order
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-10-04 17:20:15 +02:00
Joachim Wiberg 41648a073b Fix evaluation order of /lib/finit/system/* vs /etc/finit.d/*
See updated documentation and inline comment for details.

Fix #371

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-10-04 17:20:15 +02:00
Joachim Wiberg 33cee0ba5f system: fix lost udevadm calls due to overloading
The system/10-hotplug.conf needs to index its calls to udevadm for all
calls to udevadm, not just the trigger calls.  Otherwise the first
udevadm is overloaded with all subseequent (unindexed) udevamd stanzas.

Also, make sure all udevadm calls to settle/reload are hidden.

Fix #372

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-10-04 17:19:46 +02:00
Joachim Wiberg 2235fb8352 system: rename *.conf files to ensure proper execution order
At bootstrap we want to start udev as soon as possible (after any
services registered by plugins).

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-10-04 11:39:39 +02:00
Joachim Wiberg eb9e94935e Failure to open fstab should log to console, reboot if no sulogin
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-10-03 17:56:49 +02:00
Joachim Wiberg fb230f2137 .github: add makeLatest flag based on non-rc/beta/alpha
Note, the makeLatest flag can also be set to 'legacy', which takes
latest date and version.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-10-03 17:42:20 +02:00
Joachim Wiberg 6aa48a8b32 .github: fix pre-release flag input
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-10-03 17:41:52 +02:00
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
Joachim Wiberg 7cb91854b0 Update ChangeLog and bump version for v4.5-rc2
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-09-14 09:22:11 +02:00
Joachim Wiberg 939ae02a6a Increase MAX command, and arg., length: 64 -> 256
With non-standard paths, e.g., when running `make distcheck`, the
absolute path to some commands become ridiculously long.  However,
this has been a recurring issue for some users in the past, so it
is time to increase the capabilibieies of Finit to cover this.

Yes, a better way is probably to allocate all these strings when they
are used, but that would require a redesign of the initctl API and
likely cause a lot of regressions before everything has stabilized.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-09-14 09:15:55 +02:00
Joachim Wiberg 480d29175c test: minor, clarify
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-09-14 09:15:40 +02:00
Joachim Wiberg ea68413512 test: add missing scripts to dist for new runparts test
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-09-14 09:15:17 +02:00
Joachim Wiberg 4edfa9859e .github: fix variable sharing between jobs
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-09-14 09:14:28 +02:00
68 changed files with 926 additions and 503 deletions
+19
View File
@@ -10,12 +10,29 @@ jobs:
name: Build and upload release tarball
if: startsWith(github.ref, 'refs/tags/')
runs-on: ubuntu-latest
env:
MAKEFLAGS: -j3
steps:
- uses: actions/checkout@v3
- name: Installing dependencies ...
run: |
sudo apt-get -y update
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]+\.[0-9]+(\.[0-9]+)?(-alpha|-beta|-rc)[0-9]*$'; then
echo "pre=true" >> $GITHUB_OUTPUT
else
echo "pre=false" >> $GITHUB_OUTPUT
fi
if echo $ver | grep -qE '^[0-9.]+\.[0-9.]+(\.[0-9]+)?$'; then
echo "latest=true" >> $GITHUB_OUTPUT
else
echo "latest=false" >> $GITHUB_OUTPUT
fi
- name: Creating Makefiles ...
run: |
./autogen.sh
@@ -36,5 +53,7 @@ jobs:
- uses: ncipollo/release-action@v1
with:
name: Finit v${{ github.ref_name }}
prerelease: ${{ steps.build.outputs.pre }}
makeLatest: ${{ steps.build.outputs.latest }}
bodyFile: "release.md"
artifacts: "artifacts/*"
+2 -2
View File
@@ -15,6 +15,7 @@ jobs:
steps:
- uses: actions/checkout@v3
- name: Check for any commits since last week
id: schedule
run: |
commits="$(git log --format=%H --since='1 week ago')"
if [ -n "$commits" ]; then
@@ -22,10 +23,9 @@ jobs:
else
echo "run=false" >> $GITHUB_OUTPUT
fi
distcheck:
needs: schedule
if: ${{ needs.schedule.outputs.run == 'true' }}
if: ${{ needs.schedule.outputs.run }}
runs-on: ubuntu-latest
steps:
- name: Install dependencies
+34 -5
View File
@@ -4,19 +4,21 @@ Change Log
All relevant changes are documented in this file.
[4.5][] - 2023-09-14
[4.5][] - 2023-10-04
--------------------
### Changes
- Refactor `runparts` and `/etc/rc.local` to no longer block the main
loop, allowing these scripts to call `initctl` to interact with Finit.
Still in a limited way due to them being used at bootstrap, issue #356
loop, allowing `initctl` calls to interact with Finit. Issue #356
- Refactor the `run` stanza to no longer block the main loop, issue #362
- Allow `sulogin` with a user different from `root`, issue #357
- Allow disabling invocation of rescue mode from kernel command line
- Add `initctl -f` to force-skip asking Finit for existing services
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 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
with `errno`, e.g., "No such file or directory" when the command
is missing from `$PATH`
@@ -25,19 +27,46 @@ All relevant changes are documented in this file.
- Update `finit.conf(5)` man page with the recommended directory
hierarchy in `/etc/finit.d/`
- 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
- 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
- Failure to open fstab should log to console, not just log to `/dev/kmsg`
- Rename `/lib/finit/system/*.conf`, added numbered prefix to ensure
proper execution order, e.g., `udevd` should always run first
- Plugins and bundled services: dbus, keventd, watchdogd, and runparts,
are now loaded *after* all services in `/lib/finit/system/`. A new
runtime-only path (for inspection) in `/run/finit/system/` is used
### 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
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
- Fix #358: fix inotify events for `/etc/finit.conf`, improved log
messages and error handling
- 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
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.
- Fix #371: swap load order of `/lib/finit/system/*` vs `/etc/finit.d/*`
We must run `10-hotplug.conf` first to ensure devices and modules are
up and loaded before the user's run/task/services are called. The order
at bootstrap is now saved in `/run/finit/conf.order` for inspection,
`/run/finit/exec.order` shows the start order of each process
- Fix #372: lost `udevadm` calls due to overloading
- Fixed dbus plugin, the function that located `<pidfile> ...` in the
`dbus/system.conf` caused spurious line breaks which led to the
service not being loaded properly
- The `runparts` executor now skips backup files (`foo~`)
- The `runparts` stanza now properly appends ` start` to scripts that
start with `S[0-9]+`. This has been broken for a very long time.
+5 -3
View File
@@ -1,4 +1,5 @@
AC_INIT([Finit],[4.5-rc1],[https://github.com/troglobit/finit/issues],[finit],[https://troglobit.com/projects/finit/])
AC_INIT([Finit], [4.5-rc5], [https://github.com/troglobit/finit/issues],
[finit], [https://troglobit.com/projects/finit/])
AC_CONFIG_AUX_DIR(aux)
AM_INIT_AUTOMAKE([1.11 foreign dist-xz subdir-objects])
AM_SILENT_RULES([yes])
@@ -297,6 +298,7 @@ pkglibdir=$libdir/finit
AC_SUBST(pkglibexecdir)
AC_EXPAND_DIR(pkglibexecdir, "$libexecdir/finit")
AC_DEFINE_UNQUOTED(FINIT_EXECPATH_, "$pkglibexecdir", [Finit libexec path])
AC_DEFINE_UNQUOTED(FINIT_RUNPATH_, "/run/finit/system", [Finit runtime dynamic system services])
AC_EXPAND_DIR(plugin_path, "$pkglibdir/plugins")
AC_SUBST(plugin_path)
@@ -304,7 +306,7 @@ AC_DEFINE_UNQUOTED(PLUGIN_PATH, "$plugin_path", [Finit plugin path])
AC_EXPAND_DIR(tmpfiles_path, "$libdir/tmpfiles.d")
AC_SUBST(tmpfiles_path)
AC_DEFINE_UNQUOTED(TMPFILES_PATH, "$tmpfiles_path", [Main tmpfiles.d/, override in /etc])
AC_DEFINE_UNQUOTED(TMPFILES_PATH_, "$tmpfiles_path", [Main tmpfiles.d/, override in /etc])
AC_EXPAND_DIR(finit_tmpfiles, "$pkglibdir/tmpfiles.d")
AC_SUBST(finit_tmpfiles)
@@ -312,7 +314,7 @@ AC_DEFINE_UNQUOTED(FINIT_TMPFILES, "$finit_tmpfiles", [Finit tmpfiles.d/ .conf p
AC_EXPAND_DIR(system_path, "$pkglibdir/system")
AC_SUBST(system_path)
AC_DEFINE_UNQUOTED(FINIT_SYSPATH, "$system_path", [Static services, previously generated at runtime by plugins])
AC_DEFINE_UNQUOTED(FINIT_SYSPATH_, "$system_path", [Static services, previously generated at runtime by plugins])
AC_EXPAND_DIR(rescue_conf, "$pkglibdir/rescue.conf")
AC_DEFINE_UNQUOTED(RESCUE_CONF, "$rescue_conf", [Finit rescue mode .conf])
+1 -1
View File
@@ -17,7 +17,7 @@ PKG_CONFIG_LIBDIR=/usr/lib/pkgconfig:/usr/local/lib/pkgconfig ./configure \
--prefix=/usr --exec-prefix= \
--sysconfdir=/etc --localstatedir=/var \
--enable-dbus-plugin --enable-x11-common-plugin \
--enable-alsa-utils-plugin --with-watchdog \
--enable-alsa-utils-plugin --without-watchdog \
--with-keventd --with-sulogin
echo
-10
View File
@@ -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
----------
+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
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
multiple conditions can be set using the same option, separated with a
comma. Alternatively, multiple `foo.cond=arg` can be given. Each will
+162 -44
View File
@@ -52,21 +52,51 @@ PID file monitoring, or [conditions](conditions.md).
### Configuration Files
Originally Finit was configured using a single file, `/etc/finit.conf`.
Although still possible to use this single configuration file, today the
following familiar layout is recommended:
Originally Finit was configured using a single file, `/etc/finit.conf`,
and although still possible to use a single configuration file, today
the following layout is recommended:
/etc/
|- finit.d/
| |- available/
| | `- my-service.conf
: |- enabled/
: | `- my-service.conf -> ../available/my-service.conf
: :
: |- static-service.conf
: `- another-static.conf
:
`- finit.conf
/
|- etc/
| |- finit.d/
| | |- available/
| | | `- my-service.conf
| : |- enabled/
| : | `- my-service.conf -> ../available/my-service.conf
| : :
| : |- static-service.conf
| : `- another-static.conf
| :
| `- finit.conf
|- lib
| `- finit/
| `- system/
| |- 10-hotplug.conf
| `- ...
`- run/
`- finit/
`- system/
|- dbus.conf
|- keventd.conf
|- runparts.conf
|- watchdogd.conf
`- ...
Configuration files in `/etc` are provided by the user, or projects like
[finit-skel](https://github.com/troglobit/finit-skel) and extended by
the user.
The files in `/lib/finit/system/*.conf` are system critical services and
setup provided by Finit, e.g. udev/mdev that must run very early at system
bootstrap. This system directory was introduced in Finit v4.4 to replace
the hard-coded services provided by plugins before. All .conf files in this
directory be either replaced by a system administrator or overridden by a
file with the same name in `/etc/finit.d/`.
The files in `/run/finit/system/*.conf` are created by plugins and Finit
bundled services like runparts, the [watchdog](#watchdog), and `keventd`
if they are enabled. Like `/lib/finit/system/*.conf`, these files can
be overridden by file with the same name in `/etc/finit.d/`.
Services in the `available/` and `enabled/` sub-directories are called
dynamic services, in contrast to static services -- the only difference
@@ -75,9 +105,27 @@ with the `enable` and `disable` commands. An administrator can always
create files and symlinks manually.
At bootstrap, and `initctl reload`, all .conf files are read, starting
with `finit.conf`, then, in alphabetical order, all `finit.d/*.conf`
files, and finally (still in alphabetical order) all `enabled/*.conf`
files.
with `finit.conf`, then `/lib/finit/system/*.conf`, `finit.d/*.conf`,
and finally all `finit.d/enabled/*.conf` files. Each directory is a
unique group, where files within each group are sorted alphabetically.
**Example:**
/lib/finit/system/10-hotplug.conf
/lib/finit/system/90-testserv.conf
/run/finit/system/dbus.conf
/run/finit/system/runparts.conf
/etc/finit.d/10-abc.conf
/etc/finit.d/20-abc.conf
/etc/finit.d/enabled/1-aaa.conf
/etc/finit.d/enabled/1-abc.conf
The resulting combined configuration is read line by line, each `run`,
`task`, and `service` added to an ordered list that ensures they are
started in the same order. This is important because of the blocking
properties of the `run` statement. For an example on the relation of
`service` and `run` statements, and dependency handling between them,
see [Conditional Loading](#conditional-loading), below.
> **Note:** the `finit.conf` and `finit.d/` names are only defaults.
> They can be changed at compile-time with two `configure` options:
@@ -164,14 +212,19 @@ everything is OK.
task [S] /lib/console-setup/console-setup.sh
service [S12345] env:-/etc/default/rsyslog rsyslogd -n $RSYSLOGD_ARGS
After runlevel S, Finit proceeds to runlevel 2. (This can be changed in
`/etc/finit.conf` using the `runlevel N` directive.) Before starting
the services in runlevel 2, Finit first stops everything 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.
After runlevel S, Finit proceeds to runlevel 2. This can be changed in
`/etc/finit.conf` using the `runlevel N` directive, or by a script
running in runlevel S that calls, e.g., `initctl runlevel 9`. The
latter is useful if startup scripts detect problems outside of Finit's
control, e.g., critical services/devices missing or hardware problems.
Before starting the services in runlevel 2, Finit first stops everything
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
> were constrained to runlevel S only are dropped from bookkeeping. So
@@ -839,10 +892,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
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> :1 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
**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 +972,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 +1189,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`
+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
net/et0/running
.It Cm pid
PID files basd on the service declaration
PID files based on the service declaration
.Cm name:id ,
gives the condition pid/name:id
.It Cm service
+5
View File
@@ -240,6 +240,11 @@ Show top-like listing based on cgroups.
List installed plugins.
.It Nm Ar runlevel Op Ar 0-9
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
Reboot system, default if
.Cm reboot
+2 -3
View File
@@ -83,6 +83,7 @@ static char *dbus_pidfn(void)
break;
}
*pos = 0;
break;
}
fclose(fp);
@@ -156,9 +157,7 @@ static void setup(void *arg)
snprintf(line, sizeof(line), "[S123456789] cgroup.system name:dbus %s %s -- %s",
cmd, DBUS_ARGS, DBUS_DESC);
if (service_register(SVC_TYPE_SERVICE, line, global_rlimit, NULL))
err(1, "Failed registering %s", DBUS_DAEMON);
conf_save_service(SVC_TYPE_SERVICE, line, "dbus.conf");
free(cmd);
}
+1 -1
View File
@@ -101,7 +101,7 @@ static int modules_load(const char *file, int index)
}
while ((line = fparseln(fp, NULL, NULL, NULL, 0))) {
char cmd[CMD_SIZE * 2], *mod, *args, *set;
char cmd[CMD_SIZE], *mod, *args, *set;
/*
* fparseln() skips regular UNIX comments only.
+1 -1
View File
@@ -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("/");
}
+15 -3
View File
@@ -367,7 +367,6 @@ static void api_cb(uev_t *w, void *arg, int events)
}
switch (rq.cmd) {
case INIT_CMD_RUNLVL:
case INIT_CMD_RELOAD:
case INIT_CMD_START_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_SUSPEND:
if (IS_RESERVED_RUNLEVEL(runlevel)) {
warnx("Unsupported command in runlevel S and 6.");
warnx("Unsupported command in runlevel S and 6/0.");
goto leave;
}
default:
@@ -387,6 +386,14 @@ static void api_cb(uev_t *w, void *arg, int events)
switch (rq.cmd) {
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) {
case 's':
case 'S':
@@ -400,7 +407,12 @@ static void api_cb(uev_t *w, void *arg, int events)
halt = SHUT_OFF;
if (lvl == 6)
halt = SHUT_REBOOT;
service_runlevel(lvl);
/* User requested change in next runlevel */
if (runlevel == INIT_LEVEL)
cfglevel = lvl;
else
service_runlevel(lvl);
break;
default:
+154 -9
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 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 = "";
# endif
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 */
@@ -393,6 +414,79 @@ void conf_saverc(void)
fclose(fp);
}
/*
* Called at bootstrap to log execution order (for debug)
*/
void conf_save_exec_order(svc_t *svc, char *cmdline, int result)
{
const char *fn = _PATH_VARRUN "finit/exec.order";
const char *ststr = !result ? "[ OK ]" : "[FAIL]";
static char *prepared = NULL;
int first = !fexist(fn);
FILE *fp;
fp = fopen(fn, "a+");
if (!fp) {
err(1, "failed writing to %s", fn);
return;
}
if (first) {
fprintf(fp, "# Execution order of run/task/services at bootstrap\n");
fprintf(fp, "# ST TYPE COMMAND LINE (DESC)\n");
}
if (result == -1) {
int len;
len = snprintf(NULL, 0, " %-7s %-64s (%s)", svc_typestr(svc), cmdline, svc->desc);
if (len > 0) {
if (prepared)
free(prepared);
prepared = malloc(++len);
if (!prepared)
return;
snprintf(prepared, len, " %-7s %-64s (%s)", svc_typestr(svc), cmdline, svc->desc);
}
} else {
if (prepared) {
memcpy(prepared, ststr, strlen(ststr));
fprintf(fp, "%s\n", prepared);
free(prepared);
prepared = NULL;
} else {
fprintf(fp, "%s %-7s %-64s (%s)\n", ststr, svc_typestr(svc), cmdline, svc->desc);
}
}
fclose(fp);
}
/*
* Called by plugins and similar that dynamically generate system services
*/
void conf_save_service(int type, char *cfg, char *file)
{
char fn[256];
svc_t foo;
FILE *fp;
mkpath(FINIT_RUNPATH_, 0755);
snprintf(fn, sizeof(fn), "%s/%s", FINIT_RUNPATH_, file);
if (fexist(fn))
warn("File %s already exists, overwriting.", fn);
fp = fopen(fn, "w");
if (!fp) {
err(1, "Failed creating %s", fn);
return;
}
foo.type = type;
fprintf(fp, "# Generated by finit:%s()\n", __func__);
fprintf(fp, "%s %s\n", svc_typestr(&foo), cfg);
fclose(fp);
}
/*
* Sets, and makes a note of, all KEY=VALUE lines in a given .conf line
* from finit.conf, or other .conf file. Note, PATH is always reset in
@@ -778,6 +872,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;
}
@@ -1122,20 +1225,51 @@ int conf_reload(void)
* but are now regular files that can be overridden by files in
* /etc/finit.d -- similar to how tmfiles.d(5) work. E.g., add
* an override .conf, or an ignore by symlinking to /dev/null
*
* The .conf files (and run/task/service stanzas) are parsed and
* started in order. Each directory is sorted alphanumerically
* and then the result is appended to the overall order:
*
* /lib/finit/system/10-hotplug.conf
* /lib/finit/system/90-testserv.conf
* /run/finit/system/dbus.conf
* /run/finit/system/tty.conf
* /etc/finit.d/10-abc.conf
* /etc/finit.d/20-abc.conf
* /etc/finit.d/enabled/1-aaa.conf
* /etc/finit.d/enabled/1-abc.conf
* /etc/finit.d/enabled/2-aaa.conf
*/
glob_append(&gl, 0, "%s/*.conf", finit_rcsd);
glob_append(&gl, 1, "%s/*.conf", FINIT_SYSPATH);
glob_append(&gl, 0, "%s/*.conf", FINIT_SYSPATH_);
glob_append(&gl, 1, "%s/*.conf", FINIT_RUNPATH_);
glob_append(&gl, 1, "%s/*.conf", finit_rcsd);
glob_append(&gl, 1, "%s/enabled/*.conf", finit_rcsd);
if (bootstrap) {
const char *fn = _PATH_VARRUN "finit/conf.order";
FILE *fp;
fp = fopen(fn, "w");
if (!fp) {
err(1, "failed creating %s", fn);
} else {
fprintf(fp, "# Evaluation & execution order of .conf files\n");
for (i = 0; i < gl.gl_pathc; i++)
fprintf(fp, "%s\n", gl.gl_pathv[i]);
fclose(fp);
}
}
for (i = 0; i < gl.gl_pathc; i++) {
char *path = gl.gl_pathv[i];
char *rp = NULL;
struct stat st;
size_t j, len;
/* check for FINIT_SYSPATH overrides */
/* check for FINIT_SYSPATH_ or FINIT_RUNPATH_ overrides */
for (j = i + 1; j < gl.gl_pathc; j++) {
if (strncmp(path, FINIT_SYSPATH, strlen(FINIT_SYSPATH)))
if (strncmp(path, FINIT_SYSPATH_, strlen(FINIT_SYSPATH_)) &&
strncmp(path, FINIT_RUNPATH_, strlen(FINIT_RUNPATH_)))
continue;
if (strcmp(basename(path), basename(gl.gl_pathv[j])))
continue;
@@ -1195,6 +1329,9 @@ done:
/* Drop record of all .conf changes */
drop_changes();
if (bootstrap)
wdog = svc_find("watchdog", "finit");
/* Override configured runlevel, user said 'S' on /proc/cmdline */
if (BOOTSTRAP && single)
cfglevel = 1;
@@ -1431,15 +1568,16 @@ int conf_init(uev_ctx_t *ctx)
*/
#ifdef WDT_DEVNODE
if (whichp(FINIT_EXECPATH_ "/watchdogd") && fexist(WDT_DEVNODE)) {
service_register(SVC_TYPE_SERVICE, "[S0123456789] cgroup.init name:watchdog :finit " FINIT_EXECPATH_ "/watchdogd -- Finit watchdog daemon", global_rlimit, NULL);
wdog = svc_find("watchdog", "finit");
conf_save_service(SVC_TYPE_SERVICE, "[S0123456789] cgroup.init name:watchdog :finit "
FINIT_EXECPATH_ "/watchdogd -- Finit watchdog daemon", "watchdogd.conf");
}
#endif
/*
* Start kernel event daemon as soon as possible, if enabled
*/
if (whichp(FINIT_EXECPATH_ "/keventd"))
service_register(SVC_TYPE_SERVICE, "[S0123456789] cgroup.init " FINIT_EXECPATH_ "/keventd -- Finit kernel event daemon", global_rlimit, NULL);
conf_save_service(SVC_TYPE_SERVICE, "[S0123456789] cgroup.init "
FINIT_EXECPATH_ "/keventd -- Finit kernel event daemon", "keventd.conf");
dbg("Allow plugins to register early runlevel 1 run/task/services ...");
plugin_run_hooks(HOOK_SVC_PLUGIN);
@@ -1463,12 +1601,19 @@ 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",
_PATH_RUNPARTS, args, runparts, runparts);
service_register(SVC_TYPE_TASK, conf, global_rlimit, NULL);
conf_save_service(SVC_TYPE_TASK, conf, "runparts.conf");
}
return 0;
+2
View File
@@ -44,6 +44,8 @@ int conf_monitor (void);
void conf_reset_env (void);
void conf_saverc (void);
void conf_save_exec_order (svc_t *svc, char *cmdline, int result);
void conf_save_service (int type, char *cfg, char *file);
void conf_parse_cmdline (int argc, char *argv[]);
int conf_parse_runlevels (char *runlevels);
void conf_parse_cond (svc_t *svc, char *cond);
+1 -1
View File
@@ -237,7 +237,7 @@ static void devmon_cb(uev_t *w, void *arg, int events)
continue;
}
dbg("Got %s", ev->name);
// dbg("Got %s", ev->name);
if (ev->mask & (IN_CREATE | IN_DELETE))
devmon_update_conds(iwp->path, ev->name, ev->mask);
}
+2 -8
View File
@@ -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 */
@@ -205,7 +204,7 @@ static int fsck(int pass)
fp = setmntent(fstab, "r");
if (!fp) {
err(1, "Failed opening fstab: %s", fstab);
logit(LOG_CONSOLE | LOG_ALERT, "Failed opening fstab: %s", fstab);
sulogin(1);
}
dbg("Opened %s, pass %d", fstab, pass);
@@ -255,11 +254,7 @@ static int fsck(int pass)
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);
#endif
dbg("Running pass %d fsck command %s", pass, cmd);
fsck_rc = run_interactive(cmd, "Checking filesystem %s", dev);
/*
@@ -282,7 +277,6 @@ static int fsck(int pass)
static int fsck_all(void)
{
int rc = 0;
#ifndef FAST_BOOT
int pass;
if (!fsck_mode)
@@ -293,7 +287,7 @@ static int fsck_all(void)
if (rc)
break;
}
#endif
return rc;
}
+1 -1
View File
@@ -60,7 +60,7 @@
#define _PATH_SULOGIN FINIT_EXECPATH_ "/sulogin"
#define _PATH_GETTY FINIT_EXECPATH_ "/getty"
#define CMD_SIZE 256
#define CMD_SIZE 1024
#define LINE_SIZE 1024
#define BUF_SIZE 4096
+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_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:
+2 -2
View File
@@ -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)
@@ -288,7 +288,7 @@ static void generic_io_cb(uev_t *w, void *arg, int events)
/* Stop watcher, callback may close descriptor on us ... */
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);
/* 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");
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);
+20 -7
View File
@@ -629,6 +629,9 @@ static int service_start(svc_t *svc)
}
compose_cmdline(svc, cmdline, sizeof(cmdline));
if (bootstrap)
conf_save_exec_order(svc, cmdline, -1);
if (svc_is_sysv(svc))
logit(LOG_CONSOLE | LOG_NOTICE, "Calling '%s start' ...", cmdline);
@@ -836,8 +839,10 @@ static int service_start(svc_t *svc)
fail:
sigprocmask(SIG_SETMASK, &omask, NULL);
if (do_progress)
if (do_progress && !run_block_pid)
print_result(result);
if (bootstrap && !run_block_pid)
conf_save_exec_order(svc, NULL, result);
return result;
}
@@ -1847,11 +1852,6 @@ void service_monitor(pid_t lost, int status)
return;
}
if (lost == run_block_pid) {
svc_mark_clean(svc); /* done, regardless of exit status */
run_block_pid = 0;
}
switch (svc->state) {
case SVC_CLEANUP_STATE:
case SVC_SETUP_STATE:
@@ -1900,6 +1900,17 @@ done:
/* No longer running, update books. */
svc->start_time = svc->pid = 0;
cont:
if (lost == run_block_pid) {
int result = WIFEXITED(status) ? WEXITSTATUS(status) : 1;
svc_mark_clean(svc); /* done, regardless of exit status */
run_block_pid = 0;
if (svc->desc[0])
print_result(result);
if (bootstrap)
conf_save_exec_order(svc, NULL, result);
}
if (!service_step(svc)) {
/* Clean out any bootstrap tasks, they've had their time in the sun. */
if (svc_clean_bootstrap(svc))
@@ -1955,7 +1966,7 @@ void service_mark_unavail(void)
if (!svc->ifstmt[0])
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);
}
}
@@ -2294,9 +2305,11 @@ restart:
svc_set_state(svc, SVC_WAITING_STATE);
else {
if (svc_is_conflict(svc)) {
#if 0
logit(svc->nowarn ? LOG_DEBUG : LOG_INFO,
"%s in conflict with %s, checking again ...",
svc_ident(svc, NULL, 0), svc->conflict);
#endif
if (!svc_conflicts(svc))
svc_unblock(svc);
}
+27 -11
View File
@@ -634,17 +634,30 @@ int svc_enabled(svc_t *svc)
if (!svc)
return 0;
if (!svc_in_runlevel(svc, runlevel))
if (!svc_in_runlevel(svc, runlevel)) {
// dbg("Not in runlevel");
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;
}
if (svc_is_missing(svc))
if (svc_is_missing(svc)) {
// dbg("missing");
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;
}
if (svc_is_tty(svc) && bootstrap) {
// dbg("is tty in bootstrap");
return 0;
}
return 1;
}
@@ -688,13 +701,14 @@ int svc_conflicts(svc_t *svc)
/**
* svc_ifthen - Check if: statement in declaration
* @is_conf: Set when called by service_mark_unavail()
* @ident: svc_t identififcation (name:id)
* @stmt: if: statement from .conf file
*
* Returns:
* %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;
svc_t *svc;
@@ -707,6 +721,9 @@ int svc_ifthen(const char *ident, char *stmt)
char *ptr = ++stmt;
int i = 0;
if (is_conf)
return 1;
if (stmt[0] == '!') {
stmt++;
not++;
@@ -717,17 +734,16 @@ int svc_ifthen(const char *ident, char *stmt)
ptr[i] = 0;
cond = cond_get(stmt);
if (not && cond == COND_ON) {
logit(LOG_NOTICE, "skipping %s, cond %s is on.", ident, stmt);
if (not && cond == COND_ON)
return 0;
}
if (!not && cond == COND_OFF) {
logit(LOG_NOTICE, "skipping %s, cond %s is off.", ident, stmt);
if (!not && cond == COND_OFF)
return 0;
}
return 1;
}
if (!is_conf)
return 1;
if (stmt[0] == '!') {
stmt++;
not++;
+9 -8
View File
@@ -85,6 +85,7 @@ typedef enum {
#define MAX_ID_LEN 16
#define MAX_ARG_LEN 64
#define MAX_CMD_LEN 256
#define MAX_IDENT_LEN (MAX_ARG_LEN + MAX_ID_LEN + 1)
#define MAX_STR_LEN 64
#define MAX_COND_LEN (MAX_ARG_LEN * 3)
@@ -118,7 +119,7 @@ typedef struct svc {
int sighalt; /* Signal to stop process, default: SIGTERM */
int killdelay; /* Delay in msec before sending SIGKILL */
pid_t oldpid, pid;
char pidfile[256];
char pidfile[MAX_CMD_LEN];
long start_time; /* Start time, as seconds since boot, from sysinfo() */
int started; /* Set for run/task/sysv to track if started */
int status; /* From waitpid() when process is collected */
@@ -181,15 +182,15 @@ typedef struct svc {
char group[MAX_USER_LEN];
/* Command, arguments and service description */
char cmd[MAX_ARG_LEN];
char args[MAX_NUM_SVC_ARGS][MAX_ARG_LEN];
char cmd[MAX_CMD_LEN];
char args[MAX_NUM_SVC_ARGS][MAX_CMD_LEN];
int args_dirty;
char conflict[MAX_ARG_LEN];
char desc[MAX_STR_LEN];
char env[MAX_ARG_LEN];
char pre_script[MAX_ARG_LEN];
char post_script[MAX_ARG_LEN];
char ready_script[MAX_ARG_LEN];
char env[MAX_CMD_LEN];
char pre_script[MAX_CMD_LEN];
char post_script[MAX_CMD_LEN];
char ready_script[MAX_CMD_LEN];
/*
* Used to forcefully kill services that won't shutdown on
@@ -240,7 +241,7 @@ void svc_prune_bootstrap (void);
void svc_enable (svc_t *svc);
int svc_enabled (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 *));
+1 -1
View File
@@ -471,7 +471,7 @@ void tmpfilesd(void)
/* in priority order */
char *dir[] = {
FINIT_TMPFILES "/*.conf",
TMPFILES_PATH "/*.conf",
TMPFILES_PATH_ "/*.conf",
"/usr/lib/tmpfiles.d/*.conf",
"/run/tmpfiles.d/*.conf",
"/etc/tmpfiles.d/*.conf", /* local admin overrides */
-1
View File
@@ -60,7 +60,6 @@ static int init(char *progname, char *devnode)
signal(SIGPWR, sighandler);
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);
if (fd == -1)
@@ -7,11 +7,11 @@ service nowarn [S12345789] cgroup.system name:udevd pid:udevd log /lib/systemd/s
service nowarn [S12345789] cgroup.system name:udevd pid:udevd log udevd -- Device event managing daemon
# Wait for udevd to start, then wait a couple of seconds for it to become ready
run nowarn if:udevd cgroup.init [S] <pid/udevd> udevadm settle -t 0 --
run nowarn if:udevd cgroup.init [S] <pid/udevd> log udevadm control --reload
run nowarn if:udevd cgroup.init :1 [S] <pid/udevd> log udevadm trigger -c add -t devices -- Requesting device events
run nowarn if:udevd cgroup.init :2 [S] <pid/udevd> log udevadm trigger -c add -t subsystems -- Requesting subsystem events
run nowarn if:udevd cgroup.init [S] <pid/udevd> log udevadm settle -t 5 -- Waiting for udev to finish
run nowarn if:udevd cgroup.init :1 [S] <pid/udevd> log udevadm settle -t 0 --
run nowarn if:udevd cgroup.init :2 [S] <pid/udevd> log udevadm control --reload --
run nowarn if:udevd cgroup.init :3 [S] <pid/udevd> log udevadm trigger -c add -t devices -- Requesting device events
run nowarn if:udevd cgroup.init :4 [S] <pid/udevd> log udevadm trigger -c add -t subsystems -- Requesting subsystem events
run nowarn if:udevd cgroup.init :5 [S] <pid/udevd> log udevadm settle -t 5 -- Waiting for udev to finish
# If udevd is not available, try mdev
run nowarn conflict:udevd [S] mdev -s -- Populating device tree
+2 -2
View File
@@ -2,9 +2,9 @@ systemdir = $(system_path)
dist_system_DATA =
if BUILD_HOTPLUG_PLUGIN
dist_system_DATA += hotplug.conf
dist_system_DATA += 10-hotplug.conf
endif
if BUILD_TESTSERV_PLUGIN
dist_system_DATA += testserv.conf
dist_system_DATA += 90-testserv.conf
endif
+8 -1
View File
@@ -2,7 +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/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 \
@@ -39,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
@@ -78,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
@@ -6,10 +6,10 @@ TEST_DIR=$(dirname "$0")
test_teardown()
{
say "Test done $(date)"
say "Test done $(date)"
say "Running test teardown."
run "rm -f $FINIT_RCSD/service.conf"
say "Running test teardown."
run "rm -f $FINIT_RCSD/service.conf"
}
# shellcheck source=/dev/null
+3 -3
View File
@@ -6,10 +6,10 @@ TEST_DIR=$(dirname "$0")
test_teardown()
{
say "Test done $(date)"
say "Test done $(date)"
say "Running test teardown."
run "rm -f $FINIT_CONF"
say "Running test teardown."
run "rm -f $FINIT_CONF"
}
# shellcheck source=/dev/null
+53 -53
View File
@@ -9,77 +9,77 @@ TEST_DIR=$(dirname "$0")
test_setup()
{
say "Test start $(date)"
say "Test start $(date)"
}
test_teardown()
{
say "Test done $(date)"
say "Running test teardown."
run "rm -f $TEST_CONF"
say "Test done $(date)"
say "Running test teardown."
run "rm -f $TEST_CONF"
}
test_one()
{
cond=$1
stanza=$2
cond=$1
stanza=$2
sleep 5
say 'Enable finit debug, try to figure out what is going on ...'
run "initctl debug"
sleep 5
say 'Enable finit debug, try to figure out what is going on ...'
run "initctl debug"
say "Add stanza '$stanza' to $TEST_CONF ..."
run "echo '$stanza' > $TEST_CONF"
say "Add stanza '$stanza' to $TEST_CONF ..."
run "echo '$stanza' > $TEST_CONF"
run "ls -l /run/ /run/finit/"
say 'Reload Finit'
run "initctl ls"
run "initctl reload"
run "initctl status"
run "ps"
run "ls -l /run/ /run/finit/"
say 'Reload Finit'
run "initctl ls"
run "initctl reload"
run "initctl status"
run "ps"
date
sleep 2
date
run "ls -l /run/ /run/finit/"
say 'Asserting condition'
run "initctl cond set $cond"
date
sleep 2
date
run "ls -l /run/ /run/finit/"
say 'Asserting condition'
run "initctl cond set $cond"
date
sleep 2
date
run "ls -l /run/ /run/finit/"
run "initctl status"
run "ps"
run "initctl status task.sh"
date
sleep 2
date
run "ls -l /run/ /run/finit/"
run "initctl status"
run "ps"
run "initctl status task.sh"
sleep 1
run "echo Hej; cat /run/task.state"
sleep 1
run "echo Hej; cat /run/task.state"
assert_file_contains /run/task.state 1
assert_file_contains /run/task.state 1
say 'Reload Finit'
run "initctl reload"
sleep 1
say 'Ensure task has not run again ...'
assert_file_contains /run/task.state 1
say 'Reload Finit'
run "initctl reload"
sleep 1
say 'Ensure task has not run again ...'
assert_file_contains /run/task.state 1
say 'Switch to another runlevel ...'
run "initctl runlevel 3"
sleep 1
say 'Ensure task has run again ...'
assert_file_contains /run/task.state 2
say 'Touch task.sh .conf file and reload Finit ...'
run "touch $TEST_CONF"
run "initctl reload"
sleep 1
# run "initctl status task.sh"
assert_file_contains /run/task.state 3
say 'Switch to another runlevel ...'
run "initctl runlevel 3"
sleep 1
say 'Ensure task has run again ...'
assert_file_contains /run/task.state 2
say 'Touch task.sh .conf file and reload Finit ...'
run "touch $TEST_CONF"
run "initctl reload"
sleep 1
# run "initctl status task.sh"
assert_file_contains /run/task.state 3
say "Done, drop stanza from $TEST_CONF ..."
run "rm $TEST_CONF"
run "initctl reload"
say "Done, drop stanza from $TEST_CONF ..."
run "rm $TEST_CONF"
run "initctl reload"
}
+33 -33
View File
@@ -7,57 +7,57 @@ TEST_DIR=$(dirname "$0")
test_setup()
{
say "Test start $(date)"
say "Test start $(date)"
}
test_teardown()
{
say "Test done $(date)"
say "Test done $(date)"
say "Running test teardown."
run "rm -f $FINIT_CONF" "/tmp/post"
say "Running test teardown."
run "rm -f $FINIT_CONF" "/tmp/post"
}
crashit()
{
nm=$1
nm=$1
say 'Simulate service crash (kill -9 ..)'
i=0
laps=100
while [ $i -lt $laps ]; do
i=$((i + 1))
say "Lap $i/$laps, killing service $nm ..." # we have this, no sleep needed
if ! run "slay $nm"; then
break;
fi
done
say 'Simulate service crash (kill -9 ..)'
i=0
laps=100
while [ $i -lt $laps ]; do
i=$((i + 1))
say "Lap $i/$laps, killing service $nm ..." # we have this, no sleep needed
if ! run "slay $nm"; then
break;
fi
done
}
test_one()
{
type=$1
shift
nm=$1
shift
args=$*
type=$1
shift
nm=$1
shift
args=$*
say "Add service stanza in $FINIT_CONF"
run "echo service log:stderr oncrash:script post:/bin/post.sh $nm $args > $FINIT_CONF"
say "Add service stanza in $FINIT_CONF"
run "echo service log:stderr oncrash:script post:/bin/post.sh $nm $args > $FINIT_CONF"
say 'Reload Finit'
run "initctl reload"
say 'Reload Finit'
run "initctl reload"
if [ "$type" = "sig" ]; then
retry "assert_num_children 1 $nm"
run "initctl status $nm"
crashit "$nm"
fi
if [ "$type" = "sig" ]; then
retry "assert_num_children 1 $nm"
run "initctl status $nm"
crashit "$nm"
fi
retry "assert_status $nm crashed" 500
run "cat /tmp/post"
assert_file_contains "/tmp/post" "POST"
run "rm -f /tmp/post"
retry "assert_status $nm crashed" 500
run "cat /tmp/post"
assert_file_contains "/tmp/post" "POST"
run "rm -f /tmp/post"
}
# shellcheck source=/dev/null
+30 -30
View File
@@ -16,15 +16,15 @@ TEST_DIR=$(dirname "$0")
test_setup()
{
say "Test start $(date)"
say "Test start $(date)"
}
test_teardown()
{
say "Test done $(date)"
say "Running test teardown."
say "Test done $(date)"
say "Running test teardown."
run "rm -f $FINIT_CONF" "/tmp/post"
run "rm -f $FINIT_CONF" "/tmp/post"
}
# shellcheck source=/dev/null
@@ -35,36 +35,36 @@ test_teardown()
test_one()
{
cond=$1
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:bar \<!$cond\> serv -np -i bar -F /tmp/arrakis >> $FINIT_CONF"
run "cat $FINIT_CONF"
cond=$1
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:bar \<!$cond\> serv -np -i bar -F /tmp/arrakis >> $FINIT_CONF"
run "cat $FINIT_CONF"
say 'Reload Finit'
run "initctl reload"
say 'Reload Finit'
run "initctl reload"
run "initctl status"
assert_status "foo" "running"
assert_cond "$cond"
assert_status "bar" "running"
run "initctl status"
assert_status "foo" "running"
assert_cond "$cond"
assert_status "bar" "running"
say "Verify bar is restarted when foo is ..."
pid=$(texec initctl |grep bar | awk '{print $1;}')
run "initctl restart foo"
run "initctl status"
assert "bar is restarted" "$(texec initctl |grep bar | awk '{print $1;}')" != "$pid"
say "Verify bar is restarted when foo is ..."
pid=$(texec initctl |grep bar | awk '{print $1;}')
run "initctl restart foo"
run "initctl status"
assert "bar is restarted" "$(texec initctl |grep bar | awk '{print $1;}')" != "$pid"
# Wait for spice to be stolen by the Harkonnen
sleep 3
# bar should now have detected the loss of spice and be in restart
run "initctl status"
assert_status "bar" "restart"
# verify bar is stopped->waiting and no longer in restart after stopping foo
run "initctl stop foo"
run "initctl status"
run "initctl status bar"
assert_status "bar" "waiting"
# Wait for spice to be stolen by the Harkonnen
sleep 3
# bar should now have detected the loss of spice and be in restart
run "initctl status"
assert_status "bar" "restart"
# verify bar is stopped->waiting and no longer in restart after stopping foo
run "initctl stop foo"
run "initctl status"
run "initctl status bar"
assert_status "bar" "waiting"
}
sep
+22 -22
View File
@@ -9,52 +9,52 @@ TEST_DIR=$(dirname "$0")
test_setup()
{
say "Test start $(date)"
say "Test start $(date)"
}
test_teardown()
{
say "Test done $(date)"
say "Running test teardown."
say "Test done $(date)"
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
# touch is close enough for our needs
mkdev()
{
dir=$(dirname "$1")
run "mkdir -p $dir"
run "touch $1"
dir=$(dirname "$1")
run "mkdir -p $dir"
run "touch $1"
}
rmdev()
{
run "rm $1"
run "rm $1"
}
test_one()
{
cond="$1"
node="/$cond"
cond="$1"
node="/$cond"
say "Checking cond $cond and device $node ..."
run "echo service log:null \<$cond\> serv -np >> $FINIT_CONF"
run "cat $FINIT_CONF"
run "initctl reload"
say "Checking cond $cond and device $node ..."
run "echo service log:null \<$cond\> serv -np >> $FINIT_CONF"
run "cat $FINIT_CONF"
run "initctl reload"
assert_status "serv" "waiting"
assert_status "serv" "waiting"
mkdev "$node"
assert_status "serv" "running"
mkdev "$node"
assert_status "serv" "running"
rmdev "$node"
assert_status "serv" "waiting"
rmdev "$node"
assert_status "serv" "waiting"
say "Cleaning up ..."
run "rm $FINIT_CONF"
run "initctl reload"
say "Cleaning up ..."
run "rm $FINIT_CONF"
run "initctl reload"
}
# shellcheck source=/dev/null
+5 -5
View File
@@ -8,16 +8,16 @@ TEST_DIR=$(dirname "$0")
test_setup()
{
say "Test start $(date)"
run "mkdir -p /etc/default"
say "Test start $(date)"
run "mkdir -p /etc/default"
}
test_teardown()
{
say "Test done $(date)"
say "Test done $(date)"
say "Running test teardown."
run "rm -f $FINIT_CONF"
say "Running test teardown."
run "rm -f $FINIT_CONF"
}
# shellcheck source=/dev/null
+4 -4
View File
@@ -5,15 +5,15 @@ TEST_DIR=$(dirname "$0")
test_setup()
{
say "Test start $(date)"
say "Test start $(date)"
}
test_teardown()
{
say "Test done $(date)"
say "Test done $(date)"
say "Running test teardown."
run "rm -f $FINIT_CONF"
say "Running test teardown."
run "rm -f $FINIT_CONF"
}
# shellcheck source=/dev/null
+8 -8
View File
@@ -9,28 +9,28 @@ TEST_DIR=$(dirname "$0")
test_setup()
{
say "Test start $(date)"
say "Test start $(date)"
}
test_teardown()
{
say "Test done $(date)"
say "Test done $(date)"
say "Running test teardown."
run "rm -f $FINIT_CONF"
say "Running test teardown."
run "rm -f $FINIT_CONF"
}
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()
{
service=$1
service=$1
say "Add service stanza '$service' to $FINIT_CONF ..."
run "echo '$service' >> $FINIT_CONF"
say "Add service stanza '$service' to $FINIT_CONF ..."
run "echo '$service' >> $FINIT_CONF"
}
# shellcheck source=/dev/null
+7 -7
View File
@@ -4,10 +4,10 @@ set -eu
cmd=""
if [ "$#" -lt 1 ]; then
cmd="/bin/sh"
cmd="/bin/sh"
else
cmd=$1
shift
cmd=$1
shift
fi
TEST_DIR=$(dirname "$0")/..
@@ -15,11 +15,11 @@ SYSROOT="${SYSROOT:-$(pwd)/${TEST_DIR}/sysroot}"
PID_FILE="$SYSROOT/running_test.pid"
if [ -f "$PID_FILE" ] ; then
target=$(cat "$PID_FILE")
target=$(pgrep -P "$target")
target=$(cat "$PID_FILE")
target=$(pgrep -P "$target")
else
echo "No test running!"
exit 1
echo "No test running!"
exit 1
fi
# shellcheck disable=SC1091
+12 -12
View File
@@ -24,9 +24,9 @@
set -eu
if [ "$#" -lt 2 ]; then
echo "Usage:"
echo " $0 [target-pid] [command [arguments]]"
exit 1
echo "Usage:"
echo " $0 [target-pid] [command [arguments]]"
exit 1
fi
target="$1"
shift
@@ -46,12 +46,12 @@ PATH="$TESTENV_PATH"
export PATH
"$nsenter" \
--preserve-credentials \
--user \
--mount \
--uts \
--ipc \
--net \
--pid \
-w -t "$target" \
"$chroot" "$SYSROOT" "$@"
--preserve-credentials \
--user \
--mount \
--uts \
--ipc \
--net \
--pid \
-w -t "$target" \
"$chroot" "$SYSROOT" "$@"
+9 -9
View File
@@ -334,7 +334,7 @@ echo "$finit_ppid" > "$SYSROOT"/running_test.pid
log "$color_reset" 'Setup of test environment done, waiting for Finit ...' ''
finit_pid=$(retry "pgrep -P $finit_ppid")
echo "Finit running as $finit_pid"
echo "Finit running as PID $finit_pid"
#tty=/dev/$(texec cat /sys/class/tty/console/active)
#texec cat "$tty" &
@@ -342,17 +342,17 @@ echo "Finit running as $finit_pid"
i=0
set +u
while [ -z "$BOOTSTRAP" ] && [ $i -lt 10 ]; do
lvl=$(texec sh -c "initctl runlevel | awk '{print \$2;}'")
if [ "$lvl" = "$FINIT_RUNLEVEL" ]; then
say "Reached runlevel $FINIT_RUNLEVEL, releasing test."
break;
fi
i=$((i + 1))
sleep 1
lvl=$(texec sh -c "initctl runlevel | awk '{print \$2;}'")
if [ "$lvl" = "$FINIT_RUNLEVEL" ]; then
say "Reached runlevel $FINIT_RUNLEVEL, releasing test."
break;
fi
i=$((i + 1))
sleep 1
done
set -u
if type test_setup > /dev/null 2>&1 ; then
test_setup
test_setup
fi
wdstart $TEST_TIMEOUT
+18 -18
View File
@@ -8,16 +8,16 @@ TEST_DIR=$(dirname "$0")
test_setup()
{
say "Test start $(date)"
run "mkdir -p /etc/default"
say "Test start $(date)"
run "mkdir -p /etc/default"
}
test_teardown()
{
say "Test done $(date)"
say "Running test teardown."
say "Test done $(date)"
say "Running test teardown."
run "rm -f $FINIT_CONF"
run "rm -f $FINIT_CONF"
}
test_one()
@@ -37,11 +37,11 @@ test_one()
run "initctl reload"
sleep 1
# run "initctl status serv"
# run "initctl status serv"
assert_status "serv" "running"
sleep 2
# run "initctl cond dump"
# run "initctl cond dump"
assert_cond "service/serv/ready"
say "Verify 'ready' is set after SIGHUP ..."
@@ -52,7 +52,7 @@ test_one()
# Issue #343
say "Verify 'ready' is reasserted if service crashes and is restarted ..."
# run "initctl status serv"
# run "initctl status serv"
run "initctl signal serv 9"
retry 'assert_status "serv" "running"' 2 1
retry 'assert_cond "service/serv/ready"' 3 1
@@ -67,7 +67,7 @@ test_one()
say "Verify 'ready' is reasserted on 'initctl reload' ..."
run "initctl reload"
sleep 1
# run "initctl; initctl cond dump"
# run "initctl; initctl cond dump"
assert_status "serv" "running"
assert_cond "service/serv/ready"
@@ -75,12 +75,12 @@ test_one()
# 'started' when they created their PID file. The serv test daemon
# waits 3 sec between pidfile and notify to trigger this bug.
if [ "$type" != "native" ]; then
say "Verify 'ready' is *not* asserted immediately on restart + reload"
run "initctl restart serv"
run "initctl reload"
sleep 1
assert_nocond "service/serv/ready"
retry 'assert_cond "service/serv/ready"' 5 0.5
say "Verify 'ready' is *not* asserted immediately on restart + reload"
run "initctl restart serv"
run "initctl reload"
sleep 1
assert_nocond "service/serv/ready"
retry 'assert_cond "service/serv/ready"' 5 0.5
fi
say "Verify 'ready' is deasserted on stop ..."
@@ -93,9 +93,9 @@ test_one()
run "rm -f $FINIT_CONF"
run "initctl reload"
# sleep 2
# num=$(run "find /proc/1/fd |wc -l")
# say "finit: number of open file descriptors after test: $num"
# sleep 2
# num=$(run "find /proc/1/fd |wc -l")
# say "finit: number of open file descriptors after test: $num"
}
# shellcheck source=/dev/null
+14 -14
View File
@@ -7,32 +7,32 @@ TEST_DIR=$(dirname "$0")
test_setup()
{
say "Test start $(date)"
say "Test start $(date)"
}
test_teardown()
{
say "Test done $(date)"
say "Running test teardown."
say "Test done $(date)"
say "Running test teardown."
run "rm -f $FINIT_CONF" "/tmp/post"
run "rm -f $FINIT_CONF" "/tmp/post"
}
test_one()
{
pidfn=$1
service=$2
pidfn=$1
service=$2
sep
say "Add service stanza '$service' to $FINIT_CONF ..."
run "echo '$service' > $FINIT_CONF"
run "initctl reload"
sep
say "Add service stanza '$service' to $FINIT_CONF ..."
run "echo '$service' > $FINIT_CONF"
run "initctl reload"
assert_is_pidfile "serv" "$pidfn"
assert_is_pidfile "serv" "$pidfn"
say "Done, drop service from $FINIT_CONF ..."
run "rm $FINIT_CONF"
run "initctl reload"
say "Done, drop service from $FINIT_CONF ..."
run "rm $FINIT_CONF"
run "initctl reload"
}
# shellcheck source=/dev/null
+28 -28
View File
@@ -5,49 +5,49 @@ TEST_DIR=$(dirname "$0")
test_setup()
{
say "Test start $(date)"
say "Test start $(date)"
}
test_teardown()
{
say "Test done $(date)"
say "Test done $(date)"
say "Running test teardown."
run "rm -f $FINIT_CONF"
say "Running test teardown."
run "rm -f $FINIT_CONF"
}
test_one()
{
pre=$1
precont=$2
service=$3
post=$4
postcont=$5
pre=$1
precont=$2
service=$3
post=$4
postcont=$5
say "Add service stanza '$service' to $FINIT_CONF ..."
run "echo '$service' > $FINIT_CONF"
say "Add service stanza '$service' to $FINIT_CONF ..."
run "echo '$service' > $FINIT_CONF"
say 'Reload Finit'
run "initctl reload"
say 'Reload Finit'
run "initctl reload"
retry 'assert_num_children 1 serv'
if [ -n "$pre" ]; then
assert_file_contains "$pre" "$precont"
run "rm -f $pre"
fi
retry 'assert_num_children 1 serv'
if [ -n "$pre" ]; then
assert_file_contains "$pre" "$precont"
run "rm -f $pre"
fi
say 'Stop the service'
run "initctl stop serv"
say 'Stop the service'
run "initctl stop serv"
retry 'assert_num_children 0 serv'
if [ -n "$post" ]; then
assert_file_contains "$post" "$postcont"
run "rm -f $post"
fi
retry 'assert_num_children 0 serv'
if [ -n "$post" ]; then
assert_file_contains "$post" "$postcont"
run "rm -f $post"
fi
say "Done, drop service from $FINIT_CONF ..."
run "rm $FINIT_CONF"
run "initctl reload"
say "Done, drop service from $FINIT_CONF ..."
run "rm $FINIT_CONF"
run "initctl reload"
}
# shellcheck source=/dev/null
+2 -2
View File
@@ -12,12 +12,12 @@ RCLOCAL="echo 'KILROY WAS HERE' > /tmp/rclocal"
test_setup()
{
say "Test start $(date)"
say "Test start $(date)"
}
test_teardown()
{
say "Test done $(date)"
say "Test done $(date)"
}
sleep 1
+19 -19
View File
@@ -6,39 +6,39 @@ TEST_DIR=$(dirname "$0")
test_setup()
{
say "Test start $(date)"
say "Test start $(date)"
}
test_teardown()
{
say "Test done $(date)"
say "Test done $(date)"
say "Running test teardown."
run "rm -f $FINIT_CONF"
say "Running test teardown."
run "rm -f $FINIT_CONF"
}
test_one()
{
service=$1
file=/tmp/ready
service=$1
file=/tmp/ready
say "Add service stanza '$service' to $FINIT_CONF ..."
run "echo '$service' > $FINIT_CONF"
say "Add service stanza '$service' to $FINIT_CONF ..."
run "echo '$service' > $FINIT_CONF"
say 'Reload Finit'
run "initctl reload"
say 'Reload Finit'
run "initctl reload"
retry 'assert_num_children 1 serv'
assert_file_contains "$file" "READY"
run "rm -f $file"
retry 'assert_num_children 1 serv'
assert_file_contains "$file" "READY"
run "rm -f $file"
say 'Stop the service'
run "initctl stop serv"
retry 'assert_num_children 0 serv'
say 'Stop the service'
run "initctl stop serv"
retry 'assert_num_children 0 serv'
say "Done, drop service from $FINIT_CONF ..."
run "rm $FINIT_CONF"
run "initctl reload"
say "Done, drop service from $FINIT_CONF ..."
run "rm $FINIT_CONF"
run "initctl reload"
}
# shellcheck source=/dev/null
+6 -6
View File
@@ -6,21 +6,21 @@ TEST_DIR=$(dirname "$0")
test_setup()
{
say "Test start $(date)"
run "mkdir -p /etc/default"
say "Test start $(date)"
run "mkdir -p /etc/default"
}
test_teardown()
{
say "Test done $(date)"
say "Test done $(date)"
say "Running test teardown."
run "rm -f $FINIT_CONF"
say "Running test teardown."
run "rm -f $FINIT_CONF"
}
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()
{
say "Test start $(date)"
run "mkdir -p /etc/default"
export TEST_TIMEOUT=5
say "Test start $(date)"
run "mkdir -p /etc/default"
export TEST_TIMEOUT=5
}
test_teardown()
{
say "Test done $(date)"
say "Test done $(date)"
say "Running test teardown."
run "rm -f $FINIT_CONF"
say "Running test teardown."
run "rm -f $FINIT_CONF"
}
# shellcheck source=/dev/null
+3 -3
View File
@@ -9,12 +9,12 @@ FINIT_RUNLEVEL=9
test_setup()
{
say "Test start $(date)"
say "Test start $(date)"
}
test_teardown()
{
say "Test done $(date)"
say "Test done $(date)"
}
# shellcheck source=/dev/null
@@ -23,7 +23,7 @@ test_teardown()
say 'Check runlevel'
lvl=$(run "initctl runlevel | awk '{print \$2;}'")
if [ "$lvl" -eq "9" ]; then
return 0
return 0
fi
return 1
+2 -2
View File
@@ -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"
+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.
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
# Drop system .conf files we don't need in test, same as above
for conf in hotplug.conf; do
find "$SYSROOT" -name $conf -delete
find "$SYSROOT" -name $conf -delete
done
+3 -3
View File
@@ -7,10 +7,10 @@ TEST_DIR=$(dirname "$0")
test_teardown()
{
say "Test done $(date)"
say "Test done $(date)"
say "Running test teardown."
run "rm -f $FINIT_CONF"
say "Running test teardown."
run "rm -f $FINIT_CONF"
}
# shellcheck source=/dev/null
+32 -31
View File
@@ -2,50 +2,51 @@
nm=$1
# shellcheck disable=SC2046
getpid()
{
initctl status "$1" |awk '/PID :/{ print $3; }'
initctl status "$1" |awk '/PID :/{ print $3; }'
}
pid=$(getpid "$nm")
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
echo "Looks bad, wait for it ..."
sleep 3
pid=$(getpid "$nm")
if [ "$oldpid" = "$pid" ]; then
echo "Finit did not deregister old PID $oldpid vs $pid"
initctl status "$nm"
ps
echo "Reloading finit ..."
initctl reload
sleep 1
initctl status "$nm"
exit 1
fi
echo "Finit did not deregister old PID $oldpid vs $pid"
initctl status "$nm"
ps
echo "Reloading finit ..."
initctl reload
sleep 1
initctl status "$nm"
exit 1
fi
fi
fi
timeout=50
while [ "$pid" -le 1 ]; do
sleep 0.1
pid=$(getpid "$nm")
if [ "$pid" -le 1 ]; then
timeout=$((timeout - 1))
if [ "$timeout" -gt 0 ]; then
continue
fi
echo "Got a bad PID: $pid, aborting ..."
ps
sleep 1
initctl status "$nm"
ps
exit 1
sleep 0.1
pid=$(getpid "$nm")
if [ "$pid" -le 1 ]; then
timeout=$((timeout - 1))
if [ "$timeout" -gt 0 ]; then
continue
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
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
+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()
{
say "Test done $(date)"
say "Test done $(date)"
say "Running test teardown."
run "rm -f $FINIT_CONF"
say "Running test teardown."
run "rm -f $FINIT_CONF"
}
# shellcheck source=/dev/null
@@ -35,9 +35,9 @@ say 'Simulate service crash (kill -9 ..)'
i=0
laps=1000
while [ $i -lt $laps ]; do
i=$((i + 1))
say "Lap $i/$laps, killing service ..." # we have this, no sleep needed
run "slay service.sh"
i=$((i + 1))
say "Lap $i/$laps, killing service ..." # we have this, no sleep needed
run "slay service.sh"
done
retry 'assert_new_pid service.sh /run/service.pid'
+27 -27
View File
@@ -5,51 +5,51 @@ TEST_DIR=$(dirname "$0")
test_setup()
{
say "Test start $(date)"
say "Test start $(date)"
}
test_teardown()
{
say "Test done $(date)"
say "Test done $(date)"
say "Running test teardown."
run "rm -f $FINIT_CONF"
say "Running test teardown."
run "rm -f $FINIT_CONF"
}
test_one()
{
pidfn=$1
service=$2
pidfn=$1
service=$2
say "Add service stanza '$service' to $FINIT_CONF ..."
run "echo '$service' > $FINIT_CONF"
say "Add service stanza '$service' to $FINIT_CONF ..."
run "echo '$service' > $FINIT_CONF"
say 'Reload Finit'
#run "initctl debug"
run "initctl reload"
#run "initctl status"
#run "ps"
say 'Reload Finit'
#run "initctl debug"
run "initctl reload"
#run "initctl status"
#run "ps"
#run "initctl status"
#run "ps"
#run "initctl status serv"
#run "initctl status"
#run "ps"
#run "initctl status serv"
retry 'assert_num_children 1 serv'
retry "assert_has_pidfile $pidfn" 1
retry 'assert_num_children 1 serv'
retry "assert_has_pidfile $pidfn" 1
say 'Stop the service'
run "initctl stop serv"
say 'Stop the service'
run "initctl stop serv"
retry 'assert_num_children 0 serv'
retry 'assert_num_children 0 serv'
say 'Start the service again'
run "initctl start serv"
say 'Start the service again'
run "initctl start serv"
retry 'assert_num_children 1 serv'
retry 'assert_num_children 1 serv'
say "Done, drop service from $FINIT_CONF ..."
run "rm $FINIT_CONF"
run "initctl reload"
say "Done, drop service from $FINIT_CONF ..."
run "rm $FINIT_CONF"
run "initctl reload"
}
# shellcheck source=/dev/null
+3 -3
View File
@@ -6,10 +6,10 @@ TEST_DIR=$(dirname "$0")
test_teardown()
{
say "Test done $(date)"
say "Test done $(date)"
say "Running test teardown."
run "rm -f $FINIT_RCSD/service.conf"
say "Running test teardown."
run "rm -f $FINIT_RCSD/service.conf"
}
# shellcheck source=/dev/null
+3 -3
View File
@@ -6,10 +6,10 @@ TEST_DIR=$(dirname "$0")
test_teardown()
{
say "Test done $(date)"
say "Test done $(date)"
say "Running test teardown."
run "rm -f $FINIT_CONF"
say "Running test teardown."
run "rm -f $FINIT_CONF"
}
# shellcheck source=/dev/null
+3 -3
View File
@@ -6,10 +6,10 @@ TEST_DIR=$(dirname "$0")
test_teardown()
{
say "Test done $(date)"
say "Test done $(date)"
say "Running test teardown."
run "rm -f $FINIT_CONF"
say "Running test teardown."
run "rm -f $FINIT_CONF"
}
# 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"
+1 -1
View File
@@ -11,4 +11,4 @@ d /run/finit/cond 0755 - - -
d /run/finit/cond/pid 0755 - - -
d /run/finit/cond/sys 0755 - - -
d /run/finit/cond/usr 0755 - - -
d /run/finit/system 0755 - - -