mirror of
https://github.com/troglobit/finit.git
synced 2026-10-13 10:14:47 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fca5ce57ea | ||
|
|
53aa195ad5 | ||
|
|
e60211168e | ||
|
|
dc3ee9e467 | ||
|
|
6918f3b711 | ||
|
|
66020f48ea | ||
|
|
47b0d4cccf | ||
|
|
92c2efa655 | ||
|
|
b69aa8a8bd | ||
|
|
ca90bbfb04 | ||
|
|
0b5c555c7f | ||
|
|
6443995fc9 | ||
|
|
180faf8a40 | ||
|
|
0ebdd32f6b | ||
|
|
60bf858302 | ||
|
|
7c86b40190 | ||
|
|
4f3f140a09 | ||
|
|
10c24b1674 | ||
|
|
2b4f89ecd1 | ||
|
|
c42a6f2869 | ||
|
|
89bb609a7e | ||
|
|
da6298aecd | ||
|
|
576318cc29 | ||
|
|
0d7d331ad4 | ||
|
|
c886ecb5cc | ||
|
|
304a096877 | ||
|
|
064c7682fc | ||
|
|
58239b897b | ||
|
|
5281d82e80 | ||
|
|
5ff28c4dc6 | ||
|
|
f2218836af | ||
|
|
fbb3779d17 | ||
|
|
68f44f7a97 | ||
|
|
50e587f447 | ||
|
|
fb4c560196 | ||
|
|
8b5fa5eeaa | ||
|
|
88ec21e9cc | ||
|
|
84adec4006 | ||
|
|
19b2b2a279 | ||
|
|
e4163b7221 | ||
|
|
eaef302420 | ||
|
|
d5738da307 | ||
|
|
c9f930c7ad | ||
|
|
e2ee372b5d | ||
|
|
7ff7f93364 | ||
|
|
d5a95760ef | ||
|
|
24d1425b74 | ||
|
|
43d9e25ba7 | ||
|
|
f27998ae4f | ||
|
|
c8e0b6b9ef | ||
|
|
f7e8fccb2f | ||
|
|
7bbccb1213 | ||
|
|
d38c333e04 | ||
|
|
095f6b645c | ||
|
|
b4d10cbade | ||
|
|
5d703fd39e | ||
|
|
eaaf8d862e | ||
|
|
2468f11cd8 | ||
|
|
f8a6a119ac | ||
|
|
1889b88aab | ||
|
|
0d70023bfe | ||
|
|
41648a073b | ||
|
|
33cee0ba5f | ||
|
|
2235fb8352 | ||
|
|
eb9e94935e | ||
|
|
fb230f2137 | ||
|
|
6aa48a8b32 | ||
|
|
5b9cebbfd3 | ||
|
|
38791616e0 | ||
|
|
fede3fd2e1 | ||
|
|
a46a33238d | ||
|
|
afe0488bf2 | ||
|
|
ec5e42694d | ||
|
|
2e73563eea | ||
|
|
338521a748 | ||
|
|
6ae1083c99 | ||
|
|
846806747b | ||
|
|
8904ca993e | ||
|
|
efed0db16b | ||
|
|
11946f12d3 | ||
|
|
2ba359ed80 | ||
|
|
fafd524701 | ||
|
|
1ee6c9f46b | ||
|
|
a88eb82a68 | ||
|
|
a436a1c8cb |
@@ -10,12 +10,29 @@ 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]+\.[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 ...
|
- name: Creating Makefiles ...
|
||||||
run: |
|
run: |
|
||||||
./autogen.sh
|
./autogen.sh
|
||||||
@@ -36,5 +53,7 @@ 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: ${{ steps.build.outputs.pre }}
|
||||||
|
makeLatest: ${{ steps.build.outputs.latest }}
|
||||||
bodyFile: "release.md"
|
bodyFile: "release.md"
|
||||||
artifacts: "artifacts/*"
|
artifacts: "artifacts/*"
|
||||||
|
|||||||
+91
-7
@@ -4,44 +4,127 @@ Change Log
|
|||||||
All relevant changes are documented in this file.
|
All relevant changes are documented in this file.
|
||||||
|
|
||||||
|
|
||||||
[4.5][] - 2023-09-15
|
[4.6][] - 2023-11-13
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
### Changes
|
||||||
|
- Add support for service `notify:pid` and `readiness none` global
|
||||||
|
option to change how Finit expects readiness notification, issue #386
|
||||||
|
|
||||||
|
### Fixes
|
||||||
|
- Fix #383: dbus and runparts regression in Finit v4.5. The configure
|
||||||
|
script must expand `FINIT_RUNPATH_` before defining it in `config.h`
|
||||||
|
- Fix #384: service environment variables drop everything but the first
|
||||||
|
argument, e.g., `VAR="foo bar qux"` drops everything but `foo`
|
||||||
|
- Fix #385: internal conditions, e.g., `<int/bootstrap>` turn into flux
|
||||||
|
when leaving bootstrap, causing depending services to stop
|
||||||
|
- Fix #387: global environment variables declared with `set VAR=NAME` do
|
||||||
|
not drop leading `set `, causing `'set VAR'='NAME'` in env.
|
||||||
|
- Sanity check environment variables, for services and globally. Ensure
|
||||||
|
the variable name (key) does not contain spaces, or a leading `set `
|
||||||
|
|
||||||
|
|
||||||
|
[4.5][] - 2023-10-30
|
||||||
--------------------
|
--------------------
|
||||||
|
|
||||||
### 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`
|
||||||
- Add support for Bash completion to `initctl`, issue #360
|
- Add Bash completion support for `initctl`, configurable, issue #360
|
||||||
- Handle absolute path to `initctl [enable|disable]`, not supported
|
- Handle absolute path to `initctl [enable|disable]`, not supported
|
||||||
- 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
|
||||||
|
- 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
|
||||||
|
- Redirect `log*` output to console when `finit.debug` is enabled
|
||||||
|
- Assert `<int/container>` condition if we detect running in container
|
||||||
|
- Add support for mdev's netlink daemon mode, issue #367
|
||||||
|
- Add support for mdevd in `10-hotplug.conf`, preferred over plain mdev
|
||||||
|
- Disable modprobe plugin by default, udevd and mdev/mdevd loads modules
|
||||||
|
- Update documentation for run/task shell limitations, issue #376
|
||||||
|
- Update documentation regarding automount of `/run` and `/tmp`
|
||||||
|
- Update plugin documentation, add section about limited tmpfiles.d(5) support
|
||||||
|
- Skip registering service when `if:!name` matches a known service.
|
||||||
|
This allows conditional loading of alternative services, e.g. if udevd
|
||||||
|
is already loaded we do not need mdevd
|
||||||
|
- Drop `doc/bootstrap.md`, inaccurate and confusing to users
|
||||||
|
|
||||||
### 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.
|
||||||
|
- 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
|
||||||
|
- Adjust final `udevadm settle` timeout: 5 -> 30 sec
|
||||||
|
- 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` 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.
|
||||||
|
- Fix #377: expand service `env:file` variables, allow constructs like:
|
||||||
|
|
||||||
|
RUNDIR=/var/run/somesvc
|
||||||
|
DAEMON_ARGS=--workdir $RUNDIR --other-args...
|
||||||
|
- Fix #378: warn on console if run/task times out during bootstrap
|
||||||
|
- Fix #378: add run/task support for `<!>` to allow transition from
|
||||||
|
bootstrap to multi-user runlevel even though task has not run yet.
|
||||||
|
- Fix #382: do not clear `<service/foo/STATE>` conditions on reload.
|
||||||
|
Introduced back in v4.3-rc2, 82cc10be8, the support for automatic
|
||||||
|
service conditions have had a weird and unintended behavior. Any
|
||||||
|
change in state (see `doc/svc-machine.png`) caused Finit to clear
|
||||||
|
out *all* previously acquired service conditions.
|
||||||
|
|
||||||
|
However, when moving between RUNNING and PAUSED states, a service
|
||||||
|
should not have its conditions cleared. The PAUSED state, seen
|
||||||
|
also by all conditions moving to FLUX, is only temporary while an
|
||||||
|
`initctl reload` is processed. If a service has no changes to be
|
||||||
|
applied it will move back to RUNNING.
|
||||||
|
|
||||||
|
Also, we cannot clear the service conditions because other run/task
|
||||||
|
or services may depend on it and clearing them would cause Finit to
|
||||||
|
`SIGTERM` these processes (since they are no longer eligible to run).
|
||||||
|
|
||||||
|
|
||||||
[4.4][] - 2023-05-15
|
[4.4][] - 2023-05-15
|
||||||
@@ -1550,7 +1633,8 @@ Major bug fix release.
|
|||||||
|
|
||||||
* Initial release
|
* Initial release
|
||||||
|
|
||||||
[UNRELEASED]: https://github.com/troglobit/finit/compare/4.5...HEAD
|
[UNRELEASED]: https://github.com/troglobit/finit/compare/4.6...HEAD
|
||||||
|
[4.6]: https://github.com/troglobit/finit/compare/4.5...4.6
|
||||||
[4.5]: https://github.com/troglobit/finit/compare/4.4...4.5
|
[4.5]: https://github.com/troglobit/finit/compare/4.4...4.5
|
||||||
[4.4]: https://github.com/troglobit/finit/compare/4.3...4.4
|
[4.4]: https://github.com/troglobit/finit/compare/4.3...4.4
|
||||||
[4.3]: https://github.com/troglobit/finit/compare/4.2...4.3
|
[4.3]: https://github.com/troglobit/finit/compare/4.2...4.3
|
||||||
|
|||||||
+8
-3
@@ -10,6 +10,10 @@ if DOC
|
|||||||
SUBDIRS += doc
|
SUBDIRS += doc
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
if BASH
|
||||||
|
bashdir = $(BASH_DIR)
|
||||||
|
dist_bash_DATA = initctl
|
||||||
|
endif
|
||||||
# Compat hook
|
# Compat hook
|
||||||
install-dev:
|
install-dev:
|
||||||
@make -C src install-pkgincludeHEADERS
|
@make -C src install-pkgincludeHEADERS
|
||||||
@@ -30,6 +34,7 @@ release: distcheck
|
|||||||
printf "$$file.sha256\t"; cat ../$$file.sha256 | cut -f1 -d' '; \
|
printf "$$file.sha256\t"; cat ../$$file.sha256 | cut -f1 -d' '; \
|
||||||
done
|
done
|
||||||
|
|
||||||
DISTCHECK_CONFIGURE_FLAGS = --prefix=/usr --sysconfdir=/etc --localstatedir=/var \
|
DISTCHECK_CONFIGURE_FLAGS = --prefix=/usr --sysconfdir=/etc --localstatedir=/var \
|
||||||
--enable-testserv-plugin --enable-x11-common-plugin \
|
--enable-testserv-plugin --enable-x11-common-plugin \
|
||||||
--with-watchdog --with-keventd --with-fstab=/etc/fstab
|
--with-watchdog --with-keventd --with-fstab=/etc/fstab \
|
||||||
|
--with-bash-completion-dir=no
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
|
|
||||||
* [Introduction](#introduction)
|
* [Introduction](#introduction)
|
||||||
* [Features](#features)
|
* [Features](#features)
|
||||||
* [Bootstrap](doc/bootstrap.md#bootstrap)
|
|
||||||
* [Runlevels](#runlevels)
|
* [Runlevels](#runlevels)
|
||||||
* [Syntax](doc/config.md#syntax)
|
* [Syntax](doc/config.md#syntax)
|
||||||
* [Runparts & /etc/rc.local](#runparts--etcrclocal)
|
* [Runparts & /etc/rc.local](#runparts--etcrclocal)
|
||||||
@@ -391,8 +390,7 @@ Right after the runlevel change when all services have started properly,
|
|||||||
No configuration stanza in `/etc/finit.conf` is required for `rc.local`.
|
No configuration stanza in `/etc/finit.conf` is required for `rc.local`.
|
||||||
If it exists and is an executable shell script Finit calls it at the very
|
If it exists and is an executable shell script Finit calls it at the very
|
||||||
end of the boot, before calling the `HOOK_SYSTEM_UP`. See more on hooks
|
end of the boot, before calling the `HOOK_SYSTEM_UP`. See more on hooks
|
||||||
in [doc/plugins.md](doc/plugins.md#hooks), and about the system bootstrap
|
in [doc/plugins.md](doc/plugins.md#hooks).
|
||||||
in [doc/bootstrap.md](doc/bootstrap.md).
|
|
||||||
|
|
||||||
|
|
||||||
### Limitations
|
### Limitations
|
||||||
|
|||||||
+33
-10
@@ -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.6], [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])
|
||||||
@@ -14,10 +15,10 @@ AC_CONFIG_FILES([Makefile
|
|||||||
man/Makefile
|
man/Makefile
|
||||||
plugins/Makefile
|
plugins/Makefile
|
||||||
src/Makefile
|
src/Makefile
|
||||||
system/Makefile
|
system/Makefile system/10-hotplug.conf
|
||||||
tmpfiles.d/Makefile
|
|
||||||
test/test.env test/Makefile
|
test/test.env test/Makefile
|
||||||
test/lib/Makefile test/src/Makefile])
|
test/lib/Makefile test/src/Makefile
|
||||||
|
tmpfiles.d/Makefile])
|
||||||
|
|
||||||
# Older versions of autoconf (<2.58) do not have AC_CONFIG_MACRO_DIR()
|
# Older versions of autoconf (<2.58) do not have AC_CONFIG_MACRO_DIR()
|
||||||
#m4_include([m4/plugin.m4])
|
#m4_include([m4/plugin.m4])
|
||||||
@@ -93,18 +94,22 @@ AC_ARG_ENABLE(all_plugins,
|
|||||||
AC_PLUGIN([alsa-utils], [no], [Save and restore ALSA sound settings using alsactl])
|
AC_PLUGIN([alsa-utils], [no], [Save and restore ALSA sound settings using alsactl])
|
||||||
AC_PLUGIN([dbus], [no], [Setup and start system message bus, D-Bus])
|
AC_PLUGIN([dbus], [no], [Setup and start system message bus, D-Bus])
|
||||||
AC_PLUGIN([modules-load], [no], [Scans /etc/modules-load.d for modules to load])
|
AC_PLUGIN([modules-load], [no], [Scans /etc/modules-load.d for modules to load])
|
||||||
AC_PLUGIN([modprobe], [yes], [Coldplug modules using modalias magic])
|
AC_PLUGIN([modprobe], [no], [Coldplug modules using modalias magic])
|
||||||
AC_PLUGIN([resolvconf], [no], [Setup necessary files for resolvconf])
|
AC_PLUGIN([resolvconf], [no], [Setup necessary files for resolvconf])
|
||||||
AC_PLUGIN([x11-common], [no], [Console setup (for X)])
|
AC_PLUGIN([x11-common], [no], [Console setup (for X)])
|
||||||
AC_PLUGIN([netlink], [yes], [Basic netlink plugin for IFUP/IFDN and GW events. Can be replaced with externally built plugin that links with libnl or similar.])
|
AC_PLUGIN([netlink], [yes], [Basic netlink plugin for IFUP/IFDN and GW events. Can be replaced with externally built plugin that links with libnl or similar.])
|
||||||
AC_PLUGIN([hook-scripts], [no], [Trigger script execution from hook points])
|
AC_PLUGIN([hook-scripts], [no], [Trigger script execution from hook points])
|
||||||
AC_PLUGIN([hotplug], [yes], [Setup and start udev or mdev hotplug daemon])
|
AC_PLUGIN([hotplug], [yes], [Start udevd or mdev kernel event datamon])
|
||||||
AC_PLUGIN([rtc], [yes], [Save and restore RTC using hwclock])
|
AC_PLUGIN([rtc], [yes], [Save and restore RTC using hwclock])
|
||||||
AC_PLUGIN([tty], [yes], [Automatically activate new TTYs, e.g. USB-to-serial])
|
AC_PLUGIN([tty], [yes], [Automatically activate new TTYs, e.g. USB-to-serial])
|
||||||
AC_PLUGIN([urandom], [yes], [Setup and save random seed at boot/shutdown])
|
AC_PLUGIN([urandom], [yes], [Setup and save random seed at boot/shutdown])
|
||||||
AC_PLUGIN([testserv], [no], [Test plugin to start test serv daemon])
|
AC_PLUGIN([testserv], [no], [Test plugin to start test serv daemon])
|
||||||
|
|
||||||
# Check for extra arguments or packages
|
# Check for extra arguments or packages
|
||||||
|
AC_ARG_WITH([bash-completion-dir],
|
||||||
|
AS_HELP_STRING([--with-bash-completion-dir[=PATH]], [Directory to install Bash completion, default: auto]),
|
||||||
|
[bash_dir=$withval], [bash_dir=yes])
|
||||||
|
|
||||||
AC_ARG_WITH(fstab,
|
AC_ARG_WITH(fstab,
|
||||||
AS_HELP_STRING([--with-fstab=FILE], [System default fstab, default $sysconfdir/fstab]),
|
AS_HELP_STRING([--with-fstab=FILE], [System default fstab, default $sysconfdir/fstab]),
|
||||||
[fstab=$withval], [fstab=yes])
|
[fstab=$withval], [fstab=yes])
|
||||||
@@ -195,6 +200,12 @@ AS_IF([test "x$enable_rescue" != "xno"], [
|
|||||||
AM_CONDITIONAL(LOGROTATE, [test "x$enable_logrotate" = "xyes"])
|
AM_CONDITIONAL(LOGROTATE, [test "x$enable_logrotate" = "xyes"])
|
||||||
|
|
||||||
### With features ##############################################################################
|
### With features ##############################################################################
|
||||||
|
AS_IF([test "x$bash_dir" = "xyes"], [
|
||||||
|
PKG_CHECK_MODULES([BASH_COMPLETION], [bash-completion >= 2.0],
|
||||||
|
[BASH_DIR="$(pkg-config --variable=completionsdir bash-completion)"],
|
||||||
|
[BASH_DIR="$datadir/bash-completion/completions"])], [
|
||||||
|
BASH_DIR="$bash_dir"])
|
||||||
|
|
||||||
AS_IF([test "x$with_fstab" != "xno"], [
|
AS_IF([test "x$with_fstab" != "xno"], [
|
||||||
AS_IF([test "x$fstab" = "xyes"], [fstab=$sysconfdir/fstab])
|
AS_IF([test "x$fstab" = "xyes"], [fstab=$sysconfdir/fstab])
|
||||||
AC_EXPAND_DIR(fstab_path, "$fstab")
|
AC_EXPAND_DIR(fstab_path, "$fstab")
|
||||||
@@ -284,19 +295,27 @@ AS_IF([test "x$with_plugin_path" != "xno"], [
|
|||||||
AC_DEFINE_UNQUOTED(EXTERNAL_PLUGIN_PATH, "$plugin_path", [Built-in default: /usr/lib/finit/plugins:/usr/local/lib/finit/plugins])])
|
AC_DEFINE_UNQUOTED(EXTERNAL_PLUGIN_PATH, "$plugin_path", [Built-in default: /usr/lib/finit/plugins:/usr/local/lib/finit/plugins])])
|
||||||
|
|
||||||
# Control build with automake flags
|
# Control build with automake flags
|
||||||
AM_CONDITIONAL(STATIC, [test "x$enable_static" = "xyes"])
|
AM_CONDITIONAL(BASH, [test "x$bash_dir" != "xno"])
|
||||||
|
AM_CONDITIONAL(STATIC, [test "x$enable_static" = "xyes"])
|
||||||
AM_CONDITIONAL(KEVENTD, [test "x$with_keventd" != "xno"])
|
AM_CONDITIONAL(KEVENTD, [test "x$with_keventd" != "xno"])
|
||||||
AM_CONDITIONAL(SULOGIN, [test "x$with_sulogin" != "xno"])
|
AM_CONDITIONAL(SULOGIN, [test "x$with_sulogin" != "xno"])
|
||||||
AM_CONDITIONAL(WATCHDOGD, [test "x$with_watchdog" != "xno"])
|
AM_CONDITIONAL(WATCHDOGD, [test "x$with_watchdog" != "xno"])
|
||||||
AM_CONDITIONAL(DOC, [test "x$enable_doc" = "xyes"])
|
AM_CONDITIONAL(DOC, [test "x$enable_doc" = "xyes"])
|
||||||
AM_CONDITIONAL(CONTRIB, [test "x$enable_contrib" = "xyes"])
|
AM_CONDITIONAL(CONTRIB, [test "x$enable_contrib" = "xyes"])
|
||||||
AM_CONDITIONAL(TESTSERV, [test "x$enable_testserv_plugin" = "xyes"])
|
AM_CONDITIONAL(TESTSERV, [test "x$enable_testserv_plugin" = "xyes"])
|
||||||
|
|
||||||
|
# Workaround for as-of-yet unreleased runstatedir support, planned for
|
||||||
|
# autoconf 2.70, which some major distros have backported.
|
||||||
|
AS_IF([test -z "$runstatedir"], runstatedir="$localstatedir/run")
|
||||||
|
AC_SUBST(runstatedir)
|
||||||
|
|
||||||
# Override default libdir, used for plugins and rescue.conf
|
# Override default libdir, used for plugins and rescue.conf
|
||||||
pkglibdir=$libdir/finit
|
pkglibdir=$libdir/finit
|
||||||
AC_SUBST(pkglibexecdir)
|
AC_SUBST(pkglibexecdir)
|
||||||
AC_EXPAND_DIR(pkglibexecdir, "$libexecdir/finit")
|
AC_EXPAND_DIR(pkglibexecdir, "$libexecdir/finit")
|
||||||
AC_DEFINE_UNQUOTED(FINIT_EXECPATH_, "$pkglibexecdir", [Finit libexec path])
|
AC_DEFINE_UNQUOTED(FINIT_EXECPATH_, "$pkglibexecdir", [Finit libexec path])
|
||||||
|
AC_EXPAND_DIR(finit_runpath, "$runstatedir/finit/system")
|
||||||
|
AC_DEFINE_UNQUOTED(FINIT_RUNPATH_, "$finit_runpath", [Finit runtime dynamic system services])
|
||||||
|
|
||||||
AC_EXPAND_DIR(plugin_path, "$pkglibdir/plugins")
|
AC_EXPAND_DIR(plugin_path, "$pkglibdir/plugins")
|
||||||
AC_SUBST(plugin_path)
|
AC_SUBST(plugin_path)
|
||||||
@@ -304,7 +323,7 @@ AC_DEFINE_UNQUOTED(PLUGIN_PATH, "$plugin_path", [Finit plugin path])
|
|||||||
|
|
||||||
AC_EXPAND_DIR(tmpfiles_path, "$libdir/tmpfiles.d")
|
AC_EXPAND_DIR(tmpfiles_path, "$libdir/tmpfiles.d")
|
||||||
AC_SUBST(tmpfiles_path)
|
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_EXPAND_DIR(finit_tmpfiles, "$pkglibdir/tmpfiles.d")
|
||||||
AC_SUBST(finit_tmpfiles)
|
AC_SUBST(finit_tmpfiles)
|
||||||
@@ -312,13 +331,16 @@ AC_DEFINE_UNQUOTED(FINIT_TMPFILES, "$finit_tmpfiles", [Finit tmpfiles.d/ .conf p
|
|||||||
|
|
||||||
AC_EXPAND_DIR(system_path, "$pkglibdir/system")
|
AC_EXPAND_DIR(system_path, "$pkglibdir/system")
|
||||||
AC_SUBST(system_path)
|
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_EXPAND_DIR(rescue_conf, "$pkglibdir/rescue.conf")
|
||||||
AC_DEFINE_UNQUOTED(RESCUE_CONF, "$rescue_conf", [Finit rescue mode .conf])
|
AC_DEFINE_UNQUOTED(RESCUE_CONF, "$rescue_conf", [Finit rescue mode .conf])
|
||||||
AC_EXPAND_DIR(sample_conf, "$pkglibdir/sample.conf")
|
AC_EXPAND_DIR(sample_conf, "$pkglibdir/sample.conf")
|
||||||
AC_DEFINE_UNQUOTED(SAMPLE_CONF, "$sample_conf", [Finit sameple.conf for initctl create])
|
AC_DEFINE_UNQUOTED(SAMPLE_CONF, "$sample_conf", [Finit sameple.conf for initctl create])
|
||||||
|
|
||||||
|
AC_EXPAND_DIR(bash_completion_dir, "$BASH_DIR")
|
||||||
|
AC_SUBST(BASH_DIR, "$bash_completion_dir")
|
||||||
|
|
||||||
AS_IF([test "$heading" = ""], [heading="<DEFAULT>"])
|
AS_IF([test "$heading" = ""], [heading="<DEFAULT>"])
|
||||||
AS_IF([test "$heading" = "no"], [heading="<NONE>"])
|
AS_IF([test "$heading" = "no"], [heading="<NONE>"])
|
||||||
|
|
||||||
@@ -355,6 +377,7 @@ Behavior:
|
|||||||
Optional features:
|
Optional features:
|
||||||
Install doc/..........: $enable_doc
|
Install doc/..........: $enable_doc
|
||||||
Install contrib/......: $enable_contrib
|
Install contrib/......: $enable_contrib
|
||||||
|
Bash completion.......: $bash_completion_dir
|
||||||
Built-in keventd......: $with_keventd
|
Built-in keventd......: $with_keventd
|
||||||
Built-in sulogin......: $with_sulogin $sulogin
|
Built-in sulogin......: $with_sulogin $sulogin
|
||||||
Built-in watchdogd....: $with_watchdog $watchdog
|
Built-in watchdogd....: $with_watchdog $watchdog
|
||||||
|
|||||||
@@ -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
@@ -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
|
||||||
----------
|
----------
|
||||||
|
|
||||||
|
|||||||
@@ -1,59 +0,0 @@
|
|||||||
Bootstrap
|
|
||||||
=========
|
|
||||||
|
|
||||||
0. Get bearings, disable kernel logs, initialize TTY and print banner,
|
|
||||||
unless `HOOK_BANNER` is defined, then call that instead
|
|
||||||
1. Prepare emergency shell, if enabled
|
|
||||||
2. Set up initial signal handlers
|
|
||||||
3. Set up default $PATH early
|
|
||||||
4. Mount `/proc` and `/sys`
|
|
||||||
5. Check kernel command line for `debug` to figure out log level
|
|
||||||
6. Load all `.so` plugins
|
|
||||||
7. Call `fsck` on file systems listed in `/etc/fstab`
|
|
||||||
8. Populate `/dev` using either udev or mdev, depending on system type
|
|
||||||
9. Parse `/etc/finit.conf`
|
|
||||||
10. Start built-in watchdog, if enabled and `WDT_DEVNODE` exists. This
|
|
||||||
means any WDT that requires a kernel module need to be either
|
|
||||||
compiled into the kernel, or insmod'ed in `/etc/finit.conf`
|
|
||||||
11. Load all `/etc/finit.d/*.conf` files and set hostname
|
|
||||||
12. Remount `/` read-write if `/` is listed in `/etc/fstab` without `ro`
|
|
||||||
13. Call 1st level hooks, `HOOK_ROOTFS_UP`
|
|
||||||
14. Mount all file systems listed in `/etc/fstab` and swap, if available.
|
|
||||||
On mount error `HOOK_MOUNT_ERROR` is called. After mount, regardless
|
|
||||||
of error, `HOOK_MOUNT_POST` is called
|
|
||||||
15. Enable SysV init signals
|
|
||||||
16. Call 2nd level hooks, `HOOK_BASEFS_UP`
|
|
||||||
17. Cleanup stale files from `/tmp/*` et al, handled by `bootmisc` plugin
|
|
||||||
18. Load kernel params from `/etc/sysctl.d/*.conf`, `/etc/sysctl.conf`
|
|
||||||
et al. (Supports all locations that SysV init does.), handled by
|
|
||||||
`procps` plugin
|
|
||||||
19. Start all 'S' runlevel tasks and services
|
|
||||||
20. Bring up loopback interface and all `/etc/network/interfaces`, if
|
|
||||||
the `.conf` setting `network <SCRIPT>` is set, it is called instead
|
|
||||||
21. Call 3rd level hooks, `HOOK_NETWORK_UP`
|
|
||||||
22. If `runparts <DIR>` is set, [run-parts(8)][] is called on `<DIR>`
|
|
||||||
23. Switch to the configured runlevel from `/etc/finit.conf`, default 2.
|
|
||||||
At every runlevel change all `*.conf` files in `/etc/finit.d/` are
|
|
||||||
(re)loaded and new services, tasks, and blocking run commands are
|
|
||||||
started. Provided they are allowed in the new runlevel and all of
|
|
||||||
their conditions, if any, are set.
|
|
||||||
24. Call 4th level hooks, `HOOK_SVC_UP`
|
|
||||||
25. Call `/etc/rc.local`, if it exists and is an executable shell script
|
|
||||||
26. Call 5th level (last) hooks, `HOOK_SYSTEM_UP`
|
|
||||||
27. Start all configured TTYs
|
|
||||||
|
|
||||||
In (19) and (23) tasks and services defined in `/etc/finit.conf` and
|
|
||||||
`/etc/finit.d/*.conf` are started.
|
|
||||||
|
|
||||||
Notice the seven hook points that are called at various point in the
|
|
||||||
bootstrap process. This is where plugins can extend the boot in any
|
|
||||||
way they please. There are other hook points available, for more on
|
|
||||||
this, see [plugins.md](plugins.md).
|
|
||||||
|
|
||||||
For instance, at `HOOK_BASEFS_UP` a plugin could read an XML file from a
|
|
||||||
USB stick, convert/copy its contents to the system's `/etc/` directory,
|
|
||||||
well before all 'S' runlevel tasks are started. This could be used with
|
|
||||||
system images that are created read-only and all configuration is stored
|
|
||||||
on external media.
|
|
||||||
|
|
||||||
[run-parts(8)]: http://manpages.debian.org/cgi-bin/man.cgi?query=run-parts
|
|
||||||
@@ -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
|
||||||
|
|||||||
@@ -27,6 +27,16 @@ specified separated by comma. Multiple conditions are logically AND'ed
|
|||||||
during evaluation, i.e. all conditions must be satisfied in order for a
|
during evaluation, i.e. all conditions must be satisfied in order for a
|
||||||
service to run.
|
service to run.
|
||||||
|
|
||||||
|
A special syntax, using a leading `!` in run/task/service conditions,
|
||||||
|
denote if a:
|
||||||
|
|
||||||
|
- service does not support `SIGHUP`
|
||||||
|
- run/task should not block runlevel changes (i.e., bootstrap)
|
||||||
|
|
||||||
|
Finit guarantees by default that all run/tasks run (at least) once
|
||||||
|
per runlevel. For most tasks this is a good default, for example
|
||||||
|
checking SSH host keys or loading keymap. However, for conditions
|
||||||
|
that are unlikely to happen it is not. (See example below.)
|
||||||
|
|
||||||
### Example
|
### Example
|
||||||
|
|
||||||
@@ -41,6 +51,19 @@ being created, i.e., the service's default readiness notification.
|
|||||||
asserted. I.e., if the Zebra process above stops or restarts, netd
|
asserted. I.e., if the Zebra process above stops or restarts, netd
|
||||||
will also stop or restart.
|
will also stop or restart.
|
||||||
|
|
||||||
|
Another example is `dropbear`, it does not support `SIGHUP`, but we can
|
||||||
|
also see optional sourcing of arguments from an environment file:
|
||||||
|
|
||||||
|
service [2345789] <!> env:-/etc/default/dropbear dropbear -F -R $DROPBEAR_ARGS -- Dropbear SSH daemon
|
||||||
|
|
||||||
|
Finally, the weird "block runlevel changes" example. Here we see what
|
||||||
|
happens when Finit receives `SIGPWR`, sent from a power daemon like
|
||||||
|
[powstatd(8)][]. A condition is asserted and a user can set up their
|
||||||
|
own task to act on it. We do not want this task to block Finit from
|
||||||
|
moving to the next runlevel after bootstrap, so we set `<!>`:
|
||||||
|
|
||||||
|
task [S0123456789] <!sys/pwr/fail> name:pwrfail initctl poweroff -- Power failure, shutting down
|
||||||
|
|
||||||
|
|
||||||
Triggering
|
Triggering
|
||||||
----------
|
----------
|
||||||
@@ -260,3 +283,5 @@ Therefore, any plugin that supplies Finit with conditions must ensure
|
|||||||
that their state is updated after each reconfiguration. This can be
|
that their state is updated after each reconfiguration. This can be
|
||||||
done by binding to the `HOOK_SVC_RECONF` hook. For an example of how
|
done by binding to the `HOOK_SVC_RECONF` hook. For an example of how
|
||||||
to do this, see `plugins/pidfile.c`.
|
to do this, see `plugins/pidfile.c`.
|
||||||
|
|
||||||
|
[powstatd(8)]: https://manpages.ubuntu.com/manpages/trusty/en/man8/powstatd.8.html
|
||||||
|
|||||||
+221
-86
@@ -52,21 +52,51 @@ PID file monitoring, or [conditions](conditions.md).
|
|||||||
|
|
||||||
### Configuration Files
|
### Configuration Files
|
||||||
|
|
||||||
Originally Finit was configured using a single file, `/etc/finit.conf`.
|
Originally Finit was configured using a single file, `/etc/finit.conf`,
|
||||||
Although still possible to use this single configuration file, today the
|
and although still possible to use a single configuration file, today
|
||||||
following familiar layout is recommended:
|
the following layout is recommended:
|
||||||
|
|
||||||
/etc/
|
/
|
||||||
|- finit.d/
|
|- etc/
|
||||||
| |- available/
|
| |- finit.d/
|
||||||
| | `- my-service.conf
|
| | |- available/
|
||||||
: |- enabled/
|
| | | `- my-service.conf
|
||||||
: | `- my-service.conf -> ../available/my-service.conf
|
| : |- enabled/
|
||||||
: :
|
| : | `- my-service.conf -> ../available/my-service.conf
|
||||||
: |- static-service.conf
|
| : :
|
||||||
: `- another-static.conf
|
| : |- static-service.conf
|
||||||
:
|
| : `- another-static.conf
|
||||||
`- finit.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
|
Services in the `available/` and `enabled/` sub-directories are called
|
||||||
dynamic services, in contrast to static services -- the only difference
|
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.
|
create files and symlinks manually.
|
||||||
|
|
||||||
At bootstrap, and `initctl reload`, all .conf files are read, starting
|
At bootstrap, and `initctl reload`, all .conf files are read, starting
|
||||||
with `finit.conf`, then, in alphabetical order, all `finit.d/*.conf`
|
with `finit.conf`, then `/lib/finit/system/*.conf`, `finit.d/*.conf`,
|
||||||
files, and finally (still in alphabetical order) all `enabled/*.conf`
|
and finally all `finit.d/enabled/*.conf` files. Each directory is a
|
||||||
files.
|
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.
|
> **Note:** the `finit.conf` and `finit.d/` names are only defaults.
|
||||||
> They can be changed at compile-time with two `configure` options:
|
> They can be changed at compile-time with two `configure` options:
|
||||||
@@ -126,18 +174,22 @@ layout, as specified in the [FHS][]:
|
|||||||
|- spool/
|
|- spool/
|
||||||
`- tmp/
|
`- tmp/
|
||||||
|
|
||||||
Finit starts (very early) by mounting `/dev`, `/proc/`, and `/sys`,
|
Finit starts by mounting the critical file systems `/dev`, `/proc/`, and
|
||||||
unless they (i.e., `/dev`) are already mounted. When all plugins and
|
`/sys`, unless they are already mounted. When all plugins and other,
|
||||||
other, core Finit functions, have been set up, all relevant filesystems
|
core Finit functions, have been set up, all relevant filesystems (where
|
||||||
(`PASS > 0`) are checked and mounted from the selected `fstab`, either
|
`PASS > 0`) are checked and mounted from the selected `fstab`, either
|
||||||
the default `/etc/fstab`, or any custom one selected from the command
|
the default `/etc/fstab`, or any custom one selected from the command
|
||||||
line, or at build time.
|
line, or at build time.
|
||||||
|
|
||||||
Any file system not listed `fstab` are automatically mounted by Finit,
|
To provide a smooth ride, file system not listed in the given `fstab`,
|
||||||
as listed above, provided their respective mount point exists.
|
e.g. `/tmp` and `/run`, are automatically mounted by Finit, as listed
|
||||||
|
above, provided their respective mount point exists.
|
||||||
|
|
||||||
With all filesystems mounted, Finit calls `swapon`.
|
With all filesystems mounted, Finit calls `swapon`.
|
||||||
|
|
||||||
|
> **Tip:** to see what happens when all filesystems are mounted, have a
|
||||||
|
> look at the [`bootmisc.so` plugin](plugins.md).
|
||||||
|
|
||||||
At shutdown, and after having stopped all services and other lingering
|
At shutdown, and after having stopped all services and other lingering
|
||||||
processes have been killed, filesystems are unmounted in the reverse
|
processes have been killed, filesystems are unmounted in the reverse
|
||||||
order, and `swapoff` is called.
|
order, and `swapoff` is called.
|
||||||
@@ -154,24 +206,30 @@ order, and `swapoff` is called.
|
|||||||
- ` 0`: shutdown
|
- ` 0`: shutdown
|
||||||
|
|
||||||
Runlevels are declared per service/run/task/sysv command. Starting in
|
Runlevels are declared per service/run/task/sysv command. Starting in
|
||||||
runlevel S ([bootStrap](bootstrap.md)), usually only for tasks supposed
|
runlevel S (bootStrap), usually only for tasks supposed to run once at
|
||||||
to run once at boot, and services like `syslogd`, which you need to
|
boot, and services like `syslogd`, which you need to start and run
|
||||||
start and run throughout the whole time your system is up. Before `S`
|
throughout the whole time your system is up.
|
||||||
is started, however, Finit performs a lot of housekeeping tasks like
|
|
||||||
mounting all filesystems, calling `fsck` if needed, and making sure the
|
Before `S` is started, however, Finit performs a lot of housekeeping
|
||||||
everything is OK.
|
tasks like mounting all filesystems, calling `fsck` if needed, and
|
||||||
|
making sure the 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
|
||||||
@@ -298,17 +356,31 @@ most notably systemd and s6, other methods for signaling "readiness"
|
|||||||
arrived and daemons were adapted to these new schemes to a larger
|
arrived and daemons were adapted to these new schemes to a larger
|
||||||
extent.
|
extent.
|
||||||
|
|
||||||
As of Finit v4.4 partial support for systemd and s6 is available. The
|
As of Finit v4.4 partial support for systemd and s6 style readiness
|
||||||
native PID file mode of operation is still default, the other's can be
|
notification is available, and the native PID file mode of operation is,
|
||||||
defined per service, like this:
|
as of Finit v4.6 optional, by default it is still enabled, but this can
|
||||||
|
be changed in `finit.conf`:
|
||||||
|
|
||||||
|
readiness none
|
||||||
|
|
||||||
|
This will be made the default in Finit 5.0. In this mode of operation,
|
||||||
|
every service needs to explicitly declare their readiness notification,
|
||||||
|
like this:
|
||||||
|
|
||||||
|
service notify:pid watchdogd
|
||||||
service notify:systemd foo
|
service notify:systemd foo
|
||||||
service notify:s6 bar
|
service notify:s6 bar
|
||||||
|
service notify:none qux
|
||||||
|
|
||||||
|
The `notify:none` syntax is for completeness in systems which run in
|
||||||
|
`readiness pid` mode (default). Services declared with `notify:none`
|
||||||
|
will assert ready condition as soon as Finit has started them, e.g.,
|
||||||
|
`service/qux/ready`.
|
||||||
|
|
||||||
To synchronize two services the following condition can be used:
|
To synchronize two services the following condition can be used:
|
||||||
|
|
||||||
service notify:systemd A
|
service notify:pid watchdogd
|
||||||
service <service/A/ready> B
|
service <service/watchdogd/ready> stress-ng --cpu 8
|
||||||
|
|
||||||
For details on the syntax and options, see below.
|
For details on the syntax and options, see below.
|
||||||
|
|
||||||
@@ -467,7 +539,7 @@ following directives:
|
|||||||
|
|
||||||
|
|
||||||
> **Note:** not all directives are available in `/etc/finit.d/*.conf`
|
> **Note:** not all directives are available in `/etc/finit.d/*.conf`
|
||||||
> and some directives are only available at [bootstrap][], runlevel `S`,
|
> and some directives are only available at bootstrap, runlevel `S`,
|
||||||
> see [Limitations](#limitations) below for details.
|
> see [Limitations](#limitations) below for details.
|
||||||
|
|
||||||
|
|
||||||
@@ -480,7 +552,7 @@ the contents of that file is used.
|
|||||||
|
|
||||||
Deprecated. We recommend using `/etc/hostname` instead.
|
Deprecated. We recommend using `/etc/hostname` instead.
|
||||||
|
|
||||||
> **Note:** only read and executed in runlevel S ([bootstrap][]).
|
> **Note:** only read and executed in runlevel S (bootstrap).
|
||||||
|
|
||||||
|
|
||||||
### Kernel Modules
|
### Kernel Modules
|
||||||
@@ -498,7 +570,7 @@ BusyBox mdev tool, add to `/etc/mdev.conf`:
|
|||||||
|
|
||||||
$MODALIAS=.* root:root 0660 @modprobe -b "$MODALIAS"
|
$MODALIAS=.* root:root 0660 @modprobe -b "$MODALIAS"
|
||||||
|
|
||||||
> **Note:** only read and executed in runlevel S ([bootstrap][]).
|
> **Note:** only read and executed in runlevel S (bootstrap).
|
||||||
|
|
||||||
|
|
||||||
### Networking
|
### Networking
|
||||||
@@ -511,7 +583,7 @@ Deprecated. We recommend using dedicated task/run stanzas per runlevel,
|
|||||||
or `/etc/network/interfaces` if you have a system with `ifupdown`, like
|
or `/etc/network/interfaces` if you have a system with `ifupdown`, like
|
||||||
Debian, Ubuntu, Linux Mint, or an embedded BusyBox system.
|
Debian, Ubuntu, Linux Mint, or an embedded BusyBox system.
|
||||||
|
|
||||||
> **Note:** only read and executed in runlevel S ([bootstrap][]).
|
> **Note:** only read and executed in runlevel S (bootstrap).
|
||||||
|
|
||||||
|
|
||||||
### Alternate finit.d/
|
### Alternate finit.d/
|
||||||
@@ -566,7 +638,7 @@ stanzas can share the same rlimits if they are in the same .conf.
|
|||||||
|
|
||||||
**Syntax:** `runlevel <N>`
|
**Syntax:** `runlevel <N>`
|
||||||
|
|
||||||
The system runlevel to go to after [bootstrap][] (S) has completed. `N`
|
The system runlevel to go to after bootstrap (S) has completed. `N`
|
||||||
is the runlevel number 0-9, where 6 is reserved for reboot and 0 for
|
is the runlevel number 0-9, where 6 is reserved for reboot and 0 for
|
||||||
halt.
|
halt.
|
||||||
|
|
||||||
@@ -575,7 +647,7 @@ Finit disables networking in this mode.
|
|||||||
|
|
||||||
*Default:* 2
|
*Default:* 2
|
||||||
|
|
||||||
> **Note:** only read and executed in runlevel S ([bootstrap][]).
|
> **Note:** only read and executed in runlevel S (bootstrap).
|
||||||
|
|
||||||
|
|
||||||
### One-shot Commands (sequence)
|
### One-shot Commands (sequence)
|
||||||
@@ -615,11 +687,14 @@ also the `--quiet` and `--batch` options.
|
|||||||
|
|
||||||
One-shot like 'run', but starts in parallel with the next command.
|
One-shot like 'run', but starts in parallel with the next command.
|
||||||
|
|
||||||
Both `run` and `task` commands are run in a shell, so pipes and
|
Both `run` and `task` commands are run in a shell, so basic pipes and
|
||||||
redirects can be freely used:
|
redirects can be used:
|
||||||
|
|
||||||
task [s] echo "foo" | cat >/tmp/bar
|
task [s] echo "foo" | cat >/tmp/bar
|
||||||
|
|
||||||
|
Please note, `;`, `&&`, `||`, and similar are *not supported*. Any
|
||||||
|
non-trivial constructs are better placed in a separate shell script.
|
||||||
|
|
||||||
|
|
||||||
### SysV Init Scripts
|
### SysV Init Scripts
|
||||||
|
|
||||||
@@ -839,45 +914,106 @@ 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> :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
|
### 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 in the directory are called, in alphabetic order. The scripts in
|
||||||
The scripts in this directory are executed at the very end of runlevel
|
this directory are executed at the very end of runlevel `S`.
|
||||||
`S`, [bootstrap][].
|
|
||||||
|
|
||||||
A common use-case for runparts scripts is to create and enable/disable
|
A common use-case for runparts scripts is to create and enable/disable
|
||||||
services, which Finit will then apply when changing runlevel from S to
|
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
|
||||||
|
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.
|
||||||
|
|
||||||
1. Finit is single threaded and all scripts executed from these two
|
> **Note:** `runparts` scrips are only read and executed in runlevel S.
|
||||||
mechanisms are limited to file system operations (early or late
|
> See [hook scripts](plugins.md#hooks) for other ways to run scripts at
|
||||||
hooks may not have write access!) and standard UNIX programs.
|
> certain points during the complete lifetime of the system.
|
||||||
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
|
|
||||||
> ([bootstrap][]). See [hook scripts](plugins.md#hooks) for other ways
|
|
||||||
> to run scripts at certain points during the complete lifetime of the
|
|
||||||
> system.
|
|
||||||
|
|
||||||
**Recommendations:**
|
**Recommendations:**
|
||||||
|
|
||||||
@@ -990,8 +1126,8 @@ can be omitted to keep the kernel default.
|
|||||||
tty [12345] @console noclear vt220
|
tty [12345] @console noclear vt220
|
||||||
|
|
||||||
On really bare bones systems, or for board bringup, Finit can give you a
|
On really bare bones systems, or for board bringup, Finit can give you a
|
||||||
shell prompt as soon as [bootstrap][] is done, without opening any
|
shell prompt as soon as bootstrap is done, without opening any device
|
||||||
device node:
|
node:
|
||||||
|
|
||||||
tty [12345789] notty
|
tty [12345789] notty
|
||||||
|
|
||||||
@@ -1073,8 +1209,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`
|
||||||
|
|
||||||
@@ -1224,12 +1362,11 @@ Watchdog
|
|||||||
When built `--with-watchdog` a separate service is built and installed
|
When built `--with-watchdog` a separate service is built and installed
|
||||||
in `/libexec/finit/watchdogd`. If this exists at runtime, and the WDT
|
in `/libexec/finit/watchdogd`. If this exists at runtime, and the WDT
|
||||||
device node exists, Finit will start it and treat it as the elected
|
device node exists, Finit will start it and treat it as the elected
|
||||||
watchdog service to delegate its reboot to. See [bootstrap][] for
|
watchdog service to delegate its reboot to. This delegation is to
|
||||||
details. This delegation is to ensure that the system is rebooted by a
|
ensure that the system is rebooted by a hardware watchdog timer -- on
|
||||||
hardware watchdog timer -- on many embedded systems this is crucial to
|
many embedded systems this is crucial to ensure all circuits on the
|
||||||
ensure all circuits on the board are properly reset for the next boot,
|
board are properly reset for the next boot, in effect ensuring the
|
||||||
in effect ensuring the system works the same after both a power-on and
|
system works the same after both a power-on and reboot event.
|
||||||
reboot event.
|
|
||||||
|
|
||||||
The delegation is performed at the very last steps of system shutdown,
|
The delegation is performed at the very last steps of system shutdown,
|
||||||
if reboot has been selected and an elected watchdog is known, first a
|
if reboot has been selected and an elected watchdog is known, first a
|
||||||
@@ -1251,8 +1388,6 @@ device descriptor. If the kernel driver has been built without this,
|
|||||||
the only option is to remove `/libexec/finit/watchdogd` or build without
|
the only option is to remove `/libexec/finit/watchdogd` or build without
|
||||||
it at configure time.
|
it at configure time.
|
||||||
|
|
||||||
[bootstrap]: bootstrap.md
|
|
||||||
|
|
||||||
|
|
||||||
keventd
|
keventd
|
||||||
-------
|
-------
|
||||||
|
|||||||
+17
-5
@@ -28,9 +28,16 @@ For your convenience a set of *optional* plugins are available:
|
|||||||
system and runs at `HOOK_BASEFS_UP`. The `/var`, `/run`, and `/dev`
|
system and runs at `HOOK_BASEFS_UP`. The `/var`, `/run`, and `/dev`
|
||||||
file systems must be writable for this plugin to work.
|
file systems must be writable for this plugin to work.
|
||||||
|
|
||||||
Note: On an embedded system both `/var` and `/run` can be `tmpfs` RAM
|
This plugin is a wrapper for the [tmpfiles.d(5)][] implementation that
|
||||||
disks and `/dev` is usually a `devtmpfs`. This must be defined in the
|
Finit has. Capable but limited: no aging, attributes, or subvolumes.
|
||||||
`/etc/fstab` file and in the Linux kernel config.
|
|
||||||
|
By default, `/lib/finit/tmpfiles.d` carries all the default .conf
|
||||||
|
files distributed with Finit. It is read first but can be overridden
|
||||||
|
by any of the standard tmpfiles.d directories, e.g. `/etc/tmpfiles.d`.
|
||||||
|
|
||||||
|
> **Note:** On an embedded system both `/var` and `/run` can be `tmpfs`
|
||||||
|
> RAM disks and `/dev` is usually a `devtmpfs`. This must be defined
|
||||||
|
> in the `/etc/fstab` file and in the Linux kernel config.
|
||||||
|
|
||||||
* *dbus.so*: Setup and start system message bus, D-Bus, at boot.
|
* *dbus.so*: Setup and start system message bus, D-Bus, at boot.
|
||||||
_Optional plugin._
|
_Optional plugin._
|
||||||
@@ -50,8 +57,11 @@ For your convenience a set of *optional* plugins are available:
|
|||||||
customized at build-time using the `--with-hook-scripts-path=PATH`
|
customized at build-time using the `--with-hook-scripts-path=PATH`
|
||||||
argument to `configure`.
|
argument to `configure`.
|
||||||
|
|
||||||
* *hotplug.so*: Setup and start either udev or mdev hotplug daemon, if
|
* *hotplug.so*: Replaced with `/lib/finit/system/10-hotplug.conf`, which
|
||||||
available. Enabled by default.
|
checks for `udevd` and `mdev` at boot. This file can be overridden by a
|
||||||
|
file in `/etc/finit.d/10-hotplug.conf`.
|
||||||
|
|
||||||
|
Enabled by default.
|
||||||
|
|
||||||
> See the [Services](config.md#services) section in the configuration
|
> See the [Services](config.md#services) section in the configuration
|
||||||
> guide for an example how to run `mdevd`, alternative to plain mdev.
|
> guide for an example how to run `mdevd`, alternative to plain mdev.
|
||||||
@@ -217,3 +227,5 @@ Plugins like `tty.so` extend finit by acting on events, they are called
|
|||||||
I/O plugins and are called from the finit main loop when `poll()`
|
I/O plugins and are called from the finit main loop when `poll()`
|
||||||
detects an event. See the source code for `plugins/*.c` for more help
|
detects an event. See the source code for `plugins/*.c` for more help
|
||||||
and ideas.
|
and ideas.
|
||||||
|
|
||||||
|
[tmpfiles.d(5)]: https://www.freedesktop.org/software/systemd/man/tmpfiles.d.html
|
||||||
|
|||||||
+1
-1
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
+5
-6
@@ -83,6 +83,7 @@ static char *dbus_pidfn(void)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
*pos = 0;
|
*pos = 0;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
@@ -142,23 +143,21 @@ static void setup(void *arg)
|
|||||||
|
|
||||||
/* Generate machine id for dbus */
|
/* Generate machine id for dbus */
|
||||||
if (whichp("dbus-uuidgen"))
|
if (whichp("dbus-uuidgen"))
|
||||||
run_interactive("dbus-uuidgen --ensure", "Creating machine UUID for D-Bus");
|
run_interactive("dbus-uuidgen --ensure", "Verifying D-Bus machine UUID");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Register service with Finit
|
* Register service with Finit
|
||||||
* Note: dbus drops privs after starting up.
|
* Note: dbus drops privs after starting up.
|
||||||
*/
|
*/
|
||||||
if (pidfn) {
|
if (pidfn) {
|
||||||
snprintf(line, sizeof(line), "[S123456789] cgroup.system name:dbus pid:!%s %s %s -- %s",
|
snprintf(line, sizeof(line), "[S123456789] cgroup.system notify:none name:dbus pid:!%s %s %s -- %s",
|
||||||
pidfn, cmd, DBUS_ARGS, DBUS_DESC);
|
pidfn, cmd, DBUS_ARGS, DBUS_DESC);
|
||||||
free(pidfn);
|
free(pidfn);
|
||||||
} else
|
} else
|
||||||
snprintf(line, sizeof(line), "[S123456789] cgroup.system name:dbus %s %s -- %s",
|
snprintf(line, sizeof(line), "[S123456789] cgroup.system notify:none name:dbus %s %s -- %s",
|
||||||
cmd, DBUS_ARGS, DBUS_DESC);
|
cmd, DBUS_ARGS, DBUS_DESC);
|
||||||
|
|
||||||
if (service_register(SVC_TYPE_SERVICE, line, global_rlimit, NULL))
|
conf_save_service(SVC_TYPE_SERVICE, line, "dbus.conf");
|
||||||
err(1, "Failed registering %s", DBUS_DAEMON);
|
|
||||||
|
|
||||||
free(cmd);
|
free(cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+7
-6
@@ -79,7 +79,7 @@ static void pidfile_update_conds(char *dir, char *name, uint32_t mask)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
dbg("Found svc %s for %s with pid %d", svc->name, fn, svc->pid);
|
dbg("Found svc %s for %s with pid %d", svc_ident(svc, NULL, 0), fn, svc->pid);
|
||||||
mkcond(svc, cond, sizeof(cond));
|
mkcond(svc, cond, sizeof(cond));
|
||||||
|
|
||||||
if (mask & (IN_CLOSE_WRITE | IN_ATTRIB | IN_MODIFY | IN_MOVED_TO)) {
|
if (mask & (IN_CLOSE_WRITE | IN_ATTRIB | IN_MODIFY | IN_MOVED_TO)) {
|
||||||
@@ -88,7 +88,7 @@ static void pidfile_update_conds(char *dir, char *name, uint32_t mask)
|
|||||||
* systemd style services rely on their respective
|
* systemd style services rely on their respective
|
||||||
* readiness notification. Issue #343
|
* readiness notification. Issue #343
|
||||||
*/
|
*/
|
||||||
if (!svc->notify)
|
if (svc->notify == SVC_NOTIFY_PID)
|
||||||
svc_started(svc);
|
svc_started(svc);
|
||||||
|
|
||||||
if (!svc_has_pidfile(svc)) {
|
if (!svc_has_pidfile(svc)) {
|
||||||
@@ -120,12 +120,13 @@ static void pidfile_update_conds(char *dir, char *name, uint32_t mask)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cond_set(cond);
|
if (svc->notify == SVC_NOTIFY_PID)
|
||||||
if (!svc->notify)
|
cond_set(cond);
|
||||||
|
if (svc->notify == SVC_NOTIFY_PID || svc->notify == SVC_NOTIFY_NONE)
|
||||||
service_ready(svc);
|
service_ready(svc);
|
||||||
} else if (mask & IN_DELETE) {
|
} else if (mask & IN_DELETE) {
|
||||||
cond_clear(cond);
|
cond_clear(cond);
|
||||||
if (!svc->notify)
|
if (svc->notify == SVC_NOTIFY_PID)
|
||||||
service_ready(svc);
|
service_ready(svc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -240,7 +241,7 @@ static void pidfile_reconf(void *arg)
|
|||||||
if (svc_is_changed(svc) || svc_is_starting(svc))
|
if (svc_is_changed(svc) || svc_is_starting(svc))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!svc->notify)
|
if (svc->notify == SVC_NOTIFY_PID)
|
||||||
service_ready(svc);
|
service_ready(svc);
|
||||||
|
|
||||||
mkcond(svc, cond, sizeof(cond));
|
mkcond(svc, cond, sizeof(cond));
|
||||||
|
|||||||
@@ -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("/");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,6 +19,8 @@ if WATCHDOGD
|
|||||||
pkglibexec_PROGRAMS += watchdogd
|
pkglibexec_PROGRAMS += watchdogd
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
dist_pkglibexec_SCRIPTS = coldplug
|
||||||
|
|
||||||
finit_pkglibdir = $(pkglibdir)
|
finit_pkglibdir = $(pkglibdir)
|
||||||
finit_pkglib_SCRIPTS = rescue.conf sample.conf
|
finit_pkglib_SCRIPTS = rescue.conf sample.conf
|
||||||
|
|
||||||
|
|||||||
@@ -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:
|
||||||
|
|||||||
Executable
+11
@@ -0,0 +1,11 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# With the daemon mode ('mdev -df') we no longer need the hotplug helper
|
||||||
|
echo "" > /proc/sys/kernel/hotplug
|
||||||
|
|
||||||
|
# Wait for 'mdev -df' to set up its event queue.
|
||||||
|
sleep 1
|
||||||
|
|
||||||
|
# Trigger 'add' event for all devices and subsystems to load all modules
|
||||||
|
# and any firmware needed by the hardware.
|
||||||
|
find /sys/devices -name uevent -print | while IFS='' read X; do echo add > $X; done
|
||||||
+10
-2
@@ -222,8 +222,16 @@ static int do_delete(const char *fpath, const struct stat *sb, int tflag, struct
|
|||||||
static void cond_delpath(const char *path)
|
static void cond_delpath(const char *path)
|
||||||
{
|
{
|
||||||
nftw(path, do_delete, 20, FTW_DEPTH);
|
nftw(path, do_delete, 20, FTW_DEPTH);
|
||||||
if (remove(path) && errno != ENOENT)
|
if (remove(path)) {
|
||||||
err(1, "Failed removing condition path %s", path);
|
switch (errno) {
|
||||||
|
case ENOENT: /* Ignore */
|
||||||
|
case ENOTEMPTY: /* Only at shutdown and for directories */
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
err(1, "Failed removing condition path %s", path);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int cond_set_path(const char *path, enum cond_state next)
|
int cond_set_path(const char *path, enum cond_state next)
|
||||||
|
|||||||
+199
-13
@@ -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 */
|
||||||
|
|
||||||
@@ -393,6 +414,79 @@ void conf_saverc(void)
|
|||||||
fclose(fp);
|
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)
|
||||||
|
goto done;
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
done:
|
||||||
|
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))
|
||||||
|
warnx("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
|
* 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
|
* from finit.conf, or other .conf file. Note, PATH is always reset in
|
||||||
@@ -451,6 +545,23 @@ static void parse_env(char *line)
|
|||||||
*end-- = 0;
|
*end-- = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* strip any leading 'set ' */
|
||||||
|
end = key;
|
||||||
|
if (!strncmp(key, "set", 3))
|
||||||
|
end += 3;
|
||||||
|
|
||||||
|
/* check key, no spaces allowed */
|
||||||
|
while (*end && isspace(*end))
|
||||||
|
end++;
|
||||||
|
key = end;
|
||||||
|
while (*end && !isspace(*end))
|
||||||
|
end++;
|
||||||
|
if (*end != 0) {
|
||||||
|
warnx("'%s=%s': not a valid identifier", key, val);
|
||||||
|
return; /* invalid key */
|
||||||
|
}
|
||||||
|
|
||||||
|
dbg("Global env '%s'='%s'", key, val);
|
||||||
setenv(key, val, 1);
|
setenv(key, val, 1);
|
||||||
|
|
||||||
node = malloc(sizeof(*node));
|
node = malloc(sizeof(*node));
|
||||||
@@ -562,11 +673,22 @@ void conf_parse_cond(svc_t *svc, char *cond)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* First character must be '!' if SIGHUP is not supported. */
|
/*
|
||||||
|
* First character must be '!' if:
|
||||||
|
* - service: SIGHUP is not supported
|
||||||
|
* - run/task: Do not block bootstrap
|
||||||
|
*/
|
||||||
ptr = cond;
|
ptr = cond;
|
||||||
if (ptr[i] == '!') {
|
if (ptr[i] == '!') {
|
||||||
svc->sighup = 0;
|
|
||||||
ptr++;
|
ptr++;
|
||||||
|
|
||||||
|
if (svc_is_runtask(svc)) {
|
||||||
|
/* see service_runtask_clean() */
|
||||||
|
svc->sighup = 1;
|
||||||
|
svc->once = 1;
|
||||||
|
} else {
|
||||||
|
svc->sighup = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
while (ptr[i] != '>' && ptr[i] != 0)
|
while (ptr[i] != '>' && ptr[i] != 0)
|
||||||
@@ -778,6 +900,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;
|
||||||
}
|
}
|
||||||
@@ -844,6 +975,18 @@ static int parse_static(char *line, int is_rcsd)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Before Finit 5 the default readiness notification is PID.
|
||||||
|
* This default can be changed by setting 'readiness none' in
|
||||||
|
* the file /etc/finit.conf, only read once at bootstrap.
|
||||||
|
*/
|
||||||
|
if (BOOTSTRAP && MATCH_CMD(line, "readiness ", x)) {
|
||||||
|
char *token = strip_line(x);
|
||||||
|
|
||||||
|
if (!strcmp(token, "none"))
|
||||||
|
readiness = SVC_NOTIFY_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
if (MATCH_CMD(line, "reboot-delay ", x)) {
|
if (MATCH_CMD(line, "reboot-delay ", x)) {
|
||||||
syncsec = strtonum(strip_line(x), 0, 60, NULL);
|
syncsec = strtonum(strip_line(x), 0, 60, NULL);
|
||||||
return 0;
|
return 0;
|
||||||
@@ -1122,20 +1265,51 @@ int conf_reload(void)
|
|||||||
* but are now regular files that can be overridden by files in
|
* 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
|
* /etc/finit.d -- similar to how tmfiles.d(5) work. E.g., add
|
||||||
* an override .conf, or an ignore by symlinking to /dev/null
|
* 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, 0, "%s/*.conf", FINIT_SYSPATH_);
|
||||||
glob_append(&gl, 1, "%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);
|
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++) {
|
for (i = 0; i < gl.gl_pathc; i++) {
|
||||||
char *path = gl.gl_pathv[i];
|
char *path = gl.gl_pathv[i];
|
||||||
char *rp = NULL;
|
char *rp = NULL;
|
||||||
struct stat st;
|
struct stat st;
|
||||||
size_t j, len;
|
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++) {
|
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;
|
continue;
|
||||||
if (strcmp(basename(path), basename(gl.gl_pathv[j])))
|
if (strcmp(basename(path), basename(gl.gl_pathv[j])))
|
||||||
continue;
|
continue;
|
||||||
@@ -1195,6 +1369,9 @@ done:
|
|||||||
/* Drop record of all .conf changes */
|
/* Drop record of all .conf changes */
|
||||||
drop_changes();
|
drop_changes();
|
||||||
|
|
||||||
|
if (bootstrap)
|
||||||
|
wdog = svc_find("watchdog", "finit");
|
||||||
|
|
||||||
/* Override configured runlevel, user said 'S' on /proc/cmdline */
|
/* Override configured runlevel, user said 'S' on /proc/cmdline */
|
||||||
if (BOOTSTRAP && single)
|
if (BOOTSTRAP && single)
|
||||||
cfglevel = 1;
|
cfglevel = 1;
|
||||||
@@ -1245,7 +1422,8 @@ static int conf_change_act(char *dir, char *name, uint32_t mask)
|
|||||||
struct conf_change *node;
|
struct conf_change *node;
|
||||||
char *rp = NULL;
|
char *rp = NULL;
|
||||||
|
|
||||||
if (name[0])
|
/* Check for actual printable characters, sometimes STX */
|
||||||
|
if (name[0] && name[0] >= ' ')
|
||||||
paste(fn, sizeof(fn), dir, name);
|
paste(fn, sizeof(fn), dir, name);
|
||||||
else
|
else
|
||||||
strlcpy(fn, dir, sizeof(fn));
|
strlcpy(fn, dir, sizeof(fn));
|
||||||
@@ -1431,15 +1609,16 @@ int conf_init(uev_ctx_t *ctx)
|
|||||||
*/
|
*/
|
||||||
#ifdef WDT_DEVNODE
|
#ifdef WDT_DEVNODE
|
||||||
if (whichp(FINIT_EXECPATH_ "/watchdogd") && fexist(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);
|
conf_save_service(SVC_TYPE_SERVICE, "[S0123456789] cgroup.init notify:none name:watchdog :finit "
|
||||||
wdog = svc_find("watchdog", "finit");
|
FINIT_EXECPATH_ "/watchdogd -- Finit watchdog daemon", "watchdogd.conf");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
/*
|
/*
|
||||||
* Start kernel event daemon as soon as possible, if enabled
|
* Start kernel event daemon as soon as possible, if enabled
|
||||||
*/
|
*/
|
||||||
if (whichp(FINIT_EXECPATH_ "/keventd"))
|
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 notify:none "
|
||||||
|
FINIT_EXECPATH_ "/keventd -- Finit kernel event daemon", "keventd.conf");
|
||||||
|
|
||||||
dbg("Allow plugins to register early runlevel 1 run/task/services ...");
|
dbg("Allow plugins to register early runlevel 1 run/task/services ...");
|
||||||
plugin_run_hooks(HOOK_SVC_PLUGIN);
|
plugin_run_hooks(HOOK_SVC_PLUGIN);
|
||||||
@@ -1463,12 +1642,19 @@ 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 };
|
||||||
|
|
||||||
snprintf(conf, sizeof(conf), "[S] <int/bootstrap> log:console %s %s %s"
|
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> notify:none log:console %s %s %s"
|
||||||
" -- Calling runparts %s in the background",
|
" -- Calling runparts %s in the background",
|
||||||
_PATH_RUNPARTS, args, runparts, runparts);
|
_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;
|
return 0;
|
||||||
|
|||||||
@@ -44,6 +44,8 @@ int conf_monitor (void);
|
|||||||
|
|
||||||
void conf_reset_env (void);
|
void conf_reset_env (void);
|
||||||
void conf_saverc (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[]);
|
void conf_parse_cmdline (int argc, char *argv[]);
|
||||||
int conf_parse_runlevels (char *runlevels);
|
int conf_parse_runlevels (char *runlevels);
|
||||||
void conf_parse_cond (svc_t *svc, char *cond);
|
void conf_parse_cond (svc_t *svc, char *cond);
|
||||||
|
|||||||
+1
-1
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
+7
-8
@@ -69,13 +69,13 @@ int single = 0; /* single user mode from kernel cmdline */
|
|||||||
int bootstrap = 1; /* set while bootrapping (for TTYs) */
|
int bootstrap = 1; /* set while bootrapping (for TTYs) */
|
||||||
int kerndebug = 0; /* set if /proc/sys/kernel/printk > 7 */
|
int kerndebug = 0; /* set if /proc/sys/kernel/printk > 7 */
|
||||||
int syncsec = 0; /* reboot delay */
|
int syncsec = 0; /* reboot delay */
|
||||||
|
int readiness = SVC_NOTIFY_PID;
|
||||||
char *finit_conf= NULL;
|
char *finit_conf= NULL;
|
||||||
char *finit_rcsd= NULL;
|
char *finit_rcsd= NULL;
|
||||||
char *fstab = NULL;
|
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 */
|
||||||
@@ -205,7 +205,7 @@ static int fsck(int pass)
|
|||||||
|
|
||||||
fp = setmntent(fstab, "r");
|
fp = setmntent(fstab, "r");
|
||||||
if (!fp) {
|
if (!fp) {
|
||||||
err(1, "Failed opening fstab: %s", fstab);
|
logit(LOG_CONSOLE | LOG_ALERT, "Failed opening fstab: %s", fstab);
|
||||||
sulogin(1);
|
sulogin(1);
|
||||||
}
|
}
|
||||||
dbg("Opened %s, pass %d", fstab, pass);
|
dbg("Opened %s, pass %d", fstab, pass);
|
||||||
@@ -255,11 +255,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 +278,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 +288,7 @@ static int fsck_all(void)
|
|||||||
if (rc)
|
if (rc)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -701,6 +696,10 @@ int main(int argc, char *argv[])
|
|||||||
cond_set_oneshot(plugin_hook_str(HOOK_BANNER));
|
cond_set_oneshot(plugin_hook_str(HOOK_BANNER));
|
||||||
cond_set_oneshot(plugin_hook_str(HOOK_ROOTFS_UP));
|
cond_set_oneshot(plugin_hook_str(HOOK_ROOTFS_UP));
|
||||||
|
|
||||||
|
/* Some bootstrap tasks may need to know if we're in a container. */
|
||||||
|
if (in_container())
|
||||||
|
cond_set_oneshot("int/container");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Initialize .conf system and load static /etc/finit.conf then
|
* Initialize .conf system and load static /etc/finit.conf then
|
||||||
* tell the world what we used.
|
* tell the world what we used.
|
||||||
|
|||||||
@@ -121,6 +121,7 @@ extern int single;
|
|||||||
extern int bootstrap;
|
extern int bootstrap;
|
||||||
extern int kerndebug;
|
extern int kerndebug;
|
||||||
extern int syncsec;
|
extern int syncsec;
|
||||||
|
extern int readiness;
|
||||||
extern char *fstab;
|
extern char *fstab;
|
||||||
extern char *sdown;
|
extern char *sdown;
|
||||||
extern char *network;
|
extern char *network;
|
||||||
|
|||||||
+1
-1
@@ -89,7 +89,7 @@ int exec_runtask (char *cmd, char *args[]);
|
|||||||
pid_t run_getty (char *tty, char *cmd, char *args[], int noclear, int nowait, struct rlimit rlimit[]);
|
pid_t run_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
@@ -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
@@ -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);
|
||||||
|
|
||||||
|
|||||||
+156
-65
@@ -330,14 +330,14 @@ static int lredirect(svc_t *svc)
|
|||||||
|
|
||||||
snprintf(rot, sizeof(rot), "%d:%d", logfile_size_max, logfile_count_max);
|
snprintf(rot, sizeof(rot), "%d:%d", logfile_size_max, logfile_count_max);
|
||||||
snprintf(pid, sizeof(pid), "%d", svc_pid);
|
snprintf(pid, sizeof(pid), "%d", svc_pid);
|
||||||
execlp("logger", "logger", "-f", svc->log.file, "-b", "-t", tag, "-p", prio, "-I", pid, "-r", rot, NULL);
|
execlp("logger", "logger", "-f", svc->log.file, "-b", "-t", tag, "-p", prio, debug ? "-s" : "", "-I", pid, "-r", rot, NULL);
|
||||||
} else {
|
} else {
|
||||||
char sz[20], num[3];
|
char sz[20], num[3];
|
||||||
|
|
||||||
snprintf(sz, sizeof(sz), "%d", logfile_size_max);
|
snprintf(sz, sizeof(sz), "%d", logfile_size_max);
|
||||||
snprintf(num, sizeof(num), "%d", logfile_count_max);
|
snprintf(num, sizeof(num), "%d", logfile_count_max);
|
||||||
|
|
||||||
execlp(_PATH_LOGIT, "logit", "-f", svc->log.file, "-n", sz, "-r", num, NULL);
|
execlp(_PATH_LOGIT, "logit", "-f", svc->log.file, "-n", sz, "-r", num, debug ? "-s" : "", NULL);
|
||||||
}
|
}
|
||||||
_exit(1);
|
_exit(1);
|
||||||
}
|
}
|
||||||
@@ -351,9 +351,9 @@ static int lredirect(svc_t *svc)
|
|||||||
char pid[16];
|
char pid[16];
|
||||||
|
|
||||||
snprintf(pid, sizeof(pid), "%d", svc_pid);
|
snprintf(pid, sizeof(pid), "%d", svc_pid);
|
||||||
execlp("logger", "logger", "-t", tag, "-p", prio, "-I", pid, NULL);
|
execlp("logger", "logger", "-t", tag, "-p", prio, debug ? "-s" : "", "-I", pid, NULL);
|
||||||
} else {
|
} else {
|
||||||
execlp(_PATH_LOGIT, "logit", "-t", tag, "-p", prio, NULL);
|
execlp(_PATH_LOGIT, "logit", "-t", tag, "-p", prio, debug ? "-s" : "", NULL);
|
||||||
}
|
}
|
||||||
_exit(1);
|
_exit(1);
|
||||||
}
|
}
|
||||||
@@ -394,11 +394,8 @@ static int redirect(svc_t *svc)
|
|||||||
*/
|
*/
|
||||||
static void source_env(svc_t *svc)
|
static void source_env(svc_t *svc)
|
||||||
{
|
{
|
||||||
char buf[LINE_SIZE];
|
char *buf, *val, *line, *fn;
|
||||||
char *line;
|
|
||||||
size_t len;
|
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
char *fn;
|
|
||||||
|
|
||||||
fn = svc_getenv(svc);
|
fn = svc_getenv(svc);
|
||||||
if (!fn)
|
if (!fn)
|
||||||
@@ -409,11 +406,19 @@ static void source_env(svc_t *svc)
|
|||||||
if (!fp)
|
if (!fp)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
buf = alloca(LINE_SIZE);
|
||||||
|
val = alloca(LINE_SIZE);
|
||||||
|
if (!buf || !val) {
|
||||||
|
warn("Failed allocating temporary env buffer");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
line = buf;
|
line = buf;
|
||||||
len = sizeof(buf);
|
while (fgets(line, LINE_SIZE, fp)) {
|
||||||
while (fgets(line, len, fp)) {
|
|
||||||
char *key = chomp(line);
|
char *key = chomp(line);
|
||||||
|
wordexp_t we = { 0 };
|
||||||
char *value, *end;
|
char *value, *end;
|
||||||
|
size_t i;
|
||||||
|
|
||||||
/* skip any leading whitespace */
|
/* skip any leading whitespace */
|
||||||
while (isspace(*key))
|
while (isspace(*key))
|
||||||
@@ -466,7 +471,40 @@ static void source_env(svc_t *svc)
|
|||||||
*end-- = 0;
|
*end-- = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
setenv(key, value, 1);
|
/* strip any leading 'set ' */
|
||||||
|
end = key;
|
||||||
|
if (!strncmp(key, "set", 3))
|
||||||
|
end += 3;
|
||||||
|
|
||||||
|
/* check key, no spaces allowed */
|
||||||
|
while (*end && isspace(*end))
|
||||||
|
end++;
|
||||||
|
key = end;
|
||||||
|
while (*end && !isspace(*end))
|
||||||
|
end++;
|
||||||
|
if (*end != 0) {
|
||||||
|
warnx("'%s=%s': not a valid identifier", key, val);
|
||||||
|
continue; /* invalid key */
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (wordexp(value, &we, 0)) {
|
||||||
|
case 0:
|
||||||
|
for (i = 0, *val = 0; i < we.we_wordc; i++) {
|
||||||
|
if (i > 0)
|
||||||
|
strlcat(val, " ", LINE_SIZE);
|
||||||
|
strlcat(val, we.we_wordv[i], LINE_SIZE);
|
||||||
|
}
|
||||||
|
setenv(key, val, 1);
|
||||||
|
wordfree(&we);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WRDE_NOSPACE:
|
||||||
|
wordfree(&we);
|
||||||
|
/* fallthrough */
|
||||||
|
default:
|
||||||
|
setenv(key, value, 1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
@@ -629,6 +667,9 @@ static int service_start(svc_t *svc)
|
|||||||
}
|
}
|
||||||
|
|
||||||
compose_cmdline(svc, cmdline, sizeof(cmdline));
|
compose_cmdline(svc, cmdline, sizeof(cmdline));
|
||||||
|
if (bootstrap)
|
||||||
|
conf_save_exec_order(svc, cmdline, -1);
|
||||||
|
|
||||||
if (svc_is_sysv(svc))
|
if (svc_is_sysv(svc))
|
||||||
logit(LOG_CONSOLE | LOG_NOTICE, "Calling '%s start' ...", cmdline);
|
logit(LOG_CONSOLE | LOG_NOTICE, "Calling '%s start' ...", cmdline);
|
||||||
|
|
||||||
@@ -676,11 +717,12 @@ static int service_start(svc_t *svc)
|
|||||||
wordexp_t we = { 0 };
|
wordexp_t we = { 0 };
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
if (svc->notify) {
|
if (svc->notify == SVC_NOTIFY_SYSTEMD || svc->notify == SVC_NOTIFY_S6) {
|
||||||
if (client_command(INIT_CMD_NOTIFY_SOCKET)) {
|
if (client_command(INIT_CMD_NOTIFY_SOCKET)) {
|
||||||
err(1, "%s: failed creating notify socket", svc_ident(svc, NULL, 0));
|
err(1, "%s: failed creating notify socket", svc_ident(svc, NULL, 0));
|
||||||
client_disconnect();
|
client_disconnect();
|
||||||
svc->notify = 0; /* does not change parent, restarting may work. */
|
/* does not change parent, restarting may work. */
|
||||||
|
svc->notify = SVC_NOTIFY_NONE;
|
||||||
} else {
|
} else {
|
||||||
char val[20];
|
char val[20];
|
||||||
|
|
||||||
@@ -705,7 +747,7 @@ static int service_start(svc_t *svc)
|
|||||||
if (len == 0)
|
if (len == 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (svc->notify) {
|
if (svc->notify == SVC_NOTIFY_SYSTEMD || svc->notify == SVC_NOTIFY_S6) {
|
||||||
char *ptr = strstr(arg, "%n");
|
char *ptr = strstr(arg, "%n");
|
||||||
|
|
||||||
if (ptr) {
|
if (ptr) {
|
||||||
@@ -836,8 +878,10 @@ 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);
|
||||||
|
if (bootstrap && !run_block_pid)
|
||||||
|
conf_save_exec_order(svc, NULL, result);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -880,6 +924,19 @@ static void service_kill(svc_t *svc)
|
|||||||
print(2, NULL);
|
print(2, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Ensure we don't have any notify socket lingering */
|
||||||
|
static void service_notify_stop(svc_t *svc)
|
||||||
|
{
|
||||||
|
if (svc->notify != SVC_NOTIFY_SYSTEMD && svc->notify != SVC_NOTIFY_S6)
|
||||||
|
return;
|
||||||
|
|
||||||
|
uev_io_stop(&svc->notify_watcher);
|
||||||
|
if (svc->notify_watcher.fd > 0) {
|
||||||
|
close(svc->notify_watcher.fd);
|
||||||
|
svc->notify_watcher.fd = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Clean up any lingering state from dead/killed services
|
* Clean up any lingering state from dead/killed services
|
||||||
*/
|
*/
|
||||||
@@ -895,12 +952,7 @@ static void service_cleanup(svc_t *svc)
|
|||||||
logit(LOG_CRIT, "Failed removing service %s pidfile %s",
|
logit(LOG_CRIT, "Failed removing service %s pidfile %s",
|
||||||
svc_ident(svc, NULL, 0), fn);
|
svc_ident(svc, NULL, 0), fn);
|
||||||
|
|
||||||
/* Ensure we don't have any notify socket lingering */
|
service_notify_stop(svc);
|
||||||
if (svc->notify && svc->notify_watcher.fd > 0) {
|
|
||||||
uev_io_stop(&svc->notify_watcher);
|
|
||||||
close(svc->notify_watcher.fd);
|
|
||||||
svc->notify_watcher.fd = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* No longer running, update books. */
|
/* No longer running, update books. */
|
||||||
if (svc_is_tty(svc) && svc->pid > 1)
|
if (svc_is_tty(svc) && svc->pid > 1)
|
||||||
@@ -974,7 +1026,11 @@ int service_stop(svc_t *svc)
|
|||||||
if (!svc->desc[0])
|
if (!svc->desc[0])
|
||||||
do_progress = 0;
|
do_progress = 0;
|
||||||
|
|
||||||
if (runlevel != 1 && do_progress)
|
/*
|
||||||
|
* Skip run/tasks in progress, would otherwise print silly stuff
|
||||||
|
* like: "Stopping Shutting down" ...
|
||||||
|
*/
|
||||||
|
if (runlevel != 1 && do_progress && (svc_is_daemon(svc) || svc_is_sysv(svc)))
|
||||||
print_desc("Stopping ", svc->desc);
|
print_desc("Stopping ", svc->desc);
|
||||||
|
|
||||||
if (!svc_is_sysv(svc)) {
|
if (!svc_is_sysv(svc)) {
|
||||||
@@ -1030,7 +1086,7 @@ int service_stop(svc_t *svc)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (runlevel != 1 && do_progress)
|
if (runlevel != 1 && do_progress && (svc_is_daemon(svc) || svc_is_sysv(svc)))
|
||||||
print_result(rc);
|
print_result(rc);
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
@@ -1157,13 +1213,15 @@ static void parse_log(svc_t *svc, char *arg)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int parse_notify(char *arg)
|
static svc_notify_t parse_notify(char *arg)
|
||||||
{
|
{
|
||||||
if (!strcmp(arg, "systemd"))
|
if (!strcmp(arg, "systemd"))
|
||||||
return 1;
|
return SVC_NOTIFY_SYSTEMD;
|
||||||
if (!strcmp(arg, "s6"))
|
if (!strcmp(arg, "s6"))
|
||||||
return 2;
|
return SVC_NOTIFY_S6;
|
||||||
return 0; /* unsupported/disabled */
|
if (!strcmp(arg, "pid"))
|
||||||
|
return SVC_NOTIFY_PID;
|
||||||
|
return SVC_NOTIFY_NONE; /* unsupported/none */
|
||||||
}
|
}
|
||||||
|
|
||||||
static void parse_env(svc_t *svc, char *env)
|
static void parse_env(svc_t *svc, char *env)
|
||||||
@@ -1396,7 +1454,11 @@ static void parse_cmdline_args(svc_t *svc, char *cmd, char **args)
|
|||||||
* before they are started. Or restarted, or even SIGHUP'ed, when the
|
* before they are started. Or restarted, or even SIGHUP'ed, when the
|
||||||
* gateway changes or interfaces come and go. The special case when a
|
* gateway changes or interfaces come and go. The special case when a
|
||||||
* service is declared with <!> means it does not support SIGHUP but
|
* service is declared with <!> means it does not support SIGHUP but
|
||||||
* must be STOP/START'ed at system reconfiguration.
|
* must be STOP/START'ed at system reconfiguration. For run/task a <!>
|
||||||
|
* means Finit can relax its promise to run at least once per runlevel.
|
||||||
|
* I.e., for run/task conditions that would otherwise block bootstrap:
|
||||||
|
*
|
||||||
|
* task [S0123456789] <!sys/pwr/fail> name:pwrfail initctl poweroff -- Power failure, shutting down
|
||||||
*
|
*
|
||||||
* Conditions can for example be: pid/NAME:ID for process dependencies,
|
* Conditions can for example be: pid/NAME:ID for process dependencies,
|
||||||
* net/<IFNAME>/up or net/<IFNAME>/exists. The condition handling is
|
* net/<IFNAME>/up or net/<IFNAME>/exists. The condition handling is
|
||||||
@@ -1425,6 +1487,7 @@ int service_register(int type, char *cfg, struct rlimit rlimit[], char *file)
|
|||||||
char *id = NULL, *env = NULL, *cgroup = NULL;
|
char *id = NULL, *env = NULL, *cgroup = NULL;
|
||||||
char *pre_script = NULL, *post_script = NULL;
|
char *pre_script = NULL, *post_script = NULL;
|
||||||
char *ready_script = NULL, *conflict = NULL;
|
char *ready_script = NULL, *conflict = NULL;
|
||||||
|
char ident[MAX_IDENT_LEN];
|
||||||
char *ifstmt = NULL;
|
char *ifstmt = NULL;
|
||||||
char *notify = NULL;
|
char *notify = NULL;
|
||||||
struct tty tty = { 0 };
|
struct tty tty = { 0 };
|
||||||
@@ -1549,8 +1612,16 @@ int service_register(int type, char *cfg, struct rlimit rlimit[], char *file)
|
|||||||
}
|
}
|
||||||
|
|
||||||
name = parse_name(cmd, name);
|
name = parse_name(cmd, name);
|
||||||
if (!id)
|
strlcpy(ident, name, sizeof(ident));
|
||||||
|
if (!id) {
|
||||||
id = "";
|
id = "";
|
||||||
|
} else {
|
||||||
|
strlcat(ident, ":", sizeof(ident));
|
||||||
|
strlcat(ident, id, sizeof(ident));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ifstmt && !svc_ifthen(1, ident, ifstmt))
|
||||||
|
return 0;
|
||||||
|
|
||||||
levels = conf_parse_runlevels(runlevels);
|
levels = conf_parse_runlevels(runlevels);
|
||||||
if (runlevel != INIT_LEVEL && !ISOTHER(levels, INIT_LEVEL)) {
|
if (runlevel != INIT_LEVEL && !ISOTHER(levels, INIT_LEVEL)) {
|
||||||
@@ -1715,17 +1786,12 @@ int service_register(int type, char *cfg, struct rlimit rlimit[], char *file)
|
|||||||
else
|
else
|
||||||
svc->log.enabled = 0;
|
svc->log.enabled = 0;
|
||||||
}
|
}
|
||||||
if (notify) {
|
|
||||||
int type = parse_notify(notify);
|
|
||||||
|
|
||||||
if (type <= 0)
|
if (notify)
|
||||||
goto disable_notify;
|
svc->notify = parse_notify(notify);
|
||||||
svc->notify = type;
|
else
|
||||||
} else if (svc->notify) {
|
svc->notify = readiness;
|
||||||
disable_notify:
|
|
||||||
/* XXX: close existing socket */
|
|
||||||
svc->notify = 0;
|
|
||||||
}
|
|
||||||
if (desc)
|
if (desc)
|
||||||
strlcpy(svc->desc, desc, sizeof(svc->desc));
|
strlcpy(svc->desc, desc, sizeof(svc->desc));
|
||||||
else if (type == SVC_TYPE_TTY)
|
else if (type == SVC_TYPE_TTY)
|
||||||
@@ -1847,11 +1913,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 +1961,17 @@ 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) {
|
||||||
|
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)) {
|
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 +2027,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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2183,6 +2255,7 @@ static void service_retry(svc_t *svc)
|
|||||||
static void svc_set_state(svc_t *svc, svc_state_t new_state)
|
static void svc_set_state(svc_t *svc, svc_state_t new_state)
|
||||||
{
|
{
|
||||||
svc_state_t *state = (svc_state_t *)&svc->state;
|
svc_state_t *state = (svc_state_t *)&svc->state;
|
||||||
|
const svc_state_t old_state = svc->state;
|
||||||
|
|
||||||
/* if PID isn't collected within SVC_TERM_TIMEOUT msec, kill it! */
|
/* if PID isn't collected within SVC_TERM_TIMEOUT msec, kill it! */
|
||||||
if (new_state == SVC_STOPPING_STATE) {
|
if (new_state == SVC_STOPPING_STATE) {
|
||||||
@@ -2203,7 +2276,7 @@ static void svc_set_state(svc_t *svc, svc_state_t new_state)
|
|||||||
snprintf(failure, sizeof(failure), "%s/%s/failure", svc_typestr(svc), svc_ident(svc, NULL, 0));
|
snprintf(failure, sizeof(failure), "%s/%s/failure", svc_typestr(svc), svc_ident(svc, NULL, 0));
|
||||||
|
|
||||||
/* create success/failure condition when entering SVC_DONE_STATE. */
|
/* create success/failure condition when entering SVC_DONE_STATE. */
|
||||||
if (*state == SVC_DONE_STATE) {
|
if (new_state == SVC_DONE_STATE) {
|
||||||
if (svc->started && !WEXITSTATUS(svc->status))
|
if (svc->started && !WEXITSTATUS(svc->status))
|
||||||
cond_set_oneshot(success);
|
cond_set_oneshot(success);
|
||||||
else
|
else
|
||||||
@@ -2211,7 +2284,7 @@ static void svc_set_state(svc_t *svc, svc_state_t new_state)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* clear all conditions when entering SVC_HALTED_STATE. */
|
/* clear all conditions when entering SVC_HALTED_STATE. */
|
||||||
if (*state == SVC_HALTED_STATE) {
|
if (new_state == SVC_HALTED_STATE) {
|
||||||
cond_clear(success);
|
cond_clear(success);
|
||||||
cond_clear(failure);
|
cond_clear(failure);
|
||||||
}
|
}
|
||||||
@@ -2221,9 +2294,14 @@ static void svc_set_state(svc_t *svc, svc_state_t new_state)
|
|||||||
char cond[MAX_COND_LEN];
|
char cond[MAX_COND_LEN];
|
||||||
|
|
||||||
snprintf(cond, sizeof(cond), "service/%s/", svc_ident(svc, NULL, 0));
|
snprintf(cond, sizeof(cond), "service/%s/", svc_ident(svc, NULL, 0));
|
||||||
cond_clear(cond);
|
|
||||||
|
|
||||||
switch (svc->state) {
|
if ((old_state == SVC_RUNNING_STATE && new_state == SVC_PAUSED_STATE) ||
|
||||||
|
(old_state == SVC_PAUSED_STATE && new_state == SVC_RUNNING_STATE))
|
||||||
|
; /* only paused during reload, don't clear conds. */
|
||||||
|
else
|
||||||
|
cond_clear(cond);
|
||||||
|
|
||||||
|
switch (new_state) {
|
||||||
case SVC_HALTED_STATE:
|
case SVC_HALTED_STATE:
|
||||||
case SVC_RUNNING_STATE:
|
case SVC_RUNNING_STATE:
|
||||||
strlcat(cond, svc_status(svc), sizeof(cond));
|
strlcat(cond, svc_status(svc), sizeof(cond));
|
||||||
@@ -2294,9 +2372,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);
|
||||||
}
|
}
|
||||||
@@ -2315,11 +2395,7 @@ restart:
|
|||||||
char condstr[MAX_COND_LEN];
|
char condstr[MAX_COND_LEN];
|
||||||
|
|
||||||
dbg("%s: stopped, cleaning up timers and conditions ...", svc_ident(svc, NULL, 0));
|
dbg("%s: stopped, cleaning up timers and conditions ...", svc_ident(svc, NULL, 0));
|
||||||
if (svc->notify && svc->notify_watcher.fd > 0) {
|
service_notify_stop(svc);
|
||||||
uev_io_stop(&svc->notify_watcher);
|
|
||||||
close(svc->notify_watcher.fd);
|
|
||||||
svc->notify_watcher.fd = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
service_timeout_cancel(svc);
|
service_timeout_cancel(svc);
|
||||||
cond_clear(mkcond(svc, condstr, sizeof(condstr)));
|
cond_clear(mkcond(svc, condstr, sizeof(condstr)));
|
||||||
@@ -2459,7 +2535,7 @@ restart:
|
|||||||
|
|
||||||
case COND_ON:
|
case COND_ON:
|
||||||
if (svc_is_changed(svc)) {
|
if (svc_is_changed(svc)) {
|
||||||
if (svc_nohup(svc))
|
if (svc_nohup(svc) || !svc_is_daemon(svc))
|
||||||
service_stop(svc);
|
service_stop(svc);
|
||||||
else {
|
else {
|
||||||
/*
|
/*
|
||||||
@@ -2473,6 +2549,8 @@ restart:
|
|||||||
|
|
||||||
svc_mark_clean(svc);
|
svc_mark_clean(svc);
|
||||||
}
|
}
|
||||||
|
if (svc->notify == SVC_NOTIFY_NONE)
|
||||||
|
service_ready(svc);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -2497,16 +2575,21 @@ restart:
|
|||||||
svc_set_state(svc, SVC_RUNNING_STATE);
|
svc_set_state(svc, SVC_RUNNING_STATE);
|
||||||
/* Reassert condition if we go from waiting and no change */
|
/* Reassert condition if we go from waiting and no change */
|
||||||
if (!svc_is_changed(svc)) {
|
if (!svc_is_changed(svc)) {
|
||||||
char name[MAX_COND_LEN];
|
if (svc->notify == SVC_NOTIFY_PID) {
|
||||||
|
char name[MAX_COND_LEN];
|
||||||
|
|
||||||
mkcond(svc, name, sizeof(name));
|
mkcond(svc, name, sizeof(name));
|
||||||
dbg("Reassert condition %s", name);
|
dbg("Reassert condition %s", name);
|
||||||
cond_set_path(cond_path(name), COND_ON);
|
cond_set_path(cond_path(name), COND_ON);
|
||||||
|
}
|
||||||
|
|
||||||
|
dbg("Reassert %s ready condition", svc_ident(svc, NULL, 0));
|
||||||
|
service_ready(svc);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case COND_OFF:
|
case COND_OFF:
|
||||||
dbg("Condition for %s is off, sending SIGCONT + SIGTERM", svc->name);
|
dbg("Condition for %s is off, sending SIGCONT + SIGTERM", svc_ident(svc, NULL, 0));
|
||||||
kill(svc->pid, SIGCONT);
|
kill(svc->pid, SIGCONT);
|
||||||
service_stop(svc);
|
service_stop(svc);
|
||||||
break;
|
break;
|
||||||
@@ -2560,7 +2643,12 @@ void service_runtask_clean(void)
|
|||||||
if (!svc_is_runtask(svc))
|
if (!svc_is_runtask(svc))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
svc->once = 0;
|
/* run/task declared with <!> */
|
||||||
|
if (svc->sighup)
|
||||||
|
svc->once = 1;
|
||||||
|
else
|
||||||
|
svc->once = 0;
|
||||||
|
|
||||||
if (svc->state == SVC_DONE_STATE)
|
if (svc->state == SVC_DONE_STATE)
|
||||||
svc_set_state(svc, SVC_HALTED_STATE);
|
svc_set_state(svc, SVC_HALTED_STATE);
|
||||||
}
|
}
|
||||||
@@ -2568,6 +2656,7 @@ void service_runtask_clean(void)
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* service_completed - Have run/task completed in current runlevel
|
* service_completed - Have run/task completed in current runlevel
|
||||||
|
* @svcp: On %FALSE return, this points to the first incomplete svc
|
||||||
*
|
*
|
||||||
* This function checks if all run/task have run once in the current
|
* This function checks if all run/task have run once in the current
|
||||||
* runlevel. E.g., at bootstrap we must wait for these scripts or
|
* runlevel. E.g., at bootstrap we must wait for these scripts or
|
||||||
@@ -2580,7 +2669,7 @@ void service_runtask_clean(void)
|
|||||||
* Returns:
|
* Returns:
|
||||||
* %TRUE(1) or %FALSE(0)
|
* %TRUE(1) or %FALSE(0)
|
||||||
*/
|
*/
|
||||||
int service_completed(void)
|
int service_completed(svc_t **svcp)
|
||||||
{
|
{
|
||||||
svc_t *svc, *iter = NULL;
|
svc_t *svc, *iter = NULL;
|
||||||
|
|
||||||
@@ -2602,6 +2691,8 @@ int service_completed(void)
|
|||||||
|
|
||||||
if (!svc->once) {
|
if (!svc->once) {
|
||||||
dbg("%s has not yet completed ...", svc_ident(svc, NULL, 0));
|
dbg("%s has not yet completed ...", svc_ident(svc, NULL, 0));
|
||||||
|
if (svcp)
|
||||||
|
*svcp = svc;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
dbg("%s has completed ...", svc_ident(svc, NULL, 0));
|
dbg("%s has completed ...", svc_ident(svc, NULL, 0));
|
||||||
@@ -2620,13 +2711,13 @@ void service_notify_reconf(void)
|
|||||||
svc_t *svc, *iter = NULL;
|
svc_t *svc, *iter = NULL;
|
||||||
|
|
||||||
for (svc = svc_iterator(&iter, 1); svc; svc = svc_iterator(&iter, 0)) {
|
for (svc = svc_iterator(&iter, 1); svc; svc = svc_iterator(&iter, 0)) {
|
||||||
if (!svc->notify)
|
if (svc->notify == SVC_NOTIFY_PID)
|
||||||
continue; /* managed by pidfile plugin */
|
continue; /* managed by pidfile plugin */
|
||||||
|
|
||||||
if (svc->state != SVC_RUNNING_STATE)
|
if (svc->state != SVC_RUNNING_STATE)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (svc_is_changed(svc) || svc_is_starting(svc))
|
if (svc->notify != SVC_NOTIFY_NONE && (svc_is_changed(svc) || svc_is_starting(svc)))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
service_ready(svc);
|
service_ready(svc);
|
||||||
@@ -2673,7 +2764,7 @@ void service_notify_cb(uev_t *w, void *arg, int events)
|
|||||||
service_ready(svc);
|
service_ready(svc);
|
||||||
|
|
||||||
/* s6 applications close their socket after notification */
|
/* s6 applications close their socket after notification */
|
||||||
if (svc->notify == 2) {
|
if (svc->notify == SVC_NOTIFY_S6) {
|
||||||
uev_io_stop(w);
|
uev_io_stop(w);
|
||||||
close(w->fd);
|
close(w->fd);
|
||||||
w->fd = 0;
|
w->fd = 0;
|
||||||
|
|||||||
+1
-1
@@ -49,7 +49,7 @@ int service_step (svc_t *svc);
|
|||||||
void service_step_all (int types);
|
void service_step_all (int types);
|
||||||
void service_worker (void *unused);
|
void service_worker (void *unused);
|
||||||
|
|
||||||
int service_completed (void);
|
int service_completed (svc_t **svc);
|
||||||
void service_notify_reconf (void);
|
void service_notify_reconf (void);
|
||||||
|
|
||||||
void service_init (uev_ctx_t *ctx);
|
void service_init (uev_ctx_t *ctx);
|
||||||
|
|||||||
@@ -52,22 +52,30 @@ sm_t sm;
|
|||||||
*/
|
*/
|
||||||
static void sm_check_bootstrap(void *work)
|
static void sm_check_bootstrap(void *work)
|
||||||
{
|
{
|
||||||
static int cnt = 120 * 10; /* We run with 100ms period */
|
static int timeout = 120;
|
||||||
int level = cfglevel;
|
int bootstrap_done;
|
||||||
|
int level = cfglevel;
|
||||||
|
svc_t *svc = NULL;
|
||||||
|
|
||||||
dbg("Step all services ...");
|
dbg("Step all services ...");
|
||||||
service_step_all(SVC_TYPE_ANY);
|
service_step_all(SVC_TYPE_ANY);
|
||||||
|
|
||||||
if (cnt-- > 0 && !service_completed()) {
|
bootstrap_done = service_completed(&svc);
|
||||||
dbg("Not all bootstrap run/tasks have completed yet ... %d", cnt);
|
if (timeout-- > 0 && !bootstrap_done) {
|
||||||
|
dbg("Not all bootstrap run/tasks have completed yet ... %d", timeout);
|
||||||
schedule_work(work);
|
schedule_work(work);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cnt > 0)
|
if (timeout > 0) {
|
||||||
dbg("All run/task have completed, resuming bootstrap.");
|
dbg("All run/task have completed, resuming bootstrap.");
|
||||||
else
|
} else {
|
||||||
dbg("Timeout, resuming bootstrap.");
|
dbg("Timeout, resuming bootstrap.");
|
||||||
|
if (svc)
|
||||||
|
print(2, "Timeout waiting for %s to run, resuming bootstrap", svc_ident(svc, NULL, 0));
|
||||||
|
else
|
||||||
|
print(2, "Timeout waiting for unknown run/task, resuming bootstrap");
|
||||||
|
}
|
||||||
|
|
||||||
dbg("Flushing pending .conf file events ...");
|
dbg("Flushing pending .conf file events ...");
|
||||||
conf_flush_events();
|
conf_flush_events();
|
||||||
@@ -208,7 +216,7 @@ restart:
|
|||||||
service_step_all(SVC_TYPE_ANY);
|
service_step_all(SVC_TYPE_ANY);
|
||||||
|
|
||||||
/* Allow runparts to start */
|
/* Allow runparts to start */
|
||||||
cond_set("int/bootstrap");
|
cond_set_oneshot("int/bootstrap");
|
||||||
|
|
||||||
if (sm->newlevel == -1)
|
if (sm->newlevel == -1)
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -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,14 +701,16 @@ 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)
|
||||||
{
|
{
|
||||||
|
char stmts[MAX_IDENT_LEN];
|
||||||
int not = 0;
|
int not = 0;
|
||||||
svc_t *svc;
|
svc_t *svc;
|
||||||
|
|
||||||
@@ -707,40 +722,49 @@ int svc_ifthen(const char *ident, char *stmt)
|
|||||||
char *ptr = ++stmt;
|
char *ptr = ++stmt;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
||||||
if (stmt[0] == '!') {
|
if (is_conf)
|
||||||
stmt++;
|
return 1;
|
||||||
not++;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (ptr[i] != '>' && ptr[i] != 0)
|
while (ptr[i] != '>' && ptr[i] != 0)
|
||||||
i++;
|
i++;
|
||||||
ptr[i] = 0;
|
ptr[i] = 0;
|
||||||
|
|
||||||
cond = cond_get(stmt);
|
strlcpy(stmts, stmt, sizeof(stmts));
|
||||||
if (not && cond == COND_ON) {
|
for (stmt = strtok(stmts, ","); stmt; stmt = strtok(NULL, ","), not = 0) {
|
||||||
logit(LOG_NOTICE, "skipping %s, cond %s is on.", ident, stmt);
|
if (stmt[0] == '!') {
|
||||||
return 0;
|
stmt++;
|
||||||
}
|
not++;
|
||||||
if (!not && cond == COND_OFF) {
|
}
|
||||||
logit(LOG_NOTICE, "skipping %s, cond %s is off.", ident, stmt);
|
|
||||||
return 0;
|
cond = cond_get(stmt);
|
||||||
|
if (not && cond == COND_ON)
|
||||||
|
return 0;
|
||||||
|
if (!not && cond == COND_OFF)
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stmt[0] == '!') {
|
if (!is_conf)
|
||||||
stmt++;
|
return 1;
|
||||||
not++;
|
|
||||||
}
|
|
||||||
|
|
||||||
svc = svc_find_by_str(stmt);
|
strlcpy(stmts, stmt, sizeof(stmts));
|
||||||
if (not && svc) {
|
for (stmt = strtok(stmts, ","); stmt; stmt = strtok(NULL, ","), not = 0) {
|
||||||
logit(LOG_NOTICE, "skipping %s, %s already loaded.", ident, svc_ident(svc, NULL, 0));
|
if (stmt[0] == '!') {
|
||||||
return 0;
|
stmt++;
|
||||||
}
|
not++;
|
||||||
if (!not && !svc) {
|
}
|
||||||
logit(LOG_NOTICE, "skipping %s, %s not available.", ident, stmt);
|
|
||||||
return 0;
|
svc = svc_find_by_str(stmt);
|
||||||
|
if (not && svc) {
|
||||||
|
logit(LOG_NOTICE, "skipping %s, %s already loaded.", ident, svc_ident(svc, NULL, 0));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (!not && !svc) {
|
||||||
|
logit(LOG_NOTICE, "skipping %s, %s not available.", ident, stmt);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
|
|||||||
@@ -83,6 +83,14 @@ typedef enum {
|
|||||||
SVC_ONCRASH_SCRIPT,
|
SVC_ONCRASH_SCRIPT,
|
||||||
} svc_oncrash_action_t;
|
} svc_oncrash_action_t;
|
||||||
|
|
||||||
|
/* 0: none, 1: systemd, 2: s6 */
|
||||||
|
typedef enum {
|
||||||
|
SVC_NOTIFY_NONE = 0,
|
||||||
|
SVC_NOTIFY_PID,
|
||||||
|
SVC_NOTIFY_SYSTEMD,
|
||||||
|
SVC_NOTIFY_S6,
|
||||||
|
} svc_notify_t;
|
||||||
|
|
||||||
#define MAX_ID_LEN 16
|
#define MAX_ID_LEN 16
|
||||||
#define MAX_ARG_LEN 64
|
#define MAX_ARG_LEN 64
|
||||||
#define MAX_CMD_LEN 256
|
#define MAX_CMD_LEN 256
|
||||||
@@ -202,7 +210,7 @@ typedef struct svc {
|
|||||||
/*
|
/*
|
||||||
* Readiness notification socket: systemd, s6
|
* Readiness notification socket: systemd, s6
|
||||||
*/
|
*/
|
||||||
int notify; /* 0: none, 1: systemd, 2: s6 */
|
svc_notify_t notify;
|
||||||
uev_t notify_watcher; /* i/o watcher */
|
uev_t notify_watcher; /* i/o watcher */
|
||||||
|
|
||||||
/* time at svc_del(), used by gc timer */
|
/* time at svc_del(), used by gc timer */
|
||||||
@@ -241,7 +249,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
-1
@@ -471,7 +471,7 @@ void tmpfilesd(void)
|
|||||||
/* in priority order */
|
/* in priority order */
|
||||||
char *dir[] = {
|
char *dir[] = {
|
||||||
FINIT_TMPFILES "/*.conf",
|
FINIT_TMPFILES "/*.conf",
|
||||||
TMPFILES_PATH "/*.conf",
|
TMPFILES_PATH_ "/*.conf",
|
||||||
"/usr/lib/tmpfiles.d/*.conf",
|
"/usr/lib/tmpfiles.d/*.conf",
|
||||||
"/run/tmpfiles.d/*.conf",
|
"/run/tmpfiles.d/*.conf",
|
||||||
"/etc/tmpfiles.d/*.conf", /* local admin overrides */
|
"/etc/tmpfiles.d/*.conf", /* local admin overrides */
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -1,2 +1,4 @@
|
|||||||
Makefile
|
Makefile
|
||||||
Makefile.in
|
Makefile.in
|
||||||
|
# generated
|
||||||
|
10-hotplug.conf
|
||||||
|
|||||||
@@ -0,0 +1,53 @@
|
|||||||
|
# System hotplug handled by udev, mdevd, or mdev (preferred order)
|
||||||
|
#
|
||||||
|
# Your system usually has either udevd, mdev, or mdevd. They probe the system
|
||||||
|
# for devices, loading modules and any firmware needed. Since the bootstrap
|
||||||
|
# often needs to be synchronized carefully, we suggest using your system log
|
||||||
|
# daemon as the barrier for all other services. E.g.:
|
||||||
|
#
|
||||||
|
# service if:udevd <run/udevadm:5/success> [S0123456789] syslogd -F -- System log daemon
|
||||||
|
# service if:mdev <run/coldplug/success> [S0123456789] syslogd -F -- System log daemon
|
||||||
|
# service if:mdevd <run/coldplug/success> [S0123456789] syslogd -F -- System log daemon
|
||||||
|
#
|
||||||
|
# This provdes a <pid/syslogd> condition that can act as a barrier for all
|
||||||
|
# other services. Notice the `if:` statement and the condition for starting
|
||||||
|
# syslogd is only considered if either udevd or mdev (service) is loaded and
|
||||||
|
# is guaranteed to run after each respective run stanza have completed.
|
||||||
|
#
|
||||||
|
# Override this file by copying it to /etc/finit.d/, using the same name, then
|
||||||
|
# change the contents any way you like, it can even be empty.
|
||||||
|
|
||||||
|
# Check for systemd-udevd and eudev, if we find both, we opt for the latter.
|
||||||
|
service nowarn [S12345789] cgroup.system name:udevd notify:none pid:udevd log /lib/systemd/systemd-udevd -- Device event daemon (udev)
|
||||||
|
service nowarn [S12345789] cgroup.system name:udevd notify:none pid:udevd log udevd -D -- Device event daemon (udev)
|
||||||
|
|
||||||
|
# Wait for udevd to start, then trigger coldplug events and module loading.
|
||||||
|
# The last 'settle' call waits for it to finalize processing all uevents.
|
||||||
|
run nowarn if:udevd cgroup.init :1 [S] <service/udevd/ready> log udevadm settle -t 0 --
|
||||||
|
run nowarn if:udevd cgroup.init :2 [S] <service/udevd/ready> log udevadm control --reload --
|
||||||
|
run nowarn if:udevd cgroup.init :3 [S] <service/udevd/ready> log udevadm trigger -c add -t devices -- Requesting device events
|
||||||
|
run nowarn if:udevd cgroup.init :4 [S] <service/udevd/ready> log udevadm trigger -c add -t subsystems -- Requesting subsystem events
|
||||||
|
run nowarn if:udevd cgroup.init :5 [S] <service/udevd/ready> log udevadm settle -t 30 -- Waiting for udev to finish
|
||||||
|
|
||||||
|
# If udevd is not available, check for mdevd. Unlike plain 'mdev -df', the
|
||||||
|
# mdevd-coldplug process exits when mdevd has completed. So the condition
|
||||||
|
# <run/coldplug/success> (same as for plain mdev below) can be relied on as a
|
||||||
|
# barrier for services that, e.g., need to probe for switchcore ports or PHYs
|
||||||
|
# that require firmware loading before they show up.
|
||||||
|
service nowarn conflict:udevd,mdev cgroup.init notify:none if:!udevd \
|
||||||
|
[S12345789] notify:s6 mdevd -O 4 -D %n -- Device event daemon (mdevd)
|
||||||
|
run nowarn conflict:udevd,mdev cgroup.init name:coldplug <service/mdevd/ready> \
|
||||||
|
[S] mdevd-coldplug -- Cold plugging system
|
||||||
|
|
||||||
|
# If neither udevd or mdevd are available, fall back to mdev. The new daemon
|
||||||
|
# mode calls `mdev -s` internally but does not create a PID file when that is
|
||||||
|
# done, so synchronization with coldplug is fragile.
|
||||||
|
service nowarn conflict:udevd,mdevd cgroup.init notify:none if:!udevd,!mdevd \
|
||||||
|
[S12345789] mdev -df -S -- Device event daemon (mdev)
|
||||||
|
|
||||||
|
# Trigger a replay of all uevents from boot, before userspace was up and the
|
||||||
|
# filesystem mounted. Compared to udevd, we don't know when 'mdev -df' has
|
||||||
|
# finished processing all events, i.e., depending on <run/coldplug/success> is
|
||||||
|
# not an indicator of all devices having been (re)discovered and fully set up.
|
||||||
|
run nowarn conflict:udevd,mdevd cgroup.init name:coldplug if:mdev <service/mdev/running> \
|
||||||
|
[S] @pkglibexecdir@/coldplug -- Cold plugging system
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
# Test service, only used for `make check`, not for public use
|
# Test service, only used for `make check`, not for public use
|
||||||
service [S123456789] name:testserv pid:!/run/testserv.pid \
|
service [S123456789] name:testserv pid:!/run/testserv.pid \
|
||||||
<boot/testserv> cgroup.system \
|
<boot/testserv> cgroup.system notify:none \
|
||||||
/sbin/serv -n -p -i testserv -- Test serv daemon
|
/sbin/serv -n -p -i testserv -- Test serv daemon
|
||||||
+4
-2
@@ -1,10 +1,12 @@
|
|||||||
|
EXTRA_DIST = 10-hotplug.conf.in
|
||||||
systemdir = $(system_path)
|
systemdir = $(system_path)
|
||||||
|
system_DATA =
|
||||||
dist_system_DATA =
|
dist_system_DATA =
|
||||||
|
|
||||||
if BUILD_HOTPLUG_PLUGIN
|
if BUILD_HOTPLUG_PLUGIN
|
||||||
dist_system_DATA += hotplug.conf
|
system_DATA += 10-hotplug.conf
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if BUILD_TESTSERV_PLUGIN
|
if BUILD_TESTSERV_PLUGIN
|
||||||
dist_system_DATA += testserv.conf
|
dist_system_DATA += 90-testserv.conf
|
||||||
endif
|
endif
|
||||||
|
|||||||
@@ -1,17 +0,0 @@
|
|||||||
# System hotplug can be handled by udev or mdev
|
|
||||||
|
|
||||||
# Either we have systemd-udevd or eudev, on the rare occasion we find
|
|
||||||
# both, we opt for the latter. Remember, you can override this by a
|
|
||||||
# custom hotplug.conf in /etc/finit.d/ or /etc/finit.d/enabled/.
|
|
||||||
service nowarn [S12345789] cgroup.system name:udevd pid:udevd log /lib/systemd/systemd-udevd -- Device event managing daemon
|
|
||||||
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
|
|
||||||
|
|
||||||
# If udevd is not available, try mdev
|
|
||||||
run nowarn conflict:udevd [S] mdev -s -- Populating device tree
|
|
||||||
+10
-1
@@ -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 \
|
||||||
@@ -29,6 +32,7 @@ EXTRA_DIST += crashing.sh
|
|||||||
EXTRA_DIST += depserv.sh
|
EXTRA_DIST += depserv.sh
|
||||||
EXTRA_DIST += devmon.sh
|
EXTRA_DIST += devmon.sh
|
||||||
EXTRA_DIST += failing-sysv.sh
|
EXTRA_DIST += failing-sysv.sh
|
||||||
|
EXTRA_DIST += svc-env.sh
|
||||||
EXTRA_DIST += global-envs.sh
|
EXTRA_DIST += global-envs.sh
|
||||||
EXTRA_DIST += initctl-status-subset.sh
|
EXTRA_DIST += initctl-status-subset.sh
|
||||||
EXTRA_DIST += notify.sh
|
EXTRA_DIST += notify.sh
|
||||||
@@ -41,6 +45,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
|
||||||
@@ -49,6 +54,7 @@ EXTRA_DIST += start-stop-sysv.sh
|
|||||||
EXTRA_DIST += start-stop-serv.sh
|
EXTRA_DIST += start-stop-serv.sh
|
||||||
EXTRA_DIST += signal-service.sh
|
EXTRA_DIST += signal-service.sh
|
||||||
EXTRA_DIST += testserv.sh
|
EXTRA_DIST += testserv.sh
|
||||||
|
EXTRA_DIST += unexpected-restart.sh
|
||||||
|
|
||||||
AM_TESTS_ENVIRONMENT = SYSROOT='$(abs_builddir)/sysroot/';
|
AM_TESTS_ENVIRONMENT = SYSROOT='$(abs_builddir)/sysroot/';
|
||||||
AM_TESTS_ENVIRONMENT += export SYSROOT;
|
AM_TESTS_ENVIRONMENT += export SYSROOT;
|
||||||
@@ -71,6 +77,7 @@ TESTS += crashing.sh
|
|||||||
TESTS += depserv.sh
|
TESTS += depserv.sh
|
||||||
TESTS += devmon.sh
|
TESTS += devmon.sh
|
||||||
TESTS += failing-sysv.sh
|
TESTS += failing-sysv.sh
|
||||||
|
TESTS += svc-env.sh
|
||||||
TESTS += global-envs.sh
|
TESTS += global-envs.sh
|
||||||
TESTS += initctl-status-subset.sh
|
TESTS += initctl-status-subset.sh
|
||||||
TESTS += notify.sh
|
TESTS += notify.sh
|
||||||
@@ -80,6 +87,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
|
||||||
@@ -93,6 +101,7 @@ TESTS += signal-service.sh
|
|||||||
if TESTSERV
|
if TESTSERV
|
||||||
TESTS += testserv.sh
|
TESTS += testserv.sh
|
||||||
endif
|
endif
|
||||||
|
TESTS += unexpected-restart.sh
|
||||||
|
|
||||||
check-recursive: setup-chroot
|
check-recursive: setup-chroot
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
+55
-52
@@ -9,77 +9,80 @@ 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"
|
||||||
|
|
||||||
|
# Done, disable debug
|
||||||
|
run "initctl debug"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+33
-33
@@ -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
@@ -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
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
+13
-7
@@ -2,30 +2,36 @@
|
|||||||
set -eu
|
set -eu
|
||||||
|
|
||||||
TEST_DIR=$(dirname "$0")
|
TEST_DIR=$(dirname "$0")
|
||||||
|
# shellcheck disable=SC2034
|
||||||
|
BOOTSTRAP="foo=bar\n\
|
||||||
|
set COLORTERM=yes\n\
|
||||||
|
b aq=oroszoe\n\
|
||||||
|
baz=qux"
|
||||||
|
|
||||||
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
|
||||||
. "$TEST_DIR/lib/setup.sh"
|
. "$TEST_DIR/lib/setup.sh"
|
||||||
|
|
||||||
|
say "Waiting for runlevel 2"
|
||||||
|
sleep 2
|
||||||
|
|
||||||
#run "initctl debug"
|
#run "initctl debug"
|
||||||
say "Add custom envs to $FINIT_CONF ..."
|
|
||||||
run "echo 'foo=bar' > $FINIT_CONF"
|
|
||||||
run "echo 'baz=qux' >> $FINIT_CONF"
|
|
||||||
|
|
||||||
say "Add service stanza to $FINIT_CONF ..."
|
say "Add service stanza to $FINIT_CONF ..."
|
||||||
run "echo 'service serv -np -e foo:bar -- Verify foo=bar' >> $FINIT_CONF"
|
run "echo 'service serv -np -e foo:bar -- Verify foo=bar' >> $FINIT_CONF"
|
||||||
|
#run "cat $FINIT_CONF"
|
||||||
|
|
||||||
say 'Reload Finit'
|
say 'Reload Finit'
|
||||||
run "initctl reload"
|
run "initctl reload"
|
||||||
|
|||||||
@@ -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
@@ -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
@@ -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" "$@"
|
||||||
|
|||||||
+17
-9
@@ -143,7 +143,15 @@ log()
|
|||||||
|
|
||||||
sep()
|
sep()
|
||||||
{
|
{
|
||||||
printf "\e[2m――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――\e[0m\n"
|
heading=${1:-}
|
||||||
|
if [ -n "$heading" ]; then
|
||||||
|
num=$((72 - ${#heading} - 1))
|
||||||
|
printf "\e[1m%s " "$heading"
|
||||||
|
printf -- "―%.0s" $(seq 1 $num)
|
||||||
|
printf "\e[0m\n"
|
||||||
|
else
|
||||||
|
printf "\e[1m――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――\e[0m\n"
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
say()
|
say()
|
||||||
@@ -342,17 +350,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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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,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"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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
@@ -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
|
||||||
|
|||||||
+3
-2
@@ -37,5 +37,6 @@ while true; do
|
|||||||
sleep 1
|
sleep 1
|
||||||
done
|
done
|
||||||
|
|
||||||
texec diff -u /usr/share/runlevel/ref.log /tmp/runparts.log
|
sleep 1
|
||||||
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"
|
||||||
|
|||||||
@@ -12,12 +12,12 @@ cp "$top_builddir/test/src/serv" "$SYSROOT/sbin/"
|
|||||||
FINITBIN="$(pwd)/$top_builddir/src/finit" DEST="$SYSROOT" make -f "$srcdir/lib/sysroot.mk"
|
FINITBIN="$(pwd)/$top_builddir/src/finit" DEST="$SYSROOT" make -f "$srcdir/lib/sysroot.mk"
|
||||||
|
|
||||||
# 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; 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
|
# shellcheck disable=SC2043
|
||||||
find "$SYSROOT" -name $conf -delete
|
for conf in 10-hotplug.conf; do
|
||||||
|
find "$SYSROOT" -name $conf -delete
|
||||||
done
|
done
|
||||||
|
|
||||||
|
|||||||
@@ -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
@@ -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,3 +3,7 @@
|
|||||||
|
|
||||||
foo=bar
|
foo=bar
|
||||||
baz=qux
|
baz=qux
|
||||||
|
|
||||||
|
xyzzy=$foo
|
||||||
|
|
||||||
|
FOO_ARGS="-i $foo -l $xyzzy endarg"
|
||||||
|
|||||||
Executable
+3
@@ -0,0 +1,3 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
echo "$0 $*" >> /tmp/sysv.log
|
||||||
Symlink
+1
@@ -0,0 +1 @@
|
|||||||
|
S01abc.sh
|
||||||
Executable
+3
@@ -0,0 +1,3 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
echo "$0" >> /tmp/sysv.log
|
||||||
Executable
+3
@@ -0,0 +1,3 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
echo "$0" >> /tmp/sysv.log
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
/etc/rcS.d/S01abc.sh start
|
||||||
|
/etc/rcS.d/S02def.sh start
|
||||||
@@ -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
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Executable
+34
@@ -0,0 +1,34 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# Ensure service environment variables are sourced and expanded properly.
|
||||||
|
set -e
|
||||||
|
|
||||||
|
TEST_DIR=$(dirname "$0")
|
||||||
|
|
||||||
|
test_setup()
|
||||||
|
{
|
||||||
|
say "Test start $(date)"
|
||||||
|
}
|
||||||
|
|
||||||
|
test_teardown()
|
||||||
|
{
|
||||||
|
say "Test done $(date)"
|
||||||
|
|
||||||
|
say "Running test teardown."
|
||||||
|
run "rm -f $FINIT_CONF"
|
||||||
|
}
|
||||||
|
|
||||||
|
# shellcheck source=/dev/null
|
||||||
|
. "$TEST_DIR/lib/setup.sh"
|
||||||
|
|
||||||
|
sep "/etc/env:"
|
||||||
|
run "cat /etc/env"
|
||||||
|
run "echo 'service env:/etc/env serv -np -e xyzzy:bar -e \"FOO_ARGS:-i bar -l bar endarg\" -- serv checks xyzzy=bar' > $FINIT_CONF"
|
||||||
|
|
||||||
|
say 'Reload Finit'
|
||||||
|
run "initctl reload"
|
||||||
|
|
||||||
|
retry 'assert_num_children 1 serv'
|
||||||
|
|
||||||
|
say "Done, drop service from $FINIT_CONF ..."
|
||||||
|
run "rm $FINIT_CONF"
|
||||||
|
run "initctl reload"
|
||||||
Executable
+43
@@ -0,0 +1,43 @@
|
|||||||
|
#!/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
|
||||||
|
|
||||||
|
sleep 1
|
||||||
|
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"
|
||||||
Executable
+74
@@ -0,0 +1,74 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# A service (B) going into flux, 'initctl reload' with no changes to
|
||||||
|
# activate, should do not cause ripple effects removing any service
|
||||||
|
# conditions, e.g., <service/B/running>. During reload all services
|
||||||
|
# are paused while Finit checks for any service3 changes to activate,
|
||||||
|
# which may mean stopping or restarting existing services.
|
||||||
|
#
|
||||||
|
# Issue #382
|
||||||
|
set -e
|
||||||
|
|
||||||
|
#DEBUG=true
|
||||||
|
TEST_DIR=$(dirname "$0")
|
||||||
|
|
||||||
|
test_setup()
|
||||||
|
{
|
||||||
|
run "cat >> $FINIT_CONF" <<EOF
|
||||||
|
service log:stdout notify:pid name:A serv -np -i A -- A (pid)
|
||||||
|
service log:stdout notify:systemd <pid/A> name:B serv -np -i B -N 0 -- B needs A (systemd)
|
||||||
|
service log:stdout notify:s6 <service/B/ready> name:C serv -np -i C -N 0 -- C needs B (s6)
|
||||||
|
service log:stdout notify:none <pid/A> name:D type:forking serv -i D -- D needs A (forking)
|
||||||
|
task <service/C/ready,service/D/ready> name:allup initctl cond set allup -- Everything is up
|
||||||
|
EOF
|
||||||
|
say "Test start $(date)"
|
||||||
|
}
|
||||||
|
|
||||||
|
test_teardown()
|
||||||
|
{
|
||||||
|
say "Test done $(date)"
|
||||||
|
}
|
||||||
|
|
||||||
|
pidof()
|
||||||
|
{
|
||||||
|
texec initctl -j status "$1" | jq .pid
|
||||||
|
}
|
||||||
|
|
||||||
|
# shellcheck source=/dev/null
|
||||||
|
. "$TEST_DIR/lib/setup.sh"
|
||||||
|
|
||||||
|
sep "$FINIT_CONF"
|
||||||
|
run "cat $FINIT_CONF"
|
||||||
|
sep
|
||||||
|
run "initctl reload"
|
||||||
|
run "initctl status"
|
||||||
|
run "initctl cond dump"
|
||||||
|
sep
|
||||||
|
|
||||||
|
run "initctl debug"
|
||||||
|
say "waiting for primary startup to complete"
|
||||||
|
retry 'assert_status allup "done"' 10 1
|
||||||
|
assert_status C "running"
|
||||||
|
oldpid=$(pidof C)
|
||||||
|
|
||||||
|
sep "pre-reload status"
|
||||||
|
run "initctl status"
|
||||||
|
run "initctl cond dump"
|
||||||
|
sep
|
||||||
|
|
||||||
|
say "Reload Finit, who gets restarted?"
|
||||||
|
#run "initctl debug"
|
||||||
|
run "initctl reload"
|
||||||
|
sleep 2
|
||||||
|
|
||||||
|
sep "post-reload status"
|
||||||
|
run "initctl status"
|
||||||
|
run "initctl cond dump"
|
||||||
|
sep
|
||||||
|
|
||||||
|
assert_status A "running"
|
||||||
|
assert_status B "running"
|
||||||
|
assert_status C "running"
|
||||||
|
|
||||||
|
newpid=$(pidof C)
|
||||||
|
# shellcheck disable=SC2086
|
||||||
|
assert "C was not restarted" $oldpid -eq $newpid
|
||||||
@@ -11,4 +11,4 @@ d /run/finit/cond 0755 - - -
|
|||||||
d /run/finit/cond/pid 0755 - - -
|
d /run/finit/cond/pid 0755 - - -
|
||||||
d /run/finit/cond/sys 0755 - - -
|
d /run/finit/cond/sys 0755 - - -
|
||||||
d /run/finit/cond/usr 0755 - - -
|
d /run/finit/cond/usr 0755 - - -
|
||||||
|
d /run/finit/system 0755 - - -
|
||||||
|
|||||||
Reference in New Issue
Block a user