mirror of
https://github.com/troglobit/finit.git
synced 2026-10-13 10:14:47 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6b7478ff43 | ||
|
|
6c4c16cbdb | ||
|
|
e539dbfe37 | ||
|
|
90c6bcd365 | ||
|
|
c9c268f218 | ||
|
|
3feff37ba5 | ||
|
|
c67d15e272 | ||
|
|
8984c655f8 | ||
|
|
1a7b26bac3 | ||
|
|
1f47718012 | ||
|
|
fa13cddc28 | ||
|
|
185a72bd14 | ||
|
|
cd32c623cf | ||
|
|
ac4b9c2f93 | ||
|
|
5e9591d0a8 | ||
|
|
e3bcf9bf16 | ||
|
|
84fd3196b0 | ||
|
|
994e51e34f | ||
|
|
0a7814b391 | ||
|
|
73f72b39cf | ||
|
|
02e0aa7383 | ||
|
|
6528628b5c | ||
|
|
1480657982 | ||
|
|
33e378a345 | ||
|
|
b695b46a9d | ||
|
|
0e61ed727f | ||
|
|
e9d60a6c04 | ||
|
|
5e9edf9deb | ||
|
|
8ed2751ae1 | ||
|
|
7fec66dc09 | ||
|
|
75fa868a4b | ||
|
|
7b321de339 | ||
|
|
1691ebb292 | ||
|
|
c371c10455 | ||
|
|
a23e152f6b | ||
|
|
9210f2851e | ||
|
|
617609cbc5 | ||
|
|
b022916758 | ||
|
|
9a357b7aab | ||
|
|
ffd01b0276 | ||
|
|
2c95f091ee | ||
|
|
b75b107d6d | ||
|
|
1f2c1d2109 | ||
|
|
f328d24d01 | ||
|
|
211293a83d | ||
|
|
446f5bc8b8 | ||
|
|
0c6f748f2c | ||
|
|
a677b94ad9 | ||
|
|
6552cda605 | ||
|
|
3add682be3 | ||
|
|
abac31682d | ||
|
|
cfe915e6d5 | ||
|
|
ecf65ce44b | ||
|
|
0d742d6ae8 | ||
|
|
cf201a43df |
@@ -24,7 +24,8 @@ the maintainer(s) and make it easier for them to include your code.
|
|||||||
Coding Style
|
Coding Style
|
||||||
------------
|
------------
|
||||||
|
|
||||||
> **Tip:** Always submit code that follows the style of surrounding code!
|
> [!TIP]
|
||||||
|
> Always submit code that follows the style of surrounding code!
|
||||||
|
|
||||||
First of all, lines are allowed to be longer than 72 characters these
|
First of all, lines are allowed to be longer than 72 characters these
|
||||||
days. In fact, there exist no enforced maximum, but keeping it around
|
days. In fact, there exist no enforced maximum, but keeping it around
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ on:
|
|||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- 'dev'
|
- 'dev'
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
env:
|
env:
|
||||||
PROJECT_NAME: finit
|
PROJECT_NAME: finit
|
||||||
|
|||||||
+99
-39
@@ -4,6 +4,63 @@ Change Log
|
|||||||
All relevant changes are documented in this file.
|
All relevant changes are documented in this file.
|
||||||
|
|
||||||
|
|
||||||
|
[4.12][] - 2025-04-28
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
### Changes
|
||||||
|
- Improve notify:s6 readiness compatibility, by Aaron Andersen
|
||||||
|
- Update `runparts` usage text
|
||||||
|
|
||||||
|
### Fixes
|
||||||
|
- Fix variable overloading in urandom plugin
|
||||||
|
- Fix buffer overwrite in urandom plugin, reported by Aaron Andersen
|
||||||
|
|
||||||
|
|
||||||
|
[4.11][] - 2025-03-27
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
### Changes
|
||||||
|
- Update documentation regarding transition from runlevel S to 2, how
|
||||||
|
run/tasks must "complete" before Finit can move to the next runlevel
|
||||||
|
- Improve argument handling in bundled getty when launching login
|
||||||
|
|
||||||
|
### Fixes
|
||||||
|
- Fix #432: allow services in `setup` state to be stopped. This fixes
|
||||||
|
a serious blocker introduced in 4.10 that prevented systems from
|
||||||
|
being rebooted when any service was in this state
|
||||||
|
- Fix fallback `SIGKILL` when stopping a service with `SIGTERM` does
|
||||||
|
not work. This fixes a serious issue with services not responding to
|
||||||
|
the default `SIGTERM`
|
||||||
|
- Fix pre/post/ready/cleanup script execution if service has an
|
||||||
|
optional `env:file` (leading `-`)
|
||||||
|
- Fix blocked signals for pre/post/ready/cleanup scripts preventing
|
||||||
|
normal shutdown when a service/sysv is stopped in its setup state
|
||||||
|
- Fix issue where a pre:script creates a PID file in `/run` cause the
|
||||||
|
service to move from setup state to running. Any `svc_t` in setup,
|
||||||
|
teardown, or cleanup state should be ignored in the pidfile plugin
|
||||||
|
|
||||||
|
|
||||||
|
[4.10][] - 2025-03-03
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
### Changes
|
||||||
|
- Add support for `cleanup:[0-3600,]script`, runs before service is
|
||||||
|
removed, unlike `post:script` that runs when service is stopped
|
||||||
|
- Improved entropy gathering in tertiary fallback of urandom plugin
|
||||||
|
- Reclassify `sysv` from run/task class to `service`
|
||||||
|
|
||||||
|
### Fixes
|
||||||
|
- Fix #427: using an external getty with custom login program cause
|
||||||
|
Finit to use login program as the getty command
|
||||||
|
- Fix #428: allow `sysctl` path to be set at build time
|
||||||
|
- Fix #429: regression in v4.9 causing Finit to segfault at shutdown
|
||||||
|
- Fix possible memory leak when sourcing a service `env:file`
|
||||||
|
- Finit now waits until all `post:scripts` have run before returning
|
||||||
|
OK to `initctl <reload|runlevel>`. This also applies to the new
|
||||||
|
`cleanup:scripts` introduced in this release
|
||||||
|
- RFC3154 conformance formatting fix for `/dev/kmsg` fallback logging
|
||||||
|
|
||||||
|
|
||||||
[4.9][] - 2025-02-15
|
[4.9][] - 2025-02-15
|
||||||
--------------------
|
--------------------
|
||||||
|
|
||||||
@@ -68,7 +125,7 @@ All relevant changes are documented in this file.
|
|||||||
|
|
||||||
### Fixes
|
### Fixes
|
||||||
- Fix #397: system shutdown/reboot can block on console input if action
|
- Fix #397: system shutdown/reboot can block on console input if action
|
||||||
is started remotely (ssh). Caused by legact TTY screen size probing,
|
is started remotely (ssh). Caused by legacy TTY screen size probing,
|
||||||
removed from both bootstrap and shutdown/reboot
|
removed from both bootstrap and shutdown/reboot
|
||||||
- Fix #400: both `HOOK_MOUNT_ERROR` and `sulogin()` fail to trigger on
|
- Fix #400: both `HOOK_MOUNT_ERROR` and `sulogin()` fail to trigger on
|
||||||
either mount or `fsck` errors. Problem caused by unresolved status
|
either mount or `fsck` errors. Problem caused by unresolved status
|
||||||
@@ -326,7 +383,7 @@ All relevant changes are documented in this file.
|
|||||||
`/etc/finit.conf`.
|
`/etc/finit.conf`.
|
||||||
|
|
||||||
For the complete experience a new top-level configuration file directive
|
For the complete experience a new top-level configuration file directive
|
||||||
`rcsd PATH` has aslo been added. It in turn can be used by `factory.conf`
|
`rcsd PATH` has also been added. It in turn can be used by `factory.conf`
|
||||||
as follows to override `/etc/finit.d`:
|
as follows to override `/etc/finit.d`:
|
||||||
|
|
||||||
rcsd /etc/factory.d
|
rcsd /etc/factory.d
|
||||||
@@ -909,7 +966,7 @@ make sure to read the whole change log when upgrading.
|
|||||||
previously hard-coded in Finit, e.g., starting the bundled watchdogd,
|
previously hard-coded in Finit, e.g., starting the bundled watchdogd,
|
||||||
various distro packed udevd and other hotplugging tools
|
various distro packed udevd and other hotplugging tools
|
||||||
* A proper rescue mode has been added. It is started extremely early
|
* A proper rescue mode has been added. It is started extremely early
|
||||||
and is protected with a bundled `suslogin`. Exiting rescue mode now
|
and is protected with a bundled `sulogin`. Exiting rescue mode now
|
||||||
brings up the system as a normal boot, as one expects
|
brings up the system as a normal boot, as one expects
|
||||||
* Support for `sysv` start/stop scripts as well as monitoring forking
|
* Support for `sysv` start/stop scripts as well as monitoring forking
|
||||||
services, stared using `sysv` or `service` stanza
|
services, stared using `sysv` or `service` stanza
|
||||||
@@ -1740,44 +1797,47 @@ Major bug fix release.
|
|||||||
|
|
||||||
* Initial release
|
* Initial release
|
||||||
|
|
||||||
[UNRELEASED]: https://github.com/troglobit/finit/compare/4.9...HEAD
|
[UNRELEASED]: https://github.com/troglobit/finit/compare/4.11...HEAD
|
||||||
[4.9]: https://github.com/troglobit/finit/compare/4.8...4.9
|
[4.12]: https://github.com/troglobit/finit/compare/4.11...4.12
|
||||||
[4.8]: https://github.com/troglobit/finit/compare/4.7...4.8
|
[4.11]: https://github.com/troglobit/finit/compare/4.10...4.11
|
||||||
[4.7]: https://github.com/troglobit/finit/compare/4.6...4.7
|
[4.10]: https://github.com/troglobit/finit/compare/4.9...4.10
|
||||||
[4.6]: https://github.com/troglobit/finit/compare/4.5...4.6
|
[4.9]: https://github.com/troglobit/finit/compare/4.8...4.9
|
||||||
[4.5]: https://github.com/troglobit/finit/compare/4.4...4.5
|
[4.8]: https://github.com/troglobit/finit/compare/4.7...4.8
|
||||||
[4.4]: https://github.com/troglobit/finit/compare/4.3...4.4
|
[4.7]: https://github.com/troglobit/finit/compare/4.6...4.7
|
||||||
[4.3]: https://github.com/troglobit/finit/compare/4.2...4.3
|
[4.6]: https://github.com/troglobit/finit/compare/4.5...4.6
|
||||||
[4.2]: https://github.com/troglobit/finit/compare/4.1...4.2
|
[4.5]: https://github.com/troglobit/finit/compare/4.4...4.5
|
||||||
[4.1]: https://github.com/troglobit/finit/compare/4.0...4.1
|
[4.4]: https://github.com/troglobit/finit/compare/4.3...4.4
|
||||||
[4.0]: https://github.com/troglobit/finit/compare/3.1...4.0
|
[4.3]: https://github.com/troglobit/finit/compare/4.2...4.3
|
||||||
[3.1]: https://github.com/troglobit/finit/compare/3.0...3.1
|
[4.2]: https://github.com/troglobit/finit/compare/4.1...4.2
|
||||||
[3.0]: https://github.com/troglobit/finit/compare/2.4...3.0
|
[4.1]: https://github.com/troglobit/finit/compare/4.0...4.1
|
||||||
[2.4]: https://github.com/troglobit/finit/compare/2.3...2.4
|
[4.0]: https://github.com/troglobit/finit/compare/3.1...4.0
|
||||||
[2.3]: https://github.com/troglobit/finit/compare/2.2...2.3
|
[3.1]: https://github.com/troglobit/finit/compare/3.0...3.1
|
||||||
[2.2]: https://github.com/troglobit/finit/compare/2.1...2.2
|
[3.0]: https://github.com/troglobit/finit/compare/2.4...3.0
|
||||||
[2.1]: https://github.com/troglobit/finit/compare/2.0...2.1
|
[2.4]: https://github.com/troglobit/finit/compare/2.3...2.4
|
||||||
[2.0]: https://github.com/troglobit/finit/compare/1.12...2.0
|
[2.3]: https://github.com/troglobit/finit/compare/2.2...2.3
|
||||||
|
[2.2]: https://github.com/troglobit/finit/compare/2.1...2.2
|
||||||
|
[2.1]: https://github.com/troglobit/finit/compare/2.0...2.1
|
||||||
|
[2.0]: https://github.com/troglobit/finit/compare/1.12...2.0
|
||||||
[1.12]: https://github.com/troglobit/finit/compare/1.11...1.12
|
[1.12]: https://github.com/troglobit/finit/compare/1.11...1.12
|
||||||
[1.11]: https://github.com/troglobit/finit/compare/1.10...1.11
|
[1.11]: https://github.com/troglobit/finit/compare/1.10...1.11
|
||||||
[1.10]: https://github.com/troglobit/finit/compare/1.9...1.10
|
[1.10]: https://github.com/troglobit/finit/compare/1.9...1.10
|
||||||
[1.9]: https://github.com/troglobit/finit/compare/1.8...1.9
|
[1.9]: https://github.com/troglobit/finit/compare/1.8...1.9
|
||||||
[1.8]: https://github.com/troglobit/finit/compare/1.7...1.8
|
[1.8]: https://github.com/troglobit/finit/compare/1.7...1.8
|
||||||
[1.7]: https://github.com/troglobit/finit/compare/1.6...1.7
|
[1.7]: https://github.com/troglobit/finit/compare/1.6...1.7
|
||||||
[1.6]: https://github.com/troglobit/finit/compare/1.5...1.6
|
[1.6]: https://github.com/troglobit/finit/compare/1.5...1.6
|
||||||
[1.5]: https://github.com/troglobit/finit/compare/1.4...1.5
|
[1.5]: https://github.com/troglobit/finit/compare/1.4...1.5
|
||||||
[1.4]: https://github.com/troglobit/finit/compare/1.3...1.4
|
[1.4]: https://github.com/troglobit/finit/compare/1.3...1.4
|
||||||
[1.3]: https://github.com/troglobit/finit/compare/1.2...1.3
|
[1.3]: https://github.com/troglobit/finit/compare/1.2...1.3
|
||||||
[1.2]: https://github.com/troglobit/finit/compare/1.1...1.2
|
[1.2]: https://github.com/troglobit/finit/compare/1.1...1.2
|
||||||
[1.1]: https://github.com/troglobit/finit/compare/1.0...1.1
|
[1.1]: https://github.com/troglobit/finit/compare/1.0...1.1
|
||||||
[1.0]: https://github.com/troglobit/finit/compare/0.9...1.0
|
[1.0]: https://github.com/troglobit/finit/compare/0.9...1.0
|
||||||
[0.9]: https://github.com/troglobit/finit/compare/0.8...0.9
|
[0.9]: https://github.com/troglobit/finit/compare/0.8...0.9
|
||||||
[0.8]: https://github.com/troglobit/finit/compare/0.7...0.8
|
[0.8]: https://github.com/troglobit/finit/compare/0.7...0.8
|
||||||
[0.7]: https://github.com/troglobit/finit/compare/0.6...0.7
|
[0.7]: https://github.com/troglobit/finit/compare/0.6...0.7
|
||||||
[0.6]: https://github.com/troglobit/finit/compare/0.5...0.6
|
[0.6]: https://github.com/troglobit/finit/compare/0.5...0.6
|
||||||
[0.5]: https://github.com/troglobit/finit/compare/0.4...0.5
|
[0.5]: https://github.com/troglobit/finit/compare/0.4...0.5
|
||||||
[0.4]: https://github.com/troglobit/finit/compare/0.3...0.4
|
[0.4]: https://github.com/troglobit/finit/compare/0.3...0.4
|
||||||
[0.3]: https://github.com/troglobit/finit/compare/0.2...0.3
|
[0.3]: https://github.com/troglobit/finit/compare/0.2...0.3
|
||||||
[0.2]: https://github.com/troglobit/finit/compare/0.1...0.2
|
[0.2]: https://github.com/troglobit/finit/compare/0.1...0.2
|
||||||
[libuEv]: https://github.com/troglobit/libuev
|
[libuEv]: https://github.com/troglobit/libuev
|
||||||
[dea3ae8]: https://github.com/troglobit/finit/commit/dea3ae8
|
[dea3ae8]: https://github.com/troglobit/finit/commit/dea3ae8
|
||||||
|
|||||||
@@ -61,12 +61,13 @@ distributions:
|
|||||||
* [Alpine Linux](contrib/alpine/), and
|
* [Alpine Linux](contrib/alpine/), and
|
||||||
* [Debian GNU/Linux](contrib/debian/), also works on Ubuntu/Linux Mint
|
* [Debian GNU/Linux](contrib/debian/), also works on Ubuntu/Linux Mint
|
||||||
|
|
||||||
> **Note:** support for various Linux distributions does not mean Finit
|
> [!NOTE]
|
||||||
> installs easily on all architectures. The bundled install scripts are
|
> Support for various Linux distributions does not mean Finit installs
|
||||||
> examples for standard installations, tested on amd64 (x86_64) systems.
|
> easily on all architectures. The bundled install scripts are examples
|
||||||
> Custom setups, e.g., for embedded systems, can be found in any of the
|
> for standard installations, tested on amd64 (x86_64) systems. Custom
|
||||||
> following [Buildroot][] based examples: [myLinux][], [Infix][], or the
|
> setups, e.g., for embedded systems, can be found in the following
|
||||||
> plain [br2-finit-demo](https://github.com/troglobit/br2-finit-demo).
|
> [Buildroot][] based examples: [myLinux][], [Infix][], or the plain
|
||||||
|
> [br2-finit-demo](https://github.com/troglobit/br2-finit-demo).
|
||||||
|
|
||||||
|
|
||||||
Example
|
Example
|
||||||
@@ -78,9 +79,10 @@ be placed in `/etc/finit.d/available` and enabled by an operator using
|
|||||||
the [initctl](#commands--status) tool. See the above mentioned Linux
|
the [initctl](#commands--status) tool. See the above mentioned Linux
|
||||||
distributions, or [myLinux][].
|
distributions, or [myLinux][].
|
||||||
|
|
||||||
> **Note:** as of Finit v4.4, .conf lines can be broken up using the
|
> [!TIP]
|
||||||
> standard UNIX continuation character (`\`), also trailing comments are
|
> As of Finit v4.4, `.conf` lines can be broken up using the standard
|
||||||
> now supported. The latter means you need to escape any hashes used in
|
> UNIX continuation character (`\`), trailing comments are now also
|
||||||
|
> supported. The latter means you need to escape any hashes used in
|
||||||
> directives and descriptions (`\#`). For more on this and examples,
|
> directives and descriptions (`\#`). For more on this and examples,
|
||||||
> see the [finit.conf(5)][] manual or [doc/config.md](doc/config.md).
|
> see the [finit.conf(5)][] manual or [doc/config.md](doc/config.md).
|
||||||
|
|
||||||
@@ -249,7 +251,7 @@ All services in runlevel S) are started first, followed by the desired
|
|||||||
run-time runlevel. Run tasks in runlevel S can be started in sequence
|
run-time runlevel. Run tasks in runlevel S can be started in sequence
|
||||||
by using `run [S] cmd`. Changing runlevels at runtime is done like any
|
by using `run [S] cmd`. Changing runlevels at runtime is done like any
|
||||||
other init, e.g. <kbd>init 4</kbd>, but also using the more advanced
|
other init, e.g. <kbd>init 4</kbd>, but also using the more advanced
|
||||||
`intictl` tool.
|
[`initctl`](#commands--status) tool.
|
||||||
|
|
||||||
|
|
||||||
**Conditions**
|
**Conditions**
|
||||||
@@ -285,6 +287,7 @@ run [S] /path/to/ident --
|
|||||||
task [2] <hw/model/foo> /path/to/foo-init -- Initializing Foo board
|
task [2] <hw/model/foo> /path/to/foo-init -- Initializing Foo board
|
||||||
```
|
```
|
||||||
|
|
||||||
|
> [!TIP]
|
||||||
> Notice the trick with an empty description to hide the call to `ident`
|
> Notice the trick with an empty description to hide the call to `ident`
|
||||||
> in the Finit progress output.
|
> in the Finit progress output.
|
||||||
|
|
||||||
@@ -367,9 +370,10 @@ The `initctl` tool has three commands to help debug and optimize the
|
|||||||
setup and monitoring of cgroups. See the `ps`, `top`, and `cgroup`
|
setup and monitoring of cgroups. See the `ps`, `top`, and `cgroup`
|
||||||
commands for details.
|
commands for details.
|
||||||
|
|
||||||
> **Note:** systems that do not support cgroups, specifically version 2,
|
> [!NOTE]
|
||||||
> are automatically detected. On such systems the above functionality
|
> Systems that do not support cgroups, specifically version 2, are
|
||||||
> is disabled early at boot.
|
> automatically detected. On such systems the above functionality is
|
||||||
|
> disabled early at boot.
|
||||||
|
|
||||||
|
|
||||||
Runparts & /etc/rc.local
|
Runparts & /etc/rc.local
|
||||||
@@ -573,9 +577,10 @@ file must be used to tell Finit to stop and start it on `reload` and
|
|||||||
`runlevel` changes. If `<>` holds more [conditions](doc/conditions.md),
|
`runlevel` changes. If `<>` holds more [conditions](doc/conditions.md),
|
||||||
these will also affect how a service is maintained.
|
these will also affect how a service is maintained.
|
||||||
|
|
||||||
> **Note:** even though it is possible to start services not belonging in
|
> [!NOTE]
|
||||||
> the current runlevel these services will not be respawned automatically
|
> Even though it is possible to start services not belonging in the
|
||||||
> by Finit if they exit (crash). Hence, if the runlevel is 2, the below
|
> current runlevel these services will not be respawned automatically by
|
||||||
|
> Finit if they exit (crash). Hence, if the runlevel is 2, the below
|
||||||
> Dropbear SSH service will not be restarted if it is killed or exits.
|
> Dropbear SSH service will not be restarted if it is killed or exits.
|
||||||
|
|
||||||
The `status` command is the default, it displays a quick overview of all
|
The `status` command is the default, it displays a quick overview of all
|
||||||
|
|||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
AC_INIT([Finit], [4.9], [https://github.com/troglobit/finit/issues],
|
AC_INIT([Finit], [4.12], [https://github.com/troglobit/finit/issues],
|
||||||
[finit], [https://troglobit.com/projects/finit/])
|
[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])
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
HowTo: Finit on Alpine Linux 3.4...3.19
|
HowTo: Finit on Alpine Linux 3.4...3.19
|
||||||
=======================================
|
=======================================
|
||||||
|
|
||||||
> **Blog** https://troglobit.com/post/2021-02-12-alpine-linux-with-finit/
|
> [!TIP]
|
||||||
|
> https://troglobit.com/post/2021-02-12-alpine-linux-with-finit/
|
||||||
|
|
||||||
HowTo use Finit to boot an [Alpine Linux][] system. It is assumed that
|
HowTo use Finit to boot an [Alpine Linux][] system. It is assumed that
|
||||||
the user has already installed make, a compiler, C library header files,
|
the user has already installed make, a compiler, C library header files,
|
||||||
|
|||||||
@@ -20,8 +20,9 @@ tools pre-systemd work as intended.
|
|||||||
|
|
||||||
root@debian:~# apt install initscripts console-setup
|
root@debian:~# apt install initscripts console-setup
|
||||||
|
|
||||||
> **Note:** as of Debian 11 (Bullseye), libuev and libite are part of
|
> [!TIP]
|
||||||
> the main section of Debian. So just install the -dev packages :)
|
> As of Debian 11 (Bullseye), libuev and libite are part of the main
|
||||||
|
> section of Debian. So just install the -dev packages :)
|
||||||
|
|
||||||
The following script can then be used to configure, build, install and
|
The following script can then be used to configure, build, install and
|
||||||
set up your system to run Finit:
|
set up your system to run Finit:
|
||||||
@@ -47,7 +48,8 @@ comands to `initctl`, followed by `reload` to activate your changes.
|
|||||||
You can also use a standard [/etc/rc.local](rc.local) for one-shot tasks
|
You can also use a standard [/etc/rc.local](rc.local) for one-shot tasks
|
||||||
and initialization like keyboard language etc.
|
and initialization like keyboard language etc.
|
||||||
|
|
||||||
> **NOTE:** X Window system, you may need to `sudo apt install elogind`
|
> [!NOTE]
|
||||||
|
> For the X Window system, you may need to `sudo apt install elogind`
|
||||||
> (Bullseye and later), followed by `initctl reload` to activate it (it
|
> (Bullseye and later), followed by `initctl reload` to activate it (it
|
||||||
> is enabled by default), and logout/login again. The elogind daemon
|
> is enabled by default), and logout/login again. The elogind daemon
|
||||||
> ensures a regular non-root user can start and interact with an X
|
> ensures a regular non-root user can start and interact with an X
|
||||||
|
|||||||
+30
-24
@@ -1,5 +1,5 @@
|
|||||||
Building
|
Building Finit
|
||||||
========
|
==============
|
||||||
|
|
||||||
* [Introduction](#introduction)
|
* [Introduction](#introduction)
|
||||||
* [Configure](#configure)
|
* [Configure](#configure)
|
||||||
@@ -17,14 +17,15 @@ optional plugins to enable. It depends on two external libraries:
|
|||||||
- [libuEv][], the event loop
|
- [libuEv][], the event loop
|
||||||
- [libite][] (-lite), much needed frog DNA
|
- [libite][] (-lite), much needed frog DNA
|
||||||
|
|
||||||
**NOTE:** Most free/open source software that uses `configure` default
|
> [!IMPORTANT]
|
||||||
to install to `/usr/local`. However, some Linux distributions do no
|
> Most free/open source software packages that use `configure` default
|
||||||
longer search that path for installed software, e.g. Fedora and Alpine
|
> to install to `/usr/local`. However, some Linux distributions do no
|
||||||
Linux. To get finit's configure script to find its dependencies you
|
> longer search that path for installed software, e.g. Fedora and Alpine
|
||||||
have to help the `pkg-config` tool a bit if you do not change the
|
> Linux. To get finit's configure script to find its dependencies you
|
||||||
default prefix path:
|
> have to help the `pkg-config` tool a bit if you do not change the
|
||||||
|
> default prefix path:
|
||||||
PKG_CONFIG_LIBDIR=/usr/local/lib/pkgconfig ./configure
|
>
|
||||||
|
> PKG_CONFIG_LIBDIR=/usr/local/lib/pkgconfig ./configure
|
||||||
|
|
||||||
The configure script checks for all dependencies, including the correct
|
The configure script checks for all dependencies, including the correct
|
||||||
version of the above mentioned libraries. Currently required versions:
|
version of the above mentioned libraries. Currently required versions:
|
||||||
@@ -71,12 +72,13 @@ Below are a few of the main switches to configure:
|
|||||||
|
|
||||||
For more configure flags, see <kbd>./configure --help</kbd>
|
For more configure flags, see <kbd>./configure --help</kbd>
|
||||||
|
|
||||||
> **Note:** the configure script is not available in the GIT sources. It is
|
> [!NOTE]
|
||||||
> however included in (officially supported) released tarballs. The
|
> The configure script is not available in the GIT sources. It is
|
||||||
> idea is that you should not need GNU autotools to build, only the
|
> however included in (officially supported) released tarballs. The
|
||||||
> above mentioned dependencies, a POSIX shell, a C compiler and make.
|
> idea is that you should not need GNU autotools to build, only the
|
||||||
> Any contributing to Finit can generate it from `configure.ac` using
|
> above mentioned dependencies, a POSIX shell, a C compiler and make.
|
||||||
> the `autogen.sh` script.
|
> Any contributing to Finit can generate it from `configure.ac` using
|
||||||
|
> the `autogen.sh` script.
|
||||||
|
|
||||||
|
|
||||||
Example
|
Example
|
||||||
@@ -115,10 +117,11 @@ Linux config to:
|
|||||||
|
|
||||||
CONFIG_UEVENT_HELPER_PATH="/sbin/mdev"
|
CONFIG_UEVENT_HELPER_PATH="/sbin/mdev"
|
||||||
|
|
||||||
**Note:** If you run into problems starting Finit, take a look at
|
> [!TIP]
|
||||||
`finit.c`. One of the most common problems is a custom Linux kernel
|
> If you run into problems starting Finit, take a look at `finit.c`.
|
||||||
build that lack `CONFIG_DEVTMPFS`. Another is too much cruft in the
|
> One of the most common problems is a custom Linux kernel build that
|
||||||
system `/etc/fstab`.
|
> lack `CONFIG_DEVTMPFS`. Another is too much cruft in the system
|
||||||
|
> `/etc/fstab`.
|
||||||
|
|
||||||
|
|
||||||
Running
|
Running
|
||||||
@@ -157,8 +160,10 @@ enabled. The default Finit rescue mode configuration is installed into
|
|||||||
|
|
||||||
By default the a root shell, without login, is started.
|
By default the a root shell, without login, is started.
|
||||||
|
|
||||||
> **Note:** in this mode `initctl` will not work. Use the `-f` flag to
|
> [!IMPORTANT]
|
||||||
> force `reboot`, `shutdown`, or `poweroff`.
|
> In rescue mode `initctl` will not work, the same goes for `reboot`,
|
||||||
|
> `shutdown`, and `poweroff` commands, provided they are the Finit
|
||||||
|
> versions of these commands. Use the `-f` flag to force the action.
|
||||||
|
|
||||||
|
|
||||||
Debugging
|
Debugging
|
||||||
@@ -187,8 +192,9 @@ kernel usually reboots: `configure --enable-emergency-shell`. However,
|
|||||||
the behavior of Finit is severely limited when this is enabled, so use
|
the behavior of Finit is severely limited when this is enabled, so use
|
||||||
it only for debugging start up issues when Finit crashes.
|
it only for debugging start up issues when Finit crashes.
|
||||||
|
|
||||||
**NOTE:** Neither of these options should be enabled on production
|
> [!CAUTION]
|
||||||
systems since they can potentially give a user root access.
|
> None of these options should be enabled on production systems since
|
||||||
|
> they can potentially give a user root access.
|
||||||
|
|
||||||
|
|
||||||
[1]: ftp://troglobit.com/finit/finit-4.3.tar.gz
|
[1]: ftp://troglobit.com/finit/finit-4.3.tar.gz
|
||||||
|
|||||||
+6
-4
@@ -4,10 +4,11 @@ Tips & Tricks with the kernel cmdline
|
|||||||
This document summarizes the different boot parameters that can be
|
This document summarizes the different boot parameters that can be
|
||||||
passed on the Linux kernel command line. Not limited to Finit.
|
passed on the Linux kernel command line. Not limited to Finit.
|
||||||
|
|
||||||
The `bool` setting is one of `on, off, true false, 1, 0`.
|
> [!IMPORTANT]
|
||||||
|
> Remember to use `--` to separate kernel parameters from parameters to
|
||||||
|
> init. E.g., `init=/sbin/finit -- finit.debug rescue`
|
||||||
|
|
||||||
> **NOTE:** remember to use `--` to separate kernel parameters from
|
The `bool` setting is one of `on, off, true false, 1, 0`.
|
||||||
> parameters to init. E.g., `init=/sbin/finit -- finit.debug rescue`
|
|
||||||
|
|
||||||
* `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.
|
||||||
@@ -30,7 +31,8 @@ The `bool` setting is one of `on, off, true false, 1, 0`.
|
|||||||
Very useful for selecting different boot modes, e.g. manufacturing test,
|
Very useful for selecting different boot modes, e.g. manufacturing test,
|
||||||
firmware upgrade, or rescue mode.
|
firmware upgrade, or rescue mode.
|
||||||
|
|
||||||
> Note: `<boot/...>` conditions cannot be cleared with `initctl`!
|
> [!NOTE]
|
||||||
|
> `<boot/...>` conditions cannot be cleared with `initctl`!
|
||||||
|
|
||||||
* `finit.config=/path/to/alternative/finit.conf`: override the
|
* `finit.config=/path/to/alternative/finit.conf`: override the
|
||||||
compile-time bootstrap config file, default:
|
compile-time bootstrap config file, default:
|
||||||
|
|||||||
+19
-11
@@ -47,9 +47,10 @@ both the `pid/setupd` *and* `pid/zebra` conditions are satisfied. A
|
|||||||
`pid/` condition is satisfied by the corresponding service's PID file
|
`pid/` condition is satisfied by the corresponding service's PID file
|
||||||
being created, i.e., the service's default readiness notification.
|
being created, i.e., the service's default readiness notification.
|
||||||
|
|
||||||
**NOTE:** Conditions also stop services when a condition is no longer
|
> [!IMPORTANT]
|
||||||
asserted. I.e., if the Zebra process above stops or restarts, netd
|
> Conditions also stop services when a condition is no longer asserted.
|
||||||
will also stop or restart.
|
> I.e., if the `zebra` process above stops or restarts, `netd` will also
|
||||||
|
> stop or restart.
|
||||||
|
|
||||||
Another example is `dropbear`, it does not support `SIGHUP`, but we can
|
Another example is `dropbear`, it does not support `SIGHUP`, but we can
|
||||||
also see optional sourcing of arguments from an environment file:
|
also see optional sourcing of arguments from an environment file:
|
||||||
@@ -106,11 +107,16 @@ on this, see [Internals](#internals).) Thus, after a reconfiguration it
|
|||||||
is up to the "owner" of the condition to convey the new (or possibly
|
is up to the "owner" of the condition to convey the new (or possibly
|
||||||
unchanged) state of it.
|
unchanged) state of it.
|
||||||
|
|
||||||
> **Note:** For `pid/` conditions it is expected that services "touch"
|
|
||||||
> or recreate their PID file on `SIGHUP`.
|
|
||||||
|
|
||||||
Static (one-shot) conditions, like `usr/`, never enter the `flux` state.
|
Static (one-shot) conditions, like `usr/`, never enter the `flux` state.
|
||||||
|
|
||||||
|
> [!IMPORTANT]
|
||||||
|
> For `pid/` conditions it is expected that the service reassert, i.e.,
|
||||||
|
> "touch" or recreate, their PID file on `SIGHUP`. This can be done by
|
||||||
|
> calling `utimensat()` on the PID file. Provided, of course, that the
|
||||||
|
> service supports reloading on `SIGHUP`, otherwise it will be restarted
|
||||||
|
> by Finit when they instead exit on the signal. For such services, use
|
||||||
|
> `<!>` to tell Finit the service does not support `SIGHUP`.
|
||||||
|
|
||||||
|
|
||||||
Built-in Conditions
|
Built-in Conditions
|
||||||
-------------------
|
-------------------
|
||||||
@@ -171,9 +177,10 @@ Built-in conditions:
|
|||||||
- `boot/arg`
|
- `boot/arg`
|
||||||
- `dev/node` and `dev/dir/node`
|
- `dev/node` and `dev/dir/node`
|
||||||
|
|
||||||
**Note:** `up` means administratively up, the interface flag `IFF_UP`.
|
> [!NOTE]
|
||||||
`running` is the `IFF_RUNNING` flag, meaning operatively up. The
|
> Here, `up` means administratively up, the interface flag `IFF_UP`.
|
||||||
difference is that `running` tells if the NIC has link.
|
> `running` is the `IFF_RUNNING` flag, meaning operatively up. The
|
||||||
|
> difference is that `running` tells if the NIC has link.
|
||||||
|
|
||||||
|
|
||||||
Composition
|
Composition
|
||||||
@@ -205,8 +212,9 @@ the service stanza for the daemon. It is far from optimal since any
|
|||||||
synchronization of depending services may fail due to the daemon not
|
synchronization of depending services may fail due to the daemon not
|
||||||
having reinitialized/created their IPC sockets, or similar.
|
having reinitialized/created their IPC sockets, or similar.
|
||||||
|
|
||||||
> **Note:** in versions of Finit prior to v4, the PID conditions were
|
> [!NOTE]
|
||||||
> called 'svc' conditions, and they were far more complex.
|
> In versions of Finit prior to v4, the PID conditions were called 'svc'
|
||||||
|
> conditions, and they were far more complex.
|
||||||
|
|
||||||
|
|
||||||
Debugging
|
Debugging
|
||||||
|
|||||||
+130
-92
@@ -18,8 +18,8 @@ Finit Configuration
|
|||||||
* [Alternate rcS.d/](#alternate-rcs-d-)
|
* [Alternate rcS.d/](#alternate-rcs-d-)
|
||||||
* [Resource Limits](#resource-limits)
|
* [Resource Limits](#resource-limits)
|
||||||
* [Runlevels](#runlevels)
|
* [Runlevels](#runlevels)
|
||||||
* [One-shot Commands (sequence)](#one-shot-commands--sequence-)
|
* [One-shot Commands (sequence)](#one-shot-commands-sequence)
|
||||||
* [One-shot Commands (parallel)](#one-shot-commands--parallel-)
|
* [One-shot Commands (parallel)](#one-shot-commands-parallel)
|
||||||
* [SysV Init Scripts](#sysv-init-scripts)
|
* [SysV Init Scripts](#sysv-init-scripts)
|
||||||
* [Services](#services)
|
* [Services](#services)
|
||||||
* [Run-parts Scripts](#run-parts-scripts)
|
* [Run-parts Scripts](#run-parts-scripts)
|
||||||
@@ -46,8 +46,9 @@ Plugins start at [hook points](plugins.md#hooks) and can run various set
|
|||||||
up, or install event handlers that later provide runtime services, e.g.,
|
up, or install event handlers that later provide runtime services, e.g.,
|
||||||
PID file monitoring, or [conditions](conditions.md).
|
PID file monitoring, or [conditions](conditions.md).
|
||||||
|
|
||||||
> **Tip:** see [SysV Init Compatibility](#sysv-init-compatibility) for
|
> [!TIP]
|
||||||
> help to quickly get going with an existing SysV or BusyBox init setup.
|
> See [SysV Init Compatibility](#sysv-init-compatibility) for help to
|
||||||
|
> quickly get going with an existing SysV or BusyBox init setup.
|
||||||
|
|
||||||
|
|
||||||
### Configuration Files
|
### Configuration Files
|
||||||
@@ -127,8 +128,9 @@ properties of the `run` statement. For an example on the relation of
|
|||||||
`service` and `run` statements, and dependency handling between them,
|
`service` and `run` statements, and dependency handling between them,
|
||||||
see [Conditional Loading](#conditional-loading), below.
|
see [Conditional Loading](#conditional-loading), below.
|
||||||
|
|
||||||
> **Note:** the `finit.conf` and `finit.d/` names are only defaults.
|
> [!NOTE]
|
||||||
> They can be changed at compile-time with two `configure` options:
|
> The names `finit.conf` and `finit.d/` are only defaults. They can be
|
||||||
|
> changed at compile-time with two `configure` options:
|
||||||
> `--with-config=/etc/foo.conf` and `--with-rcsd=/var/foo.d`.
|
> `--with-config=/etc/foo.conf` and `--with-rcsd=/var/foo.d`.
|
||||||
>
|
>
|
||||||
> They can also be overridden from the [kernel command line](cmdline.md)
|
> They can also be overridden from the [kernel command line](cmdline.md)
|
||||||
@@ -187,8 +189,9 @@ 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
|
> [!TIP]
|
||||||
> look at the [`bootmisc.so` plugin](plugins.md).
|
> 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
|
||||||
@@ -198,6 +201,18 @@ order, and `swapoff` is called.
|
|||||||
|
|
||||||
### Runlevels
|
### Runlevels
|
||||||
|
|
||||||
|
Finit supports runlevels, but unlike other init systems runlevels are
|
||||||
|
declared per service/run/task/sysv command. When booting up a system
|
||||||
|
Finit pass through three phases:
|
||||||
|
|
||||||
|
1. Setting up the console, parsing any command line options, and other
|
||||||
|
housekeeping tasks like mounting all filesystems, and calling `fsck`
|
||||||
|
2. Starting all run/task/services in runlevel S, then waiting for all
|
||||||
|
services to have started, and all run/tasks to have completed
|
||||||
|
3. Go to runlevel 2, or whatever the user has set in the configuration
|
||||||
|
|
||||||
|
Available runlevels:
|
||||||
|
|
||||||
- ` S`: bootStrap
|
- ` S`: bootStrap
|
||||||
- ` 1`: Single user mode
|
- ` 1`: Single user mode
|
||||||
- `2-5`: traditional multi-user mode
|
- `2-5`: traditional multi-user mode
|
||||||
@@ -205,37 +220,40 @@ order, and `swapoff` is called.
|
|||||||
- `7-9`: multi-user mode (extra)
|
- `7-9`: multi-user mode (extra)
|
||||||
- ` 0`: shutdown
|
- ` 0`: shutdown
|
||||||
|
|
||||||
Runlevels are declared per service/run/task/sysv command. Starting in
|
Runlevel S (bootStrap), is for tasks supposed to run once at boot, and
|
||||||
runlevel S (bootStrap), usually only for tasks supposed to run once at
|
services like `syslogd`, which need to start early and run throughout
|
||||||
boot, and services like `syslogd`, which you need to start and run
|
the lifetime of your system.
|
||||||
throughout the whole time your system is up.
|
|
||||||
|
|
||||||
Before `S` is started, however, Finit performs a lot of housekeeping
|
Example:
|
||||||
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
|
When bootstrap has completed, Finit moves to runlevel 2. This can be
|
||||||
`/etc/finit.conf` using the `runlevel N` directive, or by a script
|
changed in `/etc/finit.conf` using the `runlevel N` directive, or by a
|
||||||
running in runlevel S that calls, e.g., `initctl runlevel 9`. The
|
script running in runlevel S that calls, e.g., `initctl runlevel 9`.
|
||||||
latter is useful if startup scripts detect problems outside of Finit's
|
The latter is useful if startup scripts detect problems outside of
|
||||||
control, e.g., critical services/devices missing or hardware problems.
|
Finit's control, e.g., critical services/devices missing or hardware
|
||||||
|
problems.
|
||||||
|
|
||||||
Before starting the services in runlevel 2, Finit first stops everything
|
Each runlevel must be allowed to "complete". Meaning, all services in
|
||||||
that is not allowed to run in 2, and then brings up networking.
|
runlevel S must have started and all run/tasks have been started and
|
||||||
Networking is expected to be available in all runlevels except: S, 1
|
collected (exited). Finit waits 120 seconds for all run/tasks in S to
|
||||||
(single user level), 6, and 0. Networking is enabled either by the
|
complete before proceeding to 2.
|
||||||
`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
|
Finit first stops everything that is not allowed to run in 2, and then
|
||||||
> were constrained to runlevel S only are dropped from bookkeeping. So
|
brings up networking. Networking is expected to be available in all
|
||||||
> when reaching the prompt, `initctl` will not show these run/tasks.
|
runlevels except: S, 1 (single user level), 6, and 0. Networking is
|
||||||
> This is a safety mechanism to prevent bootstrap-only tasks from
|
enabled either by the `network script` directive, or if you have an
|
||||||
> accidentally being run again. E.g., `console-setup.sh` above.
|
`/etc/network/interfaces` file, Finit calls `ifup -a` -- at the very
|
||||||
|
least the loopback interface is brought up.
|
||||||
|
|
||||||
|
> [!NOTE]
|
||||||
|
> When moving from runlevel S to 2, all run/task/services that were
|
||||||
|
> constrained to runlevel S only are dropped from bookkeeping. So when
|
||||||
|
> reaching the prompt, `initctl` will not show these run/tasks. This is
|
||||||
|
> a safety mechanism to prevent bootstrap-only tasks from accidentally
|
||||||
|
> being run again. E.g., `console-setup.sh` above.
|
||||||
|
|
||||||
|
|
||||||
### Managing Services
|
### Managing Services
|
||||||
@@ -322,7 +340,8 @@ the `ps` command we can see that the process is started with:
|
|||||||
|
|
||||||
foo -n --extra-arg=bar -s -x
|
foo -n --extra-arg=bar -s -x
|
||||||
|
|
||||||
> **Note:** the leading `-` determines if Finit should treat a missing
|
> [!NOTE]
|
||||||
|
> The leading `-` in `env:` determines if Finit should treat a missing
|
||||||
> environment file as blocking the start of the service or not. When
|
> environment file as blocking the start of the service or not. When
|
||||||
> `-` is used, a missing environment file does *not* block the start.
|
> `-` is used, a missing environment file does *not* block the start.
|
||||||
|
|
||||||
@@ -384,12 +403,13 @@ To synchronize two services the following condition can be used:
|
|||||||
|
|
||||||
For details on the syntax and options, see below.
|
For details on the syntax and options, see below.
|
||||||
|
|
||||||
> **Note:** on `initctl reload` conditions are normally set in "flux",
|
> [!NOTE]
|
||||||
> while figuring out which to stop, start or restart. Services that
|
> On `initctl reload` conditions are set in "flux", while figuring out
|
||||||
> need to be restarted have their `ready` condition removed prior to
|
> which to stop, start or restart. Services that need to be restarted
|
||||||
> Finit sending them SIGHUP (if they support that), or stop-starting
|
> have their `ready` condition removed prior to Finit sending them
|
||||||
> them. A daemon is expected to reassert its readiness, e.g. systemd
|
> SIGHUP (if they support that), or stop-starting them. A daemon is
|
||||||
> style daemons to write `READY=1\n`.
|
> expected to reassert its readiness, e.g. systemd style daemons to
|
||||||
|
> write `READY=1\n`.
|
||||||
>
|
>
|
||||||
> However, the s6 notify mode does not support this because in s6 you
|
> However, the s6 notify mode does not support this because in s6 you
|
||||||
> are expected to close your notify descriptor after having written
|
> are expected to close your notify descriptor after having written
|
||||||
@@ -429,9 +449,10 @@ example employs a wrapper script in `/etc/start.d`.
|
|||||||
# Execute the program
|
# Execute the program
|
||||||
exec /usr/bin/program $OPTIONS
|
exec /usr/bin/program $OPTIONS
|
||||||
|
|
||||||
> **Note:** the example sets `<!>` to denote that it doesn't support
|
> [!NOTE]
|
||||||
> `SIGHUP`. That way Finit will stop/start the service
|
> The example sets `<!>` to denote that it doesn't support `SIGHUP`.
|
||||||
> instead of sending SIGHUP at restart/reload events.
|
> That way Finit will stop/start the service instead of sending SIGHUP
|
||||||
|
> at restart/reload events.
|
||||||
|
|
||||||
|
|
||||||
Templating
|
Templating
|
||||||
@@ -514,6 +535,7 @@ A daemon using `SCHED_RR` currently need to run outside the default cgroups.
|
|||||||
|
|
||||||
service [...] <...> cgroup.root /path/to/daemon arg -- Real-Time process
|
service [...] <...> cgroup.root /path/to/daemon arg -- Real-Time process
|
||||||
|
|
||||||
|
> [!NOTE]
|
||||||
> Linux cgroups and details surrounding values are not explained in the
|
> Linux cgroups and details surrounding values are not explained in the
|
||||||
> Finit documentation. The Linux admin-guide cover this well:
|
> Finit documentation. The Linux admin-guide cover this well:
|
||||||
> <https://www.kernel.org/doc/html/latest/admin-guide/cgroup-v2.html>
|
> <https://www.kernel.org/doc/html/latest/admin-guide/cgroup-v2.html>
|
||||||
@@ -539,12 +561,9 @@ service name:sysklogd [S123456789] \
|
|||||||
```
|
```
|
||||||
|
|
||||||
The .conf files `/etc/finit.conf` and `/etc/finit.d/*` support the
|
The .conf files `/etc/finit.conf` and `/etc/finit.d/*` support the
|
||||||
following directives:
|
following directives. Some directives have restrictions, e.g., only
|
||||||
|
available at bootstrap, runlevel `S`, see [Limitations](#limitations)
|
||||||
|
below for details.
|
||||||
> **Note:** not all directives are available in `/etc/finit.d/*.conf`
|
|
||||||
> and some directives are only available at bootstrap, runlevel `S`,
|
|
||||||
> see [Limitations](#limitations) below for details.
|
|
||||||
|
|
||||||
|
|
||||||
### Hostname
|
### Hostname
|
||||||
@@ -556,7 +575,8 @@ 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
|
||||||
@@ -574,7 +594,8 @@ 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
|
||||||
@@ -587,7 +608,8 @@ 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/
|
||||||
@@ -608,8 +630,9 @@ another set of .conf files, e.g.:
|
|||||||
|
|
||||||
rcsd /etc/factory.d
|
rcsd /etc/factory.d
|
||||||
|
|
||||||
> **Note:** this directive is only available from the top-level
|
> [!NOTE]
|
||||||
> bootstrap .conf file.
|
> This directive is only available from the top-level bootstrap .conf
|
||||||
|
> file, usually `/etc/finit.conf`.
|
||||||
|
|
||||||
### Resource Limits
|
### Resource Limits
|
||||||
|
|
||||||
@@ -642,16 +665,18 @@ 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
|
||||||
is the runlevel number 0-9, where 6 is reserved for reboot and 0 for
|
the runlevel number 0-9, where 6 is reserved for reboot and 0 for halt.
|
||||||
halt.
|
Completed in this context means all services have been started and all
|
||||||
|
run/tasks have been started and collected.
|
||||||
|
|
||||||
It is recommended to keep runlevel 1 as single-user mode, because
|
It is recommended to keep runlevel 1 as single-user mode, because
|
||||||
Finit disables networking in this mode.
|
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)
|
||||||
@@ -665,10 +690,11 @@ optional arguments and description. `run` commands are guaranteed to be
|
|||||||
completed before running the next command. Useful when serialization is
|
completed before running the next command. Useful when serialization is
|
||||||
required.
|
required.
|
||||||
|
|
||||||
> **Warning:** try to avoid the `run` command. It blocks much of the
|
> [!WARNING]
|
||||||
> functionality in Finit, like (re)starting other (perhaps crashing)
|
> Try to avoid the `run` command. It blocks much of the functionality
|
||||||
> services while a `run` task is executing. Use other synchronization
|
> in Finit, like (re)starting other (perhaps crashing) services while a
|
||||||
> mechanisms instead, like conditions.
|
> `run` task is executing. Use other synchronization mechanisms
|
||||||
|
> instead, like conditions.
|
||||||
|
|
||||||
Incomplete list of unsupported `initctl` commands in `run` tasks:
|
Incomplete list of unsupported `initctl` commands in `run` tasks:
|
||||||
|
|
||||||
@@ -708,7 +734,7 @@ non-trivial constructs are better placed in a separate shell script.
|
|||||||
|
|
||||||
Similar to `task` is the `sysv` stanza, which can be used to call SysV
|
Similar to `task` is the `sysv` stanza, which can be used to call SysV
|
||||||
style scripts. The primary intention for this command is to be able to
|
style scripts. The primary intention for this command is to be able to
|
||||||
re-use much of existing setup and init scripts in Linux distributions.
|
reuse much of existing setup and init scripts in Linux distributions.
|
||||||
|
|
||||||
When entering an allowed runlevel, Finit calls `init-script start`, when
|
When entering an allowed runlevel, Finit calls `init-script start`, when
|
||||||
entering a disallowed runlevel, Finit calls `init-script stop`, and if
|
entering a disallowed runlevel, Finit calls `init-script stop`, and if
|
||||||
@@ -723,7 +749,8 @@ file, but rather watch that file for the resulting forked-off PID. This
|
|||||||
syntax also works for forking daemons that do not have a command line
|
syntax also works for forking daemons that do not have a command line
|
||||||
option to run it in the foreground, more on this below in `service`.
|
option to run it in the foreground, more on this below in `service`.
|
||||||
|
|
||||||
> **Tip:** see also [SysV Init Compatibility](#sysv-init-compatibility).
|
> [!TIP]
|
||||||
|
> See also [SysV Init Compatibility](#sysv-init-compatibility).
|
||||||
|
|
||||||
|
|
||||||
### Services
|
### Services
|
||||||
@@ -731,13 +758,13 @@ option to run it in the foreground, more on this below in `service`.
|
|||||||
**Syntax:** `service [LVLS] <COND> /path/to/daemon ARGS -- Optional description`
|
**Syntax:** `service [LVLS] <COND> /path/to/daemon ARGS -- Optional description`
|
||||||
|
|
||||||
Service, or daemon, to be monitored and automatically restarted if it
|
Service, or daemon, to be monitored and automatically restarted if it
|
||||||
exits prematurely. Finit tries to restart services that die, by
|
exits prematurely. Finit tries to restart services that die, by default
|
||||||
default 10 times before giving up and marking them as *crashed*.
|
10 times before giving up and marking them as *crashed*. After which
|
||||||
After which they have to be manually restarted with `initctl restart
|
they have to be manually restarted with `initctl restart NAME`. The
|
||||||
NAME`. The limits controling this are configurable, see the options
|
limits controlling this are configurable, see the options below.
|
||||||
below.
|
|
||||||
|
|
||||||
> **Tip:** to allow endless restarts, see below option `respawn`
|
> [!TIP]
|
||||||
|
> To allow endless restarts, see below option `respawn`
|
||||||
|
|
||||||
For daemons that support it, we recommend appending `--foreground`,
|
For daemons that support it, we recommend appending `--foreground`,
|
||||||
`--no-background`, `-n`, `-F`, or similar command line argument to
|
`--no-background`, `-n`, `-F`, or similar command line argument to
|
||||||
@@ -899,32 +926,39 @@ e.g., `halt:SIGPWR`. To change the delay between the stop signal and
|
|||||||
KILL, use the option `kill:<1-60>`, e.g., `kill:10` to wait 10 seconds
|
KILL, use the option `kill:<1-60>`, e.g., `kill:10` to wait 10 seconds
|
||||||
before sending `SIGKILL`.
|
before sending `SIGKILL`.
|
||||||
|
|
||||||
Services, including the `sysv` variant, support pre/post/ready scripts:
|
Services, including the `sysv` variant, support pre/post/ready and
|
||||||
|
cleanup scripts:
|
||||||
|
|
||||||
* `pre:[0-3600,]script`
|
* `pre:[0-3600,]script` -- called before the sysv/service is stated
|
||||||
* `post:[0-3600,]script`
|
* `post:[0-3600,]script` -- called after the sysv/service has stopped
|
||||||
* `ready:[0-3600,]script`
|
* `ready:[0-3600,]script` -- called when the sysv/service is ready
|
||||||
|
* `cleanup:[0-3600,]script` -- called when run/task/sysv/service is removed
|
||||||
|
|
||||||
The optional number (0-3600) is the timeout before Finit kills the
|
The optional number (0-3600) is the timeout before Finit kills the
|
||||||
script, it defaults to the kill delay value and can be disabled by
|
script, it defaults to the kill delay value and can be disabled by
|
||||||
setting it to zero. These scripts run as the same `@USER:GROUP` as the
|
setting it to zero. These scripts run as the same `@USER:GROUP` as the
|
||||||
service itself, with any `env:file` sourced. The scripts must use an
|
service itself, with any `env:file` sourced. The scripts are executed
|
||||||
absolute path, but are executed from the `$HOME` of the given user. The
|
from the `$HOME` of the given user. The scripts are not called with any
|
||||||
scripts are not called with any argument, but get a set of environment
|
argument, but get a set of environment variables:
|
||||||
variables:
|
|
||||||
|
|
||||||
* `SERVICE_IDENT=foo:1`
|
* `SERVICE_IDENT=foo:1`
|
||||||
* `SERVICE_NAME=foo`
|
* `SERVICE_NAME=foo`
|
||||||
* `SERVICE_ID=1`
|
* `SERVICE_ID=1`
|
||||||
|
|
||||||
The `post:script` is called with an additional set of environment
|
The `post:script` is called with an additional set of environment
|
||||||
variables:
|
variables. Yes, the text is correct, the naming was an accident:
|
||||||
|
|
||||||
- `EXIT_CODE=[exited,signal]`: set to one of `exited` or `signal`
|
- `EXIT_CODE=[exited,signal,crashed]`: normal exit, signaled, or
|
||||||
|
crashed
|
||||||
- `EXIT_STATUS=[num,SIGNAME]`: set to one of exit status code from
|
- `EXIT_STATUS=[num,SIGNAME]`: set to one of exit status code from
|
||||||
the program, if it exited normally, or the signal name (`HUP`,
|
the program, if it exited normally, or the signal name (`HUP`,
|
||||||
`TERM`, etc.) if it exited due to signal
|
`TERM`, etc.) if it exited due to signal
|
||||||
|
|
||||||
|
When a run/task/sys/service is removed (disable + reload) it is first
|
||||||
|
stopped and then removed from the runlevel. The `post:script` always
|
||||||
|
runs when the process has stopped, and the `cleanup:script` runs when
|
||||||
|
the the stanza has been removed from the runlevel.
|
||||||
|
|
||||||
> [!IMPORTANT]
|
> [!IMPORTANT]
|
||||||
> These script actions are intended for setup, cleanup, and readiness
|
> These script actions are intended for setup, cleanup, and readiness
|
||||||
> notification. It is up to the user to ensure the scripts terminate.
|
> notification. It is up to the user to ensure the scripts terminate.
|
||||||
@@ -1027,8 +1061,9 @@ before continuing. None of them can issue commands to start, stop, or
|
|||||||
restart other services. Also, ensure all your services and programs
|
restart other services. Also, ensure all your services and programs
|
||||||
either terminate or start in the background or you will block Finit.
|
either terminate or start in the background or you will block Finit.
|
||||||
|
|
||||||
> **Note:** `runparts` scrips are only read and executed in runlevel S.
|
> [!NOTE]
|
||||||
> See [hook scripts](plugins.md#hooks) for other ways to run scripts at
|
> `runparts` scripts are only read and executed in runlevel S. See
|
||||||
|
> [hook scripts](plugins.md#hooks) for other ways to run scripts at
|
||||||
> certain points during the complete lifetime of the system.
|
> certain points during the complete lifetime of the system.
|
||||||
|
|
||||||
**Recommendations:**
|
**Recommendations:**
|
||||||
@@ -1301,8 +1336,9 @@ This rescue mode can be disabled at configure time using:
|
|||||||
|
|
||||||
The rescue mode comes in two flavors; *traditional* and *fallback*.
|
The rescue mode comes in two flavors; *traditional* and *fallback*.
|
||||||
|
|
||||||
> **Note:** in this mode `initctl` will not work. Use the `-f` flag to
|
> [!NOTE]
|
||||||
> force `reboot`, `shutdown`, or `poweroff`.
|
> In this mode `initctl` will not work. Use the `-f` flag to force
|
||||||
|
> `reboot`, `shutdown`, or `poweroff`.
|
||||||
|
|
||||||
|
|
||||||
### Traditional
|
### Traditional
|
||||||
@@ -1314,11 +1350,12 @@ program is used instead. If a successful login is made, or if the user
|
|||||||
exits (Ctrl-D), the rescue mode is ended and the system boots up
|
exits (Ctrl-D), the rescue mode is ended and the system boots up
|
||||||
normally.
|
normally.
|
||||||
|
|
||||||
> **Note:** the bundled sulogin in Finit can at configure time be given
|
> [!WARNING]
|
||||||
> another user than the default (root). If the sulogin user does not
|
> The bundled sulogin in Finit can at configure time be given another
|
||||||
> have a password, or __the account is locked__, the user is presented
|
> user than the default (root). If the sulogin user does not have a
|
||||||
> with a password-less `"Press enter to enter maintenance mode."`,
|
> password, or __the account is locked__, the user is presented with a
|
||||||
> prompt which opens up a root shell.
|
> prompt: `"Press enter to enter maintenance mode."`, which will open
|
||||||
|
> up a root shell *without prompting for password*!
|
||||||
|
|
||||||
|
|
||||||
### Fallback
|
### Fallback
|
||||||
@@ -1366,10 +1403,11 @@ These can now also be set in any `.conf` file in `/etc/finit.d`.
|
|||||||
There is, however, nothing preventing you from having all configuration
|
There is, however, nothing preventing you from having all configuration
|
||||||
settings in `/etc/finit.conf`.
|
settings in `/etc/finit.conf`.
|
||||||
|
|
||||||
> **Note:** The `/etc/finit.d` directory was previously the default
|
> [!IMPORTANT]
|
||||||
> Finit [runparts](#run-parts-scripts) directory. Finit >=v4.0
|
> The default `rcsd`, i.e., `/etc/finit.d`, was previously the Finit
|
||||||
> no longer has a default `runparts` directory, make sure to
|
> [runparts](#run-parts-scripts) directory. Finit >=v4.0 no longer has
|
||||||
> update your setup, or the finit configuration, accordingly.
|
> a default `runparts` directory, make sure to update your setup, or the
|
||||||
|
> finit configuration, accordingly.
|
||||||
|
|
||||||
|
|
||||||
Watchdog
|
Watchdog
|
||||||
|
|||||||
+3
-2
@@ -34,8 +34,9 @@ build time:
|
|||||||
./configure --with-rcsd=/etc/init.d --with-config=/etc/init.d/init.conf
|
./configure --with-rcsd=/etc/init.d --with-config=/etc/init.d/init.conf
|
||||||
```
|
```
|
||||||
|
|
||||||
> **Note:** remember `--prefix` et al as well, the default is likely
|
> [!IMPORTANT]
|
||||||
> *not* what you want. See the [build docs][1] for details.
|
> Remember `--prefix` et al as well, the default is likely *not* what
|
||||||
|
> you want. See the [build docs][1] for details.
|
||||||
|
|
||||||
The resulting directory structure is depicted below. Please notice how
|
The resulting directory structure is depicted below. Please notice how
|
||||||
`/etc/finit.conf` now resides in the same sub-directory as a non-symlink
|
`/etc/finit.conf` now resides in the same sub-directory as a non-symlink
|
||||||
|
|||||||
+21
-16
@@ -35,9 +35,10 @@ For your convenience a set of *optional* plugins are available:
|
|||||||
files distributed with Finit. It is read first but can be overridden
|
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`.
|
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`
|
> [!NOTE]
|
||||||
> RAM disks and `/dev` is usually a `devtmpfs`. This must be defined
|
> On an embedded system both `/var` and `/run` can be `tmpfs` RAM
|
||||||
> in the `/etc/fstab` file and in the Linux kernel config.
|
> 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._
|
||||||
@@ -63,8 +64,9 @@ For your convenience a set of *optional* plugins are available:
|
|||||||
|
|
||||||
Enabled by default.
|
Enabled by default.
|
||||||
|
|
||||||
> See the [Services](config.md#services) section in the configuration
|
> [!TIP]
|
||||||
> guide for an example how to run `mdevd`, alternative to plain mdev.
|
> See the [Services](config.md#services) section in the configuration
|
||||||
|
> guide for an example how to run `mdevd`, alternative to plain mdev.
|
||||||
|
|
||||||
* *rtc.so*: Restore and save system clock from/to RTC on boot/halt.
|
* *rtc.so*: Restore and save system clock from/to RTC on boot/halt.
|
||||||
Enabled by default.
|
Enabled by default.
|
||||||
@@ -89,16 +91,17 @@ For your convenience a set of *optional* plugins are available:
|
|||||||
|
|
||||||
set index 1234
|
set index 1234
|
||||||
|
|
||||||
**Note:** unlike the traditional .conf `module` directive, which load
|
Since these tasks run in the background, they return `[ OK ]` at boot,
|
||||||
any listed module immediately, this plugin creates a background `task`
|
unless the modprobe tool does not exist. Check syslog for warnings
|
||||||
which load the module(s) in the background. The program is modprobe,
|
and the actual status of the operation using `initctl`.
|
||||||
`/sbin/modprobe`, which you can override per .conf file:
|
|
||||||
|
|
||||||
set modprobe /path/to/maybe-a-modprobe-wrapper
|
> [!IMPORTANT]
|
||||||
|
> Unlike the traditional .conf `module` directive, which load any listed
|
||||||
Since these tasks run in the background, they usually return `[ OK ]`
|
> module immediately, this plugin creates a background `task` which load
|
||||||
at boot, unless the modprobe tool does not exist. Check syslog for
|
> the module(s) in the background. The program is modprobe,
|
||||||
warnings and the actual status of the operation using `initctl`.
|
> `/sbin/modprobe`, which you can override per .conf file:
|
||||||
|
>
|
||||||
|
> set modprobe /path/to/maybe-a-modprobe-wrapper
|
||||||
|
|
||||||
* *netlink.so*: Listens to Linux kernel Netlink events for gateway and
|
* *netlink.so*: Listens to Linux kernel Netlink events for gateway and
|
||||||
interfaces. These events are then sent to the Finit service monitor
|
interfaces. These events are then sent to the Finit service monitor
|
||||||
@@ -158,8 +161,10 @@ hook points:
|
|||||||
EOF
|
EOF
|
||||||
$ chmod +x /libexec/finit/hook/sys/down/foo.sh
|
$ chmod +x /libexec/finit/hook/sys/down/foo.sh
|
||||||
|
|
||||||
> **Note:** to use hook scripts, even for pre-bootstrap and pre-shutdown
|
> [!IMPORTANT]
|
||||||
> tasks, you must build with `configure --enable-hook-scripts-plugin`.
|
> To use hook scripts, even for pre-bootstrap and pre-shutdown tasks,
|
||||||
|
> you must build with `configure --enable-hook-scripts-plugin`.
|
||||||
|
|
||||||
|
|
||||||
### Bootstrap Hooks
|
### Bootstrap Hooks
|
||||||
|
|
||||||
|
|||||||
+3
-2
@@ -22,8 +22,9 @@ Finit can *not* start and monitor a daemon that:
|
|||||||
| ✔ | No | No | Yes, optionally |
|
| ✔ | No | No | Yes, optionally |
|
||||||
| ✘ | Yes | No | No |
|
| ✘ | Yes | No | No |
|
||||||
|
|
||||||
> **Note:** PID files is one mechanism used to assert conditions to
|
> [!NOTE]
|
||||||
> synchronize the start and stop of other, dependent, services.
|
> PID files is one mechanism used to assert conditions to synchronize
|
||||||
|
> the start and stop of other, dependent, services.
|
||||||
|
|
||||||
### Forks to Background w/ PID File
|
### Forks to Background w/ PID File
|
||||||
|
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 230 KiB After Width: | Height: | Size: 320 KiB |
+2
-2
File diff suppressed because one or more lines are too long
|
Before Width: | Height: | Size: 164 KiB After Width: | Height: | Size: 814 KiB |
+38
-24
@@ -175,12 +175,12 @@ task [s] echo "foo" | cat >/tmp/bar
|
|||||||
.Ed
|
.Ed
|
||||||
.It Cm sysv Oo LVLS Oc Ao COND Ac Ar /path/to/script ARGS Op -- Optional description
|
.It Cm sysv Oo LVLS Oc Ao COND Ac Ar /path/to/script ARGS Op -- Optional description
|
||||||
Similar to
|
Similar to
|
||||||
.Cm task
|
.Cm service
|
||||||
is the
|
is the
|
||||||
.Cm sysv
|
.Cm sysv
|
||||||
stanza, which can be used to call SysV style start/stop scripts. The
|
stanza, which can be used to call SysV style start/stop scripts. The
|
||||||
primary intention for this command is to be able to re-use much of
|
primary intention for this command is to be able to re-use traditional
|
||||||
existing setup and init scripts in Linux distributions.
|
SysV init scripts in Linux distributions.
|
||||||
.Pp
|
.Pp
|
||||||
When entering an allowed runlevel, Finit calls
|
When entering an allowed runlevel, Finit calls
|
||||||
.Cm init-script start ,
|
.Cm init-script start ,
|
||||||
@@ -434,30 +434,42 @@ e.g.,
|
|||||||
.Cm kill:10
|
.Cm kill:10
|
||||||
to wait 10 seconds before sending SIGKILL.
|
to wait 10 seconds before sending SIGKILL.
|
||||||
.Pp
|
.Pp
|
||||||
Services support the
|
Services, including the
|
||||||
.Cm pre:script
|
.Cm sysv
|
||||||
and
|
variant, support pre/post/ready and cleanup scripts:
|
||||||
.Cm post:script
|
.Bl -tag -width 1n
|
||||||
command actions as well. These run as the same
|
.It Cm pre:[0-3600,]script
|
||||||
|
called before the sysv/service is stated
|
||||||
|
.It Cm post:[0-3600,]script
|
||||||
|
called after the sysv/service has stopped
|
||||||
|
.It Cm ready:[0-3600,]script
|
||||||
|
called when the sysv/service is ready
|
||||||
|
.It Cm cleanup:[0-3600,]script
|
||||||
|
called when run/task/sysv/service is removed
|
||||||
|
.El
|
||||||
|
.Pp
|
||||||
|
The optional number (0-3600) is the timeout before Finit kills the
|
||||||
|
script, it defaults to the kill delay value and can be disabled by
|
||||||
|
setting it to zero. These scripts run as the same
|
||||||
.Cm @USER:GROUP
|
.Cm @USER:GROUP
|
||||||
as the service itself, with any
|
as the service itself, with any
|
||||||
.Cm env:file
|
.Cm env:file
|
||||||
sourced. The scripts must use an absolute path, but are executed from
|
sourced. The scripts must use an absolute path, but are executed from
|
||||||
the
|
the
|
||||||
.Cm $HOME
|
.Cm $HOME
|
||||||
of the given user. The scripts are not called with any argument
|
of the given user. The scripts are not called with any argument, but
|
||||||
(currently), but both get the
|
both get a set of environment variables:
|
||||||
.Cm SERVICE_IDENT=foo
|
.Pp
|
||||||
environment variable set. Here
|
.Bl -tag -width 1n -compact
|
||||||
.Cm foo
|
.It Cm SERVICE_IDENT=foo:1
|
||||||
denotes the identity of the service, which if there are multiple
|
.It Cm SERVICE_NAME=foo
|
||||||
services named
|
.It Cm SERVICE_ID=1
|
||||||
.Cm foo ,
|
.El
|
||||||
may be
|
.Pp
|
||||||
.Cm foo:1 ,
|
The
|
||||||
or any unique identifier specified in the .conf file. The
|
|
||||||
.Cm post:script
|
.Cm post:script
|
||||||
is called with an additional set of environment variables:
|
is called with an additional set of environment variables, and yes the
|
||||||
|
naming looks like it should be swapped:
|
||||||
.Bl -tag -offset indent -width 1n
|
.Bl -tag -offset indent -width 1n
|
||||||
.It Cm EXIT_CODE=[exited,signal,crashed]
|
.It Cm EXIT_CODE=[exited,signal,crashed]
|
||||||
set to one of
|
set to one of
|
||||||
@@ -471,10 +483,12 @@ set to one of exit status code from the program, if it exited normally,
|
|||||||
or the signal name (HUP, TERM, etc.) if it exited due to signal
|
or the signal name (HUP, TERM, etc.) if it exited due to signal
|
||||||
.El
|
.El
|
||||||
.Pp
|
.Pp
|
||||||
The scripts have a default execution time of 3 seconds before they are
|
When a run/task/sys/service is removed (disable + reload) it is first
|
||||||
SIGKILLed, this can be adjusted using the
|
stopped and then removed from the runlevel. The
|
||||||
.Cm kill:SEC
|
.Cm post:script
|
||||||
modifier syntax.
|
always runs when the process has stopped, and the
|
||||||
|
.Cm cleanup:script
|
||||||
|
runs when the the stanza has been removed from the runlevel.
|
||||||
.It Cm runparts Aq DIR
|
.It Cm runparts Aq DIR
|
||||||
Call
|
Call
|
||||||
.Xr run-parts 8
|
.Xr run-parts 8
|
||||||
|
|||||||
@@ -41,7 +41,7 @@
|
|||||||
*
|
*
|
||||||
* Please note, the :ID is there for your benefit, it ensures that tasks
|
* Please note, the :ID is there for your benefit, it ensures that tasks
|
||||||
* in Finit are unique. If you have two tasks with the same name and ID
|
* in Finit are unique. If you have two tasks with the same name and ID
|
||||||
* (or no ID), the last one read replaces any preceeding one!
|
* (or no ID), the last one read replaces any preceding one!
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|||||||
@@ -80,6 +80,23 @@ static void pidfile_update_conds(char *dir, char *name, uint32_t mask)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
switch (svc->state) {
|
||||||
|
case SVC_TEARDOWN_STATE:
|
||||||
|
case SVC_CLEANUP_STATE:
|
||||||
|
case SVC_SETUP_STATE:
|
||||||
|
/*
|
||||||
|
* E.g., a setup script for a container may run in lieu
|
||||||
|
* of crun, trying to fetch a container image from the
|
||||||
|
* network. This script may want to advertise its PID
|
||||||
|
* to the system for clean and swift reboots.
|
||||||
|
*/
|
||||||
|
dbg("%s[%d]: ignoring any PID file changes in CLEANUP/TEARDOWN/SETUP",
|
||||||
|
svc_ident(svc, NULL, 0), svc->pid);
|
||||||
|
return;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
/* Service condistion to set/clear */
|
/* Service condistion to set/clear */
|
||||||
mkcond(svc, cond, sizeof(cond));
|
mkcond(svc, cond, sizeof(cond));
|
||||||
|
|
||||||
|
|||||||
+5
-1
@@ -32,6 +32,10 @@
|
|||||||
#include "helpers.h"
|
#include "helpers.h"
|
||||||
#include "plugin.h"
|
#include "plugin.h"
|
||||||
|
|
||||||
|
#ifndef SYSCTL_PATH
|
||||||
|
#define SYSCTL_PATH "/sbin/sysctl"
|
||||||
|
#endif
|
||||||
|
|
||||||
static void setup(void *arg)
|
static void setup(void *arg)
|
||||||
{
|
{
|
||||||
glob_t gl;
|
glob_t gl;
|
||||||
@@ -54,7 +58,7 @@ static void setup(void *arg)
|
|||||||
for (i = 0; i < gl.gl_pathc; i++) {
|
for (i = 0; i < gl.gl_pathc; i++) {
|
||||||
char cmd[160];
|
char cmd[160];
|
||||||
|
|
||||||
snprintf(cmd, sizeof(cmd), "/sbin/sysctl -e -p %s >/dev/null", gl.gl_pathv[i]);
|
snprintf(cmd, sizeof(cmd), "%s -e -p %s >/dev/null", SYSCTL_PATH, gl.gl_pathv[i]);
|
||||||
run(cmd, "sysctl");
|
run(cmd, "sysctl");
|
||||||
}
|
}
|
||||||
globfree(&gl);
|
globfree(&gl);
|
||||||
|
|||||||
@@ -338,6 +338,7 @@ PLUGIN_INIT(plugin_init)
|
|||||||
|
|
||||||
PLUGIN_EXIT(plugin_exit)
|
PLUGIN_EXIT(plugin_exit)
|
||||||
{
|
{
|
||||||
|
uev_timer_stop(&rtc_timer);
|
||||||
plugin_unregister(&plugin);
|
plugin_unregister(&plugin);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+24
-6
@@ -26,6 +26,7 @@
|
|||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <sys/time.h> /* gettimeofday() */
|
#include <sys/time.h> /* gettimeofday() */
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
#include <sys/resource.h> /* getrusage() */
|
||||||
#ifdef _LIBITE_LITE
|
#ifdef _LIBITE_LITE
|
||||||
# include <libite/lite.h>
|
# include <libite/lite.h>
|
||||||
#else
|
#else
|
||||||
@@ -43,13 +44,27 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef RANDOMSEED
|
#ifdef RANDOMSEED
|
||||||
|
/*
|
||||||
|
* This is the fallback seed function, please make sure you have drivers
|
||||||
|
* enabling /dev/hwrng instead.
|
||||||
|
*/
|
||||||
static void fallback(FILE *fp)
|
static void fallback(FILE *fp)
|
||||||
{
|
{
|
||||||
|
unsigned long seed;
|
||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
|
struct rusage ru;
|
||||||
int iter = 128;
|
int iter = 128;
|
||||||
|
|
||||||
gettimeofday(&tv, NULL);
|
gettimeofday(&tv, NULL);
|
||||||
srandom(tv.tv_sec % 3600);
|
getrusage(RUSAGE_SELF, &ru);
|
||||||
|
|
||||||
|
/* Mix multiple sources of "randomness" */
|
||||||
|
seed = tv.tv_sec ^ (tv.tv_usec << 16);
|
||||||
|
seed ^= ru.ru_utime.tv_sec ^ (ru.ru_utime.tv_usec << 16);
|
||||||
|
seed ^= ru.ru_stime.tv_sec ^ (ru.ru_stime.tv_usec << 16);
|
||||||
|
seed ^= getpid() << 8;
|
||||||
|
|
||||||
|
srandom(seed);
|
||||||
while (iter--) {
|
while (iter--) {
|
||||||
uint32_t i, prng = random();
|
uint32_t i, prng = random();
|
||||||
|
|
||||||
@@ -63,6 +78,7 @@ static void setup(void *arg)
|
|||||||
{
|
{
|
||||||
#ifdef RANDOMSEED
|
#ifdef RANDOMSEED
|
||||||
struct rand_pool_info *rpi;
|
struct rand_pool_info *rpi;
|
||||||
|
unsigned char *rpi_buf;
|
||||||
ssize_t len = 0;
|
ssize_t len = 0;
|
||||||
struct stat st;
|
struct stat st;
|
||||||
int rc = -1;
|
int rc = -1;
|
||||||
@@ -88,13 +104,14 @@ static void setup(void *arg)
|
|||||||
hw = fopen(hwrng, "r");
|
hw = fopen(hwrng, "r");
|
||||||
if (hw) {
|
if (hw) {
|
||||||
char buf[512];
|
char buf[512];
|
||||||
size_t len;
|
size_t num;
|
||||||
|
|
||||||
len = fread(buf, sizeof(buf[0]), sizeof(buf), hw);
|
num = fread(buf, sizeof(buf[0]), sizeof(buf), hw);
|
||||||
if (len == 0)
|
if (num == 0)
|
||||||
fallback(fp);
|
fallback(fp);
|
||||||
else
|
else
|
||||||
len = fwrite(buf, sizeof(buf[0]), len, fp);
|
fwrite(buf, sizeof(buf[0]), num, fp);
|
||||||
|
|
||||||
fclose(hw);
|
fclose(hw);
|
||||||
} else {
|
} else {
|
||||||
fallback(fp);
|
fallback(fp);
|
||||||
@@ -122,10 +139,11 @@ static void setup(void *arg)
|
|||||||
goto fallback;
|
goto fallback;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rpi_buf = (unsigned char *)rpi->buf;
|
||||||
do {
|
do {
|
||||||
ssize_t num;
|
ssize_t num;
|
||||||
|
|
||||||
num = read(fd, &rpi->buf[len], RANDOM_BYTES - len);
|
num = read(fd, &rpi_buf[len], RANDOM_BYTES - len);
|
||||||
if (num <= 0) {
|
if (num <= 0) {
|
||||||
if (num == -1 && errno == EINTR)
|
if (num == -1 && errno == EINTR)
|
||||||
continue;
|
continue;
|
||||||
|
|||||||
@@ -332,6 +332,11 @@ static void api_cb(uev_t *w, void *arg, int events)
|
|||||||
int sd, lvl;
|
int sd, lvl;
|
||||||
svc_t *svc;
|
svc_t *svc;
|
||||||
|
|
||||||
|
if (UEV_ERROR == events) {
|
||||||
|
dbg("%s(): api socket %d invalid.", __func__, w->fd);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
sd = accept(w->fd, NULL, NULL);
|
sd = accept(w->fd, NULL, NULL);
|
||||||
if (sd < 0) {
|
if (sd < 0) {
|
||||||
err(1, "Failed serving API request");
|
err(1, "Failed serving API request");
|
||||||
@@ -557,7 +562,7 @@ static void api_cb(uev_t *w, void *arg, int events)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (uev_io_init(ctx, &svc->notify_watcher, service_notify_cb, svc, sd, UEV_READ)) {
|
if (uev_io_init(ctx, &svc->notify_watcher, service_notify_cb, svc, sd, UEV_READ)) {
|
||||||
err(1, "Falied initializing %s readiness notifier", svc_ident(svc, NULL, 0));
|
err(1, "Failed initializing %s readiness notifier", svc_ident(svc, NULL, 0));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return; /* Don't close sd, used for notify */
|
return; /* Don't close sd, used for notify */
|
||||||
@@ -578,8 +583,6 @@ static void api_cb(uev_t *w, void *arg, int events)
|
|||||||
|
|
||||||
leave:
|
leave:
|
||||||
close(sd);
|
close(sd);
|
||||||
if (UEV_ERROR == events)
|
|
||||||
goto error;
|
|
||||||
return;
|
return;
|
||||||
error:
|
error:
|
||||||
api_exit();
|
api_exit();
|
||||||
|
|||||||
+6
-1
@@ -259,6 +259,11 @@ static void cgroup_events_cb(uev_t *w, void *arg, int events)
|
|||||||
ssize_t sz;
|
ssize_t sz;
|
||||||
size_t off;
|
size_t off;
|
||||||
|
|
||||||
|
if (UEV_ERROR == events) {
|
||||||
|
dbg("%s(): inotify socket %d invalid.", __func__, w->fd);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
sz = read(w->fd, ev_buf, sizeof(ev_buf) - 1);
|
sz = read(w->fd, ev_buf, sizeof(ev_buf) - 1);
|
||||||
if (sz <= 0) {
|
if (sz <= 0) {
|
||||||
err(1, "invalid inotify event");
|
err(1, "invalid inotify event");
|
||||||
@@ -471,7 +476,7 @@ void cgroup_init(uev_ctx_t *ctx)
|
|||||||
if (mount("none", FINIT_CGPATH, "cgroup2", opts, NULL)) {
|
if (mount("none", FINIT_CGPATH, "cgroup2", opts, NULL)) {
|
||||||
if (errno == ENOENT)
|
if (errno == ENOENT)
|
||||||
logit(LOG_INFO, "Kernel does not support cgroups v2, disabling.");
|
logit(LOG_INFO, "Kernel does not support cgroups v2, disabling.");
|
||||||
else if (errno == EPERM) /* Probably inside an unpriviliged container */
|
else if (errno == EPERM) /* Probably inside an unprivileged container */
|
||||||
logit(LOG_INFO, "Not allowed to mount cgroups v2, disabling.");
|
logit(LOG_INFO, "Not allowed to mount cgroups v2, disabling.");
|
||||||
else
|
else
|
||||||
err(1, "Failed mounting cgroup v2");
|
err(1, "Failed mounting cgroup v2");
|
||||||
|
|||||||
+1
-1
@@ -113,7 +113,7 @@ static void cond_boot_strap(void)
|
|||||||
*
|
*
|
||||||
* => 'pid/' + 'teamd' + '' = condition <pid/teamd>
|
* => 'pid/' + 'teamd' + '' = condition <pid/teamd>
|
||||||
*
|
*
|
||||||
* When you add a second aggrate you need to tell Finit it's a different
|
* When you add a second aggregate you need to tell Finit it's a different
|
||||||
* instance usugin the :ID syntax:
|
* instance usugin the :ID syntax:
|
||||||
*
|
*
|
||||||
* service :lag2 teamd -f /etc/teamd/lag2.conf -- Aggregate lag2
|
* service :lag2 teamd -f /etc/teamd/lag2.conf -- Aggregate lag2
|
||||||
|
|||||||
+7
-7
@@ -96,16 +96,16 @@ enum cond_state cond_get(const char *name)
|
|||||||
|
|
||||||
enum cond_state cond_get_agg(const char *names)
|
enum cond_state cond_get_agg(const char *names)
|
||||||
{
|
{
|
||||||
static char conds[MAX_COND_LEN];
|
|
||||||
enum cond_state s = COND_ON;
|
enum cond_state s = COND_ON;
|
||||||
char *cond;
|
|
||||||
|
|
||||||
if (!names)
|
if (names) {
|
||||||
return COND_ON;
|
char conds[strlen(names) + 1];
|
||||||
|
const char *cond;
|
||||||
|
|
||||||
strlcpy(conds, names, sizeof(conds));
|
strlcpy(conds, names, sizeof(conds));
|
||||||
for (cond = strtok(conds, ","); s && cond; cond = strtok(NULL, ","))
|
for (cond = strtok(conds, ","); s && cond; cond = strtok(NULL, ","))
|
||||||
s = min(s, cond_get(cond));
|
s = min(s, cond_get(cond));
|
||||||
|
}
|
||||||
|
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|||||||
+14
-8
@@ -1542,6 +1542,11 @@ static int conf_iwatch_read(int fd)
|
|||||||
|
|
||||||
static void conf_cb(uev_t *w, void *arg, int events)
|
static void conf_cb(uev_t *w, void *arg, int events)
|
||||||
{
|
{
|
||||||
|
if (UEV_ERROR == events) {
|
||||||
|
dbg("%s(): iwatch socket %d invalid.", __func__, w->fd);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (conf_iwatch_read(w->fd)) {
|
if (conf_iwatch_read(w->fd)) {
|
||||||
err(1, "invalid inotify event");
|
err(1, "invalid inotify event");
|
||||||
return;
|
return;
|
||||||
@@ -1574,25 +1579,26 @@ int conf_monitor(void)
|
|||||||
* have or not have symlinks in place. We need to monitor for
|
* have or not have symlinks in place. We need to monitor for
|
||||||
* changes to either symlink or target.
|
* changes to either symlink or target.
|
||||||
*/
|
*/
|
||||||
rc += iwatch_add(&iw_conf, finit_rcsd, IN_ONLYDIR);
|
rc |= iwatch_add(&iw_conf, finit_rcsd, IN_ONLYDIR);
|
||||||
snprintf(path, sizeof(path), "%s/available/", finit_rcsd);
|
snprintf(path, sizeof(path), "%s/available/", finit_rcsd);
|
||||||
rc += iwatch_add(&iw_conf, path, IN_ONLYDIR | IN_DONT_FOLLOW);
|
rc |= iwatch_add(&iw_conf, path, IN_ONLYDIR | IN_DONT_FOLLOW);
|
||||||
snprintf(path, sizeof(path), "%s/enabled/", finit_rcsd);
|
snprintf(path, sizeof(path), "%s/enabled/", finit_rcsd);
|
||||||
rc += iwatch_add(&iw_conf, path, IN_ONLYDIR | IN_DONT_FOLLOW);
|
rc |= iwatch_add(&iw_conf, path, IN_ONLYDIR | IN_DONT_FOLLOW);
|
||||||
rc += iwatch_add(&iw_conf, finit_conf, 0);
|
rc |= iwatch_add(&iw_conf, finit_conf, 0);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Systems with /etc/default, /etc/conf.d, or similar, can also
|
* Systems with /etc/default, /etc/conf.d, or similar, can also
|
||||||
* monitor changes in env files sourced by .conf files (above)
|
* monitor changes in env files sourced by .conf files (above)
|
||||||
* define your own with --with-sysconfig=/path/to/envfiles
|
* define your own with --with-sysconfig=/path/to/envfiles
|
||||||
*/
|
*/
|
||||||
rc += iwatch_add(&iw_conf, "/etc/default/", IN_ONLYDIR);
|
rc |= iwatch_add(&iw_conf, "/etc/default/", IN_ONLYDIR);
|
||||||
rc += iwatch_add(&iw_conf, "/etc/conf.d/", IN_ONLYDIR);
|
rc |= iwatch_add(&iw_conf, "/etc/conf.d/", IN_ONLYDIR);
|
||||||
#ifdef FINIT_SYSCONFIG
|
#ifdef FINIT_SYSCONFIG
|
||||||
rc += iwatch_add(&iw_conf, FINIT_SYSCONFIG, IN_ONLYDIR);
|
rc |= iwatch_add(&iw_conf, FINIT_SYSCONFIG, IN_ONLYDIR);
|
||||||
#endif
|
#endif
|
||||||
|
rc |= conf_reload();
|
||||||
|
|
||||||
return rc + conf_reload();
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
+3
-3
@@ -199,7 +199,6 @@ int run(char *cmd, char *log)
|
|||||||
int run_interactive(char *cmd, char *fmt, ...)
|
int run_interactive(char *cmd, char *fmt, ...)
|
||||||
{
|
{
|
||||||
int status, oldout = 1, olderr = 2;
|
int status, oldout = 1, olderr = 2;
|
||||||
char line[LINE_SIZE];
|
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
|
|
||||||
if (!cmd) {
|
if (!cmd) {
|
||||||
@@ -244,6 +243,7 @@ int run_interactive(char *cmd, char *fmt, ...)
|
|||||||
|
|
||||||
/* Dump any results of cmd on stderr after we've printed [ OK ] or [FAIL] */
|
/* Dump any results of cmd on stderr after we've printed [ OK ] or [FAIL] */
|
||||||
if (fp && !debug) {
|
if (fp && !debug) {
|
||||||
|
char line[LINE_SIZE];
|
||||||
size_t len, written;
|
size_t len, written;
|
||||||
|
|
||||||
rewind(fp);
|
rewind(fp);
|
||||||
@@ -281,7 +281,7 @@ int exec_runtask(char *cmd, char *args[])
|
|||||||
return execvp(_PATH_BSHELL, argv);
|
return execvp(_PATH_BSHELL, argv);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void prepare_tty(char *tty, speed_t speed, char *procname, struct rlimit rlimit[])
|
static void prepare_tty(char *tty, speed_t speed, const char *procname, struct rlimit rlimit[])
|
||||||
{
|
{
|
||||||
char name[80];
|
char name[80];
|
||||||
int fd, dummy;
|
int fd, dummy;
|
||||||
@@ -351,7 +351,7 @@ static int activate_console(int noclear, int nowait)
|
|||||||
dprint(STDERR_FILENO, clr, strlen(clr));
|
dprint(STDERR_FILENO, clr, strlen(clr));
|
||||||
dprint(STDERR_FILENO, msg, strlen(msg));
|
dprint(STDERR_FILENO, msg, strlen(msg));
|
||||||
while ((rc = read(STDIN_FILENO, &ch, 1)) > 0 && ch != '\r' && ch != '\n')
|
while ((rc = read(STDIN_FILENO, &ch, 1)) > 0 && ch != '\r' && ch != '\n')
|
||||||
continue;
|
;
|
||||||
|
|
||||||
/* On any error (likely EINTR), we avoid starting getty */
|
/* On any error (likely EINTR), we avoid starting getty */
|
||||||
if (rc == -1)
|
if (rc == -1)
|
||||||
|
|||||||
+2
-2
@@ -66,7 +66,7 @@ int prevlevel = -1;
|
|||||||
int debug = 0; /* debug mode from kernel cmdline */
|
int debug = 0; /* debug mode from kernel cmdline */
|
||||||
int rescue = 0; /* rescue mode from kernel cmdline */
|
int rescue = 0; /* rescue mode from kernel cmdline */
|
||||||
int single = 0; /* single user mode from kernel cmdline */
|
int single = 0; /* single user mode from kernel cmdline */
|
||||||
int bootstrap = 1; /* set while bootrapping (for TTYs) */
|
int bootstrap = 1; /* set while bootstrapping (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;
|
int readiness = SVC_NOTIFY_PID;
|
||||||
@@ -280,7 +280,7 @@ static int fsck(int pass)
|
|||||||
sulogin(1);
|
sulogin(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
rc += fsck_rc;
|
rc |= fsck_rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
endmntent(fp);
|
endmntent(fp);
|
||||||
|
|||||||
+2
-2
@@ -312,9 +312,9 @@ static int exec_login(char *name)
|
|||||||
struct stat st;
|
struct stat st;
|
||||||
|
|
||||||
if (passenv)
|
if (passenv)
|
||||||
execl(_PATH_LOGIN, _PATH_LOGIN, "-p", name, NULL);
|
execl(_PATH_LOGIN, _PATH_LOGIN, "-p", "--", name, NULL);
|
||||||
else
|
else
|
||||||
execl(_PATH_LOGIN, _PATH_LOGIN, name, NULL);
|
execl(_PATH_LOGIN, _PATH_LOGIN, "--", name, NULL);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Failed to exec login, should not happen on normal systems.
|
* Failed to exec login, should not happen on normal systems.
|
||||||
|
|||||||
+1
-1
@@ -87,7 +87,7 @@ void console_init(void)
|
|||||||
/* Enable line wrap, if disabled previously, e.g., qemu */
|
/* Enable line wrap, if disabled previously, e.g., qemu */
|
||||||
dprint(STDOUT_FILENO, "\033[?7h", 5);
|
dprint(STDOUT_FILENO, "\033[?7h", 5);
|
||||||
|
|
||||||
/* Reset atttributes, background and foreground color */
|
/* Reset attributes, background and foreground color */
|
||||||
dprint(STDOUT_FILENO, "\033[49m\033[39m\e[2J", 14);
|
dprint(STDOUT_FILENO, "\033[49m\033[39m\e[2J", 14);
|
||||||
|
|
||||||
log_init();
|
log_init();
|
||||||
|
|||||||
+2
-1
@@ -141,6 +141,7 @@ static inline int ln(const char *target, const char *linkpath)
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int dprint(int fd, const char *s, size_t len)
|
static inline int dprint(int fd, const char *s, size_t len)
|
||||||
{
|
{
|
||||||
size_t loop = 3;
|
size_t loop = 3;
|
||||||
@@ -159,7 +160,7 @@ static inline int dprint(int fd, const char *s, size_t len)
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline char *fgetval(char *line, const char *key, char *sep)
|
static inline char *fgetval(const char *line, const char *key, char *sep)
|
||||||
{
|
{
|
||||||
char *ptr, *str, *copy;
|
char *ptr, *str, *copy;
|
||||||
size_t len;
|
size_t len;
|
||||||
|
|||||||
+1
-1
@@ -872,7 +872,7 @@ static char *svc_environ(svc_t *svc, char *buf, size_t len, int ansi)
|
|||||||
{
|
{
|
||||||
int bold = missing(svc);
|
int bold = missing(svc);
|
||||||
|
|
||||||
if (!ansi || svc_checkenv(svc) || svc->env[0] == '-')
|
if (!ansi || svc_checkenv(svc))
|
||||||
bold = 0;
|
bold = 0;
|
||||||
|
|
||||||
strlcpy(buf, bold ? "\e[1m" : "", len);
|
strlcpy(buf, bold ? "\e[1m" : "", len);
|
||||||
|
|||||||
@@ -139,7 +139,7 @@ void logit(int prio, const char *fmt, ...)
|
|||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf(fp, "<%d>finit[1]:", LOG_DAEMON | prio);
|
fprintf(fp, "<%d>finit[1]: ", LOG_DAEMON | prio);
|
||||||
vfprintf(fp, fmt, ap);
|
vfprintf(fp, fmt, ap);
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
|
|
||||||
|
|||||||
@@ -192,7 +192,7 @@ int pid_file_set(svc_t *svc, char *file, int not)
|
|||||||
* pid:foo.tla --> /run/foo.tla.pid
|
* pid:foo.tla --> /run/foo.tla.pid
|
||||||
* pid:/tmp/foo --> /tmp/foo.pid (Not handled by pidfile plugin!)
|
* pid:/tmp/foo --> /tmp/foo.pid (Not handled by pidfile plugin!)
|
||||||
*
|
*
|
||||||
* An exclamation mark, or logial NOT, in the first character position
|
* An exclamation mark, or logical NOT, in the first character position
|
||||||
* indicates that Finit should *not* manage the PID file, and that the
|
* indicates that Finit should *not* manage the PID file, and that the
|
||||||
* process uses a "non-standard" location. Eg. if service is 'bar'
|
* process uses a "non-standard" location. Eg. if service is 'bar'
|
||||||
* Finit would assume the PID file is /run/bar.pid and the below simply
|
* Finit would assume the PID file is /run/bar.pid and the below simply
|
||||||
|
|||||||
+1
-1
@@ -193,7 +193,7 @@ int run_parts(char *dir, char *cmd, const char *env[], int progress, int sysv)
|
|||||||
#ifndef __FINIT__
|
#ifndef __FINIT__
|
||||||
static int usage(int rc)
|
static int usage(int rc)
|
||||||
{
|
{
|
||||||
warnx("usage: runparts [-dhps?] DIRECTORY");
|
warnx("usage: runparts [-bdhps?] DIRECTORY");
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -23,6 +23,7 @@
|
|||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "finit.h"
|
#include "finit.h"
|
||||||
|
#include "log.h"
|
||||||
#include "schedule.h"
|
#include "schedule.h"
|
||||||
|
|
||||||
#define SC_INIT 0x494E4954 /* "INIT", see ascii(7) */
|
#define SC_INIT 0x494E4954 /* "INIT", see ascii(7) */
|
||||||
@@ -35,6 +36,7 @@ static void cb(uev_t *w, void *arg, int events)
|
|||||||
struct wq *work = (struct wq *)arg;
|
struct wq *work = (struct wq *)arg;
|
||||||
|
|
||||||
if (UEV_ERROR == events) {
|
if (UEV_ERROR == events) {
|
||||||
|
dbg("%s(): spurious problem with schedule work timer, restarting.", __func__);
|
||||||
uev_timer_start(w);
|
uev_timer_start(w);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
+138
-49
@@ -81,7 +81,12 @@ static void service_timeout_cb(uev_t *w, void *arg, int events)
|
|||||||
{
|
{
|
||||||
svc_t *svc = arg;
|
svc_t *svc = arg;
|
||||||
|
|
||||||
/* Ignore any UEV_ERROR, we're a one-shot cb so just run it. */
|
if (UEV_ERROR == events) {
|
||||||
|
dbg("%s(): spurious problem, svc %s.", __func__, svc_ident(svc, NULL, 0));
|
||||||
|
uev_timer_start(w);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (svc->timer_cb)
|
if (svc->timer_cb)
|
||||||
svc->timer_cb(svc);
|
svc->timer_cb(svc);
|
||||||
}
|
}
|
||||||
@@ -488,28 +493,21 @@ static void source_env(svc_t *svc)
|
|||||||
while (*end && !isspace(*end))
|
while (*end && !isspace(*end))
|
||||||
end++;
|
end++;
|
||||||
if (*end != 0) {
|
if (*end != 0) {
|
||||||
warnx("'%s=%s': not a valid identifier", key, val);
|
warnx("'%s=%s': not a valid identifier", key, value);
|
||||||
continue; /* invalid key */
|
continue; /* invalid key */
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (wordexp(value, &we, 0)) {
|
if (wordexp(value, &we, 0)) {
|
||||||
case 0:
|
setenv(key, value, 1);
|
||||||
|
} else {
|
||||||
for (i = 0, *val = 0; i < we.we_wordc; i++) {
|
for (i = 0, *val = 0; i < we.we_wordc; i++) {
|
||||||
if (i > 0)
|
if (i > 0)
|
||||||
strlcat(val, " ", LINE_SIZE);
|
strlcat(val, " ", LINE_SIZE);
|
||||||
strlcat(val, we.we_wordv[i], LINE_SIZE);
|
strlcat(val, we.we_wordv[i], LINE_SIZE);
|
||||||
}
|
}
|
||||||
setenv(key, val, 1);
|
setenv(key, val, 1);
|
||||||
wordfree(&we);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case WRDE_NOSPACE:
|
|
||||||
wordfree(&we);
|
|
||||||
/* fallthrough */
|
|
||||||
default:
|
|
||||||
setenv(key, value, 1);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
wordfree(&we);
|
||||||
}
|
}
|
||||||
|
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
@@ -917,12 +915,12 @@ static void service_kill(svc_t *svc)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
dbg("%s: Sending SIGKILL to process group %d", nm, svc->pid);
|
dbg("%s: Sending SIGKILL to process %d", nm, svc->pid);
|
||||||
logit(LOG_CONSOLE | LOG_NOTICE, "Stopping %s[%d], sending SIGKILL ...", id, svc->pid);
|
logit(LOG_CONSOLE | LOG_NOTICE, "Stopping %s[%d], sending SIGKILL ...", id, svc->pid);
|
||||||
if (runlevel != 1)
|
if (runlevel != 1)
|
||||||
print_desc("Killing ", svc->desc);
|
print_desc("Killing ", svc->desc);
|
||||||
|
|
||||||
kill(-svc->pid, SIGKILL);
|
kill(svc->pid, SIGKILL);
|
||||||
|
|
||||||
/* Let SIGKILLs stand out, show result as [WARN] */
|
/* Let SIGKILLs stand out, show result as [WARN] */
|
||||||
if (runlevel != 1)
|
if (runlevel != 1)
|
||||||
@@ -1524,6 +1522,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 *cleanup_script = NULL;
|
||||||
char ident[MAX_IDENT_LEN];
|
char ident[MAX_IDENT_LEN];
|
||||||
char *ifstmt = NULL;
|
char *ifstmt = NULL;
|
||||||
char *notify = NULL;
|
char *notify = NULL;
|
||||||
@@ -1630,6 +1629,8 @@ int service_register(int type, char *cfg, struct rlimit rlimit[], char *file)
|
|||||||
post_script = arg;
|
post_script = arg;
|
||||||
else if (MATCH_CMD(cmd, "ready:", arg))
|
else if (MATCH_CMD(cmd, "ready:", arg))
|
||||||
ready_script = arg;
|
ready_script = arg;
|
||||||
|
else if (MATCH_CMD(cmd, "cleanup:", arg))
|
||||||
|
cleanup_script = arg;
|
||||||
else if (MATCH_CMD(cmd, "env:", arg))
|
else if (MATCH_CMD(cmd, "env:", arg))
|
||||||
env = arg;
|
env = arg;
|
||||||
/* catch both cgroup: and cgroup. handled in parse_cgroup() */
|
/* catch both cgroup: and cgroup. handled in parse_cgroup() */
|
||||||
@@ -1674,6 +1675,7 @@ int service_register(int type, char *cfg, struct rlimit rlimit[], char *file)
|
|||||||
if (tty_parse_args(&tty, cmd, &args))
|
if (tty_parse_args(&tty, cmd, &args))
|
||||||
return errno;
|
return errno;
|
||||||
|
|
||||||
|
/* NOTE: this may result in dev == NULL! */
|
||||||
if (tty_isatcon(tty.dev))
|
if (tty_isatcon(tty.dev))
|
||||||
dev = tty_atcon();
|
dev = tty_atcon();
|
||||||
else
|
else
|
||||||
@@ -1706,17 +1708,19 @@ int service_register(int type, char *cfg, struct rlimit rlimit[], char *file)
|
|||||||
respawn = 1;
|
respawn = 1;
|
||||||
|
|
||||||
/* Create name:id tuple for identity, e.g., tty:S0 */
|
/* Create name:id tuple for identity, e.g., tty:S0 */
|
||||||
ptr = strrchr(dev, '/');
|
if (dev) {
|
||||||
if (ptr)
|
ptr = strrchr(dev, '/');
|
||||||
ptr++;
|
if (ptr)
|
||||||
else
|
ptr++;
|
||||||
ptr = dev;
|
else
|
||||||
if (!strncmp(ptr, "tty", 3))
|
ptr = dev;
|
||||||
ptr += 3;
|
if (!strncmp(ptr, "tty", 3))
|
||||||
|
ptr += 3;
|
||||||
|
|
||||||
name = "tty";
|
name = "tty";
|
||||||
if (!id || id[0] == 0)
|
if (!id || id[0] == 0)
|
||||||
id = ptr;
|
id = ptr;
|
||||||
|
}
|
||||||
|
|
||||||
svc = svc_find_by_tty(dev);
|
svc = svc_find_by_tty(dev);
|
||||||
} else
|
} else
|
||||||
@@ -1817,6 +1821,11 @@ int service_register(int type, char *cfg, struct rlimit rlimit[], char *file)
|
|||||||
parse_script(svc, "ready", ready_script, &svc->ready_tmo, svc->ready_script, sizeof(svc->ready_script));
|
parse_script(svc, "ready", ready_script, &svc->ready_tmo, svc->ready_script, sizeof(svc->ready_script));
|
||||||
else
|
else
|
||||||
memset(svc->ready_script, 0, sizeof(svc->ready_script));
|
memset(svc->ready_script, 0, sizeof(svc->ready_script));
|
||||||
|
if (cleanup_script)
|
||||||
|
parse_script(svc, "cleanup", cleanup_script, &svc->cleanup_tmo, svc->cleanup_script, sizeof(svc->cleanup_script));
|
||||||
|
else
|
||||||
|
memset(svc->cleanup_script, 0, sizeof(svc->cleanup_script));
|
||||||
|
|
||||||
if (!svc_is_tty(svc)) {
|
if (!svc_is_tty(svc)) {
|
||||||
if (log)
|
if (log)
|
||||||
parse_log(svc, log);
|
parse_log(svc, log);
|
||||||
@@ -1916,8 +1925,8 @@ int service_register(int type, char *cfg, struct rlimit rlimit[], char *file)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This function is called when cleaning up lingering (stopped) services
|
* This function is called at the end of a runlevel change or reload
|
||||||
* after a .conf reload.
|
* command to delete all remnants of removed services.
|
||||||
*
|
*
|
||||||
* We need to ensure we properly stop the service before removing it,
|
* We need to ensure we properly stop the service before removing it,
|
||||||
* including stopping any pending restart or SIGKILL timers before we
|
* including stopping any pending restart or SIGKILL timers before we
|
||||||
@@ -1962,10 +1971,14 @@ void service_monitor(pid_t lost, int status)
|
|||||||
/* If the setup phase fails, drive svc to crashed. */
|
/* If the setup phase fails, drive svc to crashed. */
|
||||||
svc->status = status;
|
svc->status = status;
|
||||||
/* fallthrough */
|
/* fallthrough */
|
||||||
|
case SVC_TEARDOWN_STATE:
|
||||||
case SVC_CLEANUP_STATE:
|
case SVC_CLEANUP_STATE:
|
||||||
dbg("collected script %s(%d), normal exit: %d, signaled: %d, exit code: %d",
|
dbg("collected script %s(%d), normal exit: %d, signaled: %d, exit code: %d",
|
||||||
svc->state == SVC_CLEANUP_STATE ? svc->post_script : svc->pre_script,
|
(svc->state == SVC_TEARDOWN_STATE
|
||||||
lost, ok, sig, rc);
|
? svc->post_script
|
||||||
|
: (svc->state == SVC_CLEANUP_STATE
|
||||||
|
? svc->cleanup_script
|
||||||
|
: svc->pre_script)), lost, ok, sig, rc);
|
||||||
/* Kill all children in the same proess group, e.g. logit */
|
/* Kill all children in the same proess group, e.g. logit */
|
||||||
dbg("Killing lingering children in same process group ...");
|
dbg("Killing lingering children in same process group ...");
|
||||||
kill(-svc->pid, SIGKILL);
|
kill(-svc->pid, SIGKILL);
|
||||||
@@ -1994,7 +2007,7 @@ void service_monitor(pid_t lost, int status)
|
|||||||
kill(-svc->pid, SIGKILL);
|
kill(-svc->pid, SIGKILL);
|
||||||
|
|
||||||
/* Try removing PID file (in case service does not clean up after itself) */
|
/* Try removing PID file (in case service does not clean up after itself) */
|
||||||
if (svc_is_daemon(svc) || svc_is_tty(svc)) {
|
if (svc_is_daemon(svc) || svc_is_sysv(svc) || svc_is_tty(svc)) {
|
||||||
service_cleanup(svc);
|
service_cleanup(svc);
|
||||||
} else if (svc_is_runtask(svc)) {
|
} else if (svc_is_runtask(svc)) {
|
||||||
/* run/task should run at least once per runlevel */
|
/* run/task should run at least once per runlevel */
|
||||||
@@ -2134,13 +2147,16 @@ static void service_pre_script(svc_t *svc)
|
|||||||
|
|
||||||
redirect(svc);
|
redirect(svc);
|
||||||
|
|
||||||
|
/* Warning in service_start() after svc_checkenv() */
|
||||||
env_file = svc_getenv(svc);
|
env_file = svc_getenv(svc);
|
||||||
if (env_file)
|
if (env_file && fexist(env_file))
|
||||||
snprintf(buf, sizeof(buf), ". %s; exec %s", env_file, svc->pre_script);
|
snprintf(buf, sizeof(buf), ". %s; exec %s", env_file, svc->pre_script);
|
||||||
else
|
else
|
||||||
strlcpy(buf, svc->pre_script, sizeof(buf));
|
strlcpy(buf, svc->pre_script, sizeof(buf));
|
||||||
|
|
||||||
set_pre_post_envs(svc, "pre");
|
set_pre_post_envs(svc, "pre");
|
||||||
|
sig_unblock();
|
||||||
|
|
||||||
execvp(_PATH_BSHELL, argv);
|
execvp(_PATH_BSHELL, argv);
|
||||||
_exit(EX_OSERR);
|
_exit(EX_OSERR);
|
||||||
}
|
}
|
||||||
@@ -2171,12 +2187,14 @@ static void service_post_script(svc_t *svc)
|
|||||||
rc = WEXITSTATUS(svc->status);
|
rc = WEXITSTATUS(svc->status);
|
||||||
sig = WTERMSIG(svc->status);
|
sig = WTERMSIG(svc->status);
|
||||||
|
|
||||||
|
/* Warning in service_start() after svc_checkenv() */
|
||||||
env_file = svc_getenv(svc);
|
env_file = svc_getenv(svc);
|
||||||
if (env_file)
|
if (env_file && fexist(env_file))
|
||||||
snprintf(buf, sizeof(buf), ". %s; exec %s", env_file, svc->post_script);
|
snprintf(buf, sizeof(buf), ". %s; exec %s", env_file, svc->post_script);
|
||||||
else
|
else
|
||||||
strlcpy(buf, svc->post_script, sizeof(buf));
|
strlcpy(buf, svc->post_script, sizeof(buf));
|
||||||
set_pre_post_envs(svc, "post");
|
set_pre_post_envs(svc, "post");
|
||||||
|
sig_unblock();
|
||||||
|
|
||||||
if (WIFEXITED(svc->status)) {
|
if (WIFEXITED(svc->status)) {
|
||||||
char val[4];
|
char val[4];
|
||||||
@@ -2201,7 +2219,7 @@ static void service_post_script(svc_t *svc)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Unlike the pre: and post: scripts, the ready: script cannot re-use
|
* Unlike the pre: and post: scripts, the ready: script cannot reuse
|
||||||
* svc->pid, so instead we use an assoc. list for matching any scripts
|
* svc->pid, so instead we use an assoc. list for matching any scripts
|
||||||
* related to the svc, handled by service_script_add() below. When a
|
* related to the svc, handled by service_script_add() below. When a
|
||||||
* ready: script is reaped the service_monitor() checks first for the
|
* ready: script is reaped the service_monitor() checks first for the
|
||||||
@@ -2230,13 +2248,16 @@ void service_ready_script(svc_t *svc)
|
|||||||
};
|
};
|
||||||
char *env_file;
|
char *env_file;
|
||||||
|
|
||||||
|
/* Warning in service_start() after svc_checkenv() */
|
||||||
env_file = svc_getenv(svc);
|
env_file = svc_getenv(svc);
|
||||||
if (env_file)
|
if (env_file && fexist(env_file))
|
||||||
snprintf(buf, sizeof(buf), ". %s; exec %s", env_file, svc->ready_script);
|
snprintf(buf, sizeof(buf), ". %s; exec %s", env_file, svc->ready_script);
|
||||||
else
|
else
|
||||||
strlcpy(buf, svc->ready_script, sizeof(buf));
|
strlcpy(buf, svc->ready_script, sizeof(buf));
|
||||||
|
|
||||||
set_pre_post_envs(svc, "ready");
|
set_pre_post_envs(svc, "ready");
|
||||||
|
sig_unblock();
|
||||||
|
|
||||||
execvp(_PATH_BSHELL, argv);
|
execvp(_PATH_BSHELL, argv);
|
||||||
_exit(EX_OSERR);
|
_exit(EX_OSERR);
|
||||||
}
|
}
|
||||||
@@ -2245,6 +2266,44 @@ void service_ready_script(svc_t *svc)
|
|||||||
service_script_add(svc, pid, svc->ready_tmo);
|
service_script_add(svc, pid, svc->ready_tmo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void service_cleanup_script(svc_t *svc)
|
||||||
|
{
|
||||||
|
svc->pid = service_fork(svc);
|
||||||
|
if (svc->pid < 0) {
|
||||||
|
err(1, "Failed forking off %s cleanup:script %s", svc_ident(svc, NULL, 0), svc->cleanup_script);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (svc->pid == 0) {
|
||||||
|
char buf[CMD_SIZE];
|
||||||
|
char *argv[4] = {
|
||||||
|
"sh",
|
||||||
|
"-ac",
|
||||||
|
buf,
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
char *env_file;
|
||||||
|
|
||||||
|
redirect(svc);
|
||||||
|
|
||||||
|
/* Warning in service_start() after svc_checkenv() */
|
||||||
|
env_file = svc_getenv(svc);
|
||||||
|
if (env_file && fexist(env_file))
|
||||||
|
snprintf(buf, sizeof(buf), ". %s; exec %s", env_file, svc->cleanup_script);
|
||||||
|
else
|
||||||
|
strlcpy(buf, svc->cleanup_script, sizeof(buf));
|
||||||
|
|
||||||
|
set_pre_post_envs(svc, "cleanup");
|
||||||
|
sig_unblock();
|
||||||
|
|
||||||
|
execvp(_PATH_BSHELL, argv);
|
||||||
|
_exit(EX_OSERR);
|
||||||
|
}
|
||||||
|
|
||||||
|
dbg("%s: cleanup:script %s started as PID %d", svc_ident(svc, NULL, 0), svc->cleanup_script, svc->pid);
|
||||||
|
service_timeout_after(svc, svc->cleanup_tmo, service_kill_script);
|
||||||
|
}
|
||||||
|
|
||||||
static void service_retry(svc_t *svc)
|
static void service_retry(svc_t *svc)
|
||||||
{
|
{
|
||||||
char *restart_cnt = (char *)&svc->restart_cnt;
|
char *restart_cnt = (char *)&svc->restart_cnt;
|
||||||
@@ -2349,7 +2408,7 @@ static void svc_set_state(svc_t *svc, svc_state_t new_state)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (svc_is_daemon(svc)) {
|
if (svc_is_daemon(svc) || svc_is_sysv(svc)) {
|
||||||
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));
|
||||||
@@ -2432,10 +2491,12 @@ restart:
|
|||||||
|
|
||||||
switch (svc->state) {
|
switch (svc->state) {
|
||||||
case SVC_HALTED_STATE:
|
case SVC_HALTED_STATE:
|
||||||
if (enabled)
|
if (enabled) {
|
||||||
svc_set_state(svc, SVC_WAITING_STATE);
|
svc_set_state(svc, SVC_WAITING_STATE);
|
||||||
else {
|
} else {
|
||||||
if (svc_is_conflict(svc)) {
|
if (svc_is_removed(svc)) {
|
||||||
|
svc_set_state(svc, SVC_DEAD_STATE);
|
||||||
|
} else if (svc_is_conflict(svc)) {
|
||||||
#if 0
|
#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 ...",
|
||||||
@@ -2447,6 +2508,30 @@ restart:
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case SVC_TEARDOWN_STATE:
|
||||||
|
if (!svc->pid) {
|
||||||
|
dbg("%s: post script done.", svc_ident(svc, NULL, 0));
|
||||||
|
service_timeout_cancel(svc);
|
||||||
|
|
||||||
|
if (svc_is_removed(svc) && svc_has_cleanup(svc)) {
|
||||||
|
svc_set_state(svc, SVC_CLEANUP_STATE);
|
||||||
|
service_cleanup_script(svc);
|
||||||
|
} else
|
||||||
|
svc_set_state(svc, SVC_HALTED_STATE);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SVC_CLEANUP_STATE:
|
||||||
|
if (!svc->pid) {
|
||||||
|
dbg("%s: cleanup script done.", svc_ident(svc, NULL, 0));
|
||||||
|
svc_set_state(svc, SVC_HALTED_STATE);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SVC_DEAD_STATE:
|
||||||
|
/* End of the line ☠ */
|
||||||
|
break;
|
||||||
|
|
||||||
case SVC_DONE_STATE:
|
case SVC_DONE_STATE:
|
||||||
if (svc_is_changed(svc))
|
if (svc_is_changed(svc))
|
||||||
svc_set_state(svc, SVC_HALTED_STATE);
|
svc_set_state(svc, SVC_HALTED_STATE);
|
||||||
@@ -2469,8 +2554,11 @@ restart:
|
|||||||
case SVC_TYPE_SYSV:
|
case SVC_TYPE_SYSV:
|
||||||
case SVC_TYPE_TTY:
|
case SVC_TYPE_TTY:
|
||||||
if (svc_has_post(svc)) {
|
if (svc_has_post(svc)) {
|
||||||
svc_set_state(svc, SVC_CLEANUP_STATE);
|
svc_set_state(svc, SVC_TEARDOWN_STATE);
|
||||||
service_post_script(svc);
|
service_post_script(svc);
|
||||||
|
} else if (svc_is_removed(svc) && svc_has_cleanup(svc)) {
|
||||||
|
svc_set_state(svc, SVC_CLEANUP_STATE);
|
||||||
|
service_cleanup_script(svc);
|
||||||
} else
|
} else
|
||||||
svc_set_state(svc, SVC_HALTED_STATE);
|
svc_set_state(svc, SVC_HALTED_STATE);
|
||||||
break;
|
break;
|
||||||
@@ -2489,12 +2577,12 @@ restart:
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SVC_CLEANUP_STATE:
|
|
||||||
if (!svc->pid)
|
|
||||||
svc_set_state(svc, SVC_HALTED_STATE);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SVC_SETUP_STATE:
|
case SVC_SETUP_STATE:
|
||||||
|
if (!enabled) {
|
||||||
|
service_stop(svc);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (!svc->pid) {
|
if (!svc->pid) {
|
||||||
int rc = WEXITSTATUS(svc->status);
|
int rc = WEXITSTATUS(svc->status);
|
||||||
int ok = WIFEXITED(svc->status);
|
int ok = WIFEXITED(svc->status);
|
||||||
@@ -2596,7 +2684,7 @@ restart:
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (svc_is_runtask(svc)) { /* only run/task, not sysv here */
|
if (svc_is_runtask(svc)) {
|
||||||
svc_set_state(svc, SVC_STOPPING_STATE);
|
svc_set_state(svc, SVC_STOPPING_STATE);
|
||||||
svc->restart_tot++;
|
svc->restart_tot++;
|
||||||
svc->once++;
|
svc->once++;
|
||||||
@@ -2818,13 +2906,13 @@ void service_notify_cb(uev_t *w, void *arg, int events)
|
|||||||
ssize_t len;
|
ssize_t len;
|
||||||
|
|
||||||
if (UEV_ERROR == events) {
|
if (UEV_ERROR == events) {
|
||||||
warn("Spurious problem with %s notify callback, restarting.", svc_ident(svc, NULL, 0));
|
dbg("Spurious problem with %s notify callback, restarting.", svc_ident(svc, NULL, 0));
|
||||||
uev_io_start(w);
|
uev_io_start(w);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
len = read(w->fd, buf, sizeof(buf) - 1);
|
len = read(w->fd, buf, sizeof(buf) - 1);
|
||||||
if (len == -1) {
|
if (len <= 0) {
|
||||||
warn("Failed reading notification from %s", svc_ident(svc, NULL, 0));
|
warn("Failed reading notification from %s", svc_ident(svc, NULL, 0));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -2832,7 +2920,7 @@ void service_notify_cb(uev_t *w, void *arg, int events)
|
|||||||
buf[len] = 0;
|
buf[len] = 0;
|
||||||
|
|
||||||
/* systemd and s6, respectively. The latter then closes the socket */
|
/* systemd and s6, respectively. The latter then closes the socket */
|
||||||
if (!strcmp(buf, "READY=1\n") || !strcmp(buf, "\n")) {
|
if (!strcmp(buf, "READY=1\n") || buf[len - 1] == '\n') {
|
||||||
/*
|
/*
|
||||||
* native (pidfile) services are marked as started by
|
* native (pidfile) services are marked as started by
|
||||||
* the pidfile plugin.
|
* the pidfile plugin.
|
||||||
@@ -2868,7 +2956,7 @@ void service_notify_cb(uev_t *w, void *arg, int events)
|
|||||||
*
|
*
|
||||||
* This does not affect the restart_tot counter, which you can see in
|
* This does not affect the restart_tot counter, which you can see in
|
||||||
* the output from 'initctl status foo', along with this instability
|
* the output from 'initctl status foo', along with this instability
|
||||||
* "index" in parethesis: total (cnt/max)
|
* "index" in parenthesis: total (cnt/max)
|
||||||
*/
|
*/
|
||||||
static void service_interval_cb(uev_t *w, void *arg, int events)
|
static void service_interval_cb(uev_t *w, void *arg, int events)
|
||||||
{
|
{
|
||||||
@@ -2876,6 +2964,7 @@ static void service_interval_cb(uev_t *w, void *arg, int events)
|
|||||||
|
|
||||||
(void)arg;
|
(void)arg;
|
||||||
if (UEV_ERROR == events) {
|
if (UEV_ERROR == events) {
|
||||||
|
dbg("%s(): spurious problem, restarting.", __func__);
|
||||||
uev_timer_start(w);
|
uev_timer_start(w);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -232,6 +232,8 @@ void do_iterate_proc(int (*cb)(int, void *), void *data)
|
|||||||
dbg("Skipping %s ...", file);
|
dbg("Skipping %s ...", file);
|
||||||
else if (file[0] == '@')
|
else if (file[0] == '@')
|
||||||
dbg("Skipping %s ...", &file[1]);
|
dbg("Skipping %s ...", &file[1]);
|
||||||
|
else if (strstr(file, "initctl"))
|
||||||
|
dbg("Skipping %s ...", file);
|
||||||
else
|
else
|
||||||
if (cb(pid, data)) {
|
if (cb(pid, data)) {
|
||||||
dbg("PID %d is still alive (%s)", pid, file);
|
dbg("PID %d is still alive (%s)", pid, file);
|
||||||
|
|||||||
@@ -107,6 +107,9 @@ static char *sm_status(sm_state_t state)
|
|||||||
case SM_BOOTSTRAP_STATE:
|
case SM_BOOTSTRAP_STATE:
|
||||||
return "bootstrap";
|
return "bootstrap";
|
||||||
|
|
||||||
|
case SM_BOOTSTRAP_WAIT_STATE:
|
||||||
|
return "bootstrap/wait";
|
||||||
|
|
||||||
case SM_RUNNING_STATE:
|
case SM_RUNNING_STATE:
|
||||||
return "running";
|
return "running";
|
||||||
|
|
||||||
@@ -116,15 +119,20 @@ static char *sm_status(sm_state_t state)
|
|||||||
case SM_RUNLEVEL_WAIT_STATE:
|
case SM_RUNLEVEL_WAIT_STATE:
|
||||||
return "runlevel/wait";
|
return "runlevel/wait";
|
||||||
|
|
||||||
|
case SM_RUNLEVEL_CLEAN_STATE:
|
||||||
|
return "runlevel/clean";
|
||||||
|
|
||||||
case SM_RELOAD_CHANGE_STATE:
|
case SM_RELOAD_CHANGE_STATE:
|
||||||
return "reload/change";
|
return "reload/change";
|
||||||
|
|
||||||
case SM_RELOAD_WAIT_STATE:
|
case SM_RELOAD_WAIT_STATE:
|
||||||
return "reload/wait";
|
return "reload/wait";
|
||||||
|
|
||||||
default:
|
case SM_RELOAD_CLEAN_STATE:
|
||||||
return "unknown";
|
return "reload/clean";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return "unknown";
|
||||||
}
|
}
|
||||||
|
|
||||||
static char sm_runlevel(int lvl)
|
static char sm_runlevel(int lvl)
|
||||||
@@ -201,7 +209,7 @@ restart:
|
|||||||
switch (sm->state) {
|
switch (sm->state) {
|
||||||
case SM_BOOTSTRAP_STATE:
|
case SM_BOOTSTRAP_STATE:
|
||||||
dbg("Bootstrapping all services in runlevel S from %s", finit_conf);
|
dbg("Bootstrapping all services in runlevel S from %s", finit_conf);
|
||||||
service_step_all(SVC_TYPE_RUNTASK | SVC_TYPE_SERVICE);
|
service_step_all(SVC_TYPE_RUNTASK | SVC_TYPE_SERVICE | SVC_TYPE_SYSV);
|
||||||
|
|
||||||
sm->state = SM_BOOTSTRAP_WAIT_STATE;
|
sm->state = SM_BOOTSTRAP_WAIT_STATE;
|
||||||
break;
|
break;
|
||||||
@@ -235,7 +243,7 @@ restart:
|
|||||||
/* Disable progress output at normal runtime */
|
/* Disable progress output at normal runtime */
|
||||||
enable_progress(0);
|
enable_progress(0);
|
||||||
|
|
||||||
/* System bootrapped, launch TTYs et al */
|
/* System bootstrapped, launch TTYs et al */
|
||||||
bootstrap = 0;
|
bootstrap = 0;
|
||||||
service_step_all(SVC_TYPE_RESPAWN);
|
service_step_all(SVC_TYPE_RESPAWN);
|
||||||
sm->state = SM_RUNNING_STATE;
|
sm->state = SM_RUNNING_STATE;
|
||||||
@@ -319,6 +327,22 @@ restart:
|
|||||||
sm->in_teardown = 0;
|
sm->in_teardown = 0;
|
||||||
service_step_all(SVC_TYPE_ANY);
|
service_step_all(SVC_TYPE_ANY);
|
||||||
|
|
||||||
|
sm->state = SM_RUNLEVEL_CLEAN_STATE;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SM_RUNLEVEL_CLEAN_STATE:
|
||||||
|
/*
|
||||||
|
* Wait for post:script or cleanup:script to be collected,
|
||||||
|
* which moves the svc to HALTED or DEAD state. We will
|
||||||
|
* be called by the service_monitor() on collect.
|
||||||
|
*/
|
||||||
|
svc = svc_clean_completed();
|
||||||
|
if (svc) {
|
||||||
|
dbg("Waiting to collect post/cleanup script for %s, cmd %s(%d) ...",
|
||||||
|
svc_ident(svc, NULL, 0), svc->cmd, svc->pid);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
/* Cleanup stale services */
|
/* Cleanup stale services */
|
||||||
svc_clean_dynamic(service_unregister);
|
svc_clean_dynamic(service_unregister);
|
||||||
|
|
||||||
@@ -372,6 +396,22 @@ restart:
|
|||||||
dbg("Starting services after reconf ...");
|
dbg("Starting services after reconf ...");
|
||||||
service_step_all(SVC_TYPE_ANY);
|
service_step_all(SVC_TYPE_ANY);
|
||||||
|
|
||||||
|
sm->state = SM_RELOAD_CLEAN_STATE;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SM_RELOAD_CLEAN_STATE:
|
||||||
|
/*
|
||||||
|
* Wait for post:script or cleanup:script to be collected,
|
||||||
|
* which moves the svc to HALTED or DEAD state. We will
|
||||||
|
* be called by the service_monitor() on collect.
|
||||||
|
*/
|
||||||
|
svc = svc_clean_completed();
|
||||||
|
if (svc) {
|
||||||
|
dbg("Waiting to collect post/cleanup script for %s, cmd %s(%d) ...",
|
||||||
|
svc_ident(svc, NULL, 0), svc->cmd, svc->pid);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
/* Cleanup stale services */
|
/* Cleanup stale services */
|
||||||
svc_clean_dynamic(service_unregister);
|
svc_clean_dynamic(service_unregister);
|
||||||
|
|
||||||
|
|||||||
@@ -29,9 +29,11 @@ typedef enum {
|
|||||||
SM_BOOTSTRAP_WAIT_STATE, /* Waiting for bootstrap to complete */
|
SM_BOOTSTRAP_WAIT_STATE, /* Waiting for bootstrap to complete */
|
||||||
SM_RUNNING_STATE, /* Normal state, services running */
|
SM_RUNNING_STATE, /* Normal state, services running */
|
||||||
SM_RUNLEVEL_CHANGE_STATE, /* A runlevel change has occurred */
|
SM_RUNLEVEL_CHANGE_STATE, /* A runlevel change has occurred */
|
||||||
SM_RUNLEVEL_WAIT_STATE, /* Waiting for all stopped runlevel processes to be halted */
|
SM_RUNLEVEL_WAIT_STATE, /* Waiting for all stopped processes to halt */
|
||||||
|
SM_RUNLEVEL_CLEAN_STATE, /* Wait for post:scripts and cleanup:scripts */
|
||||||
SM_RELOAD_CHANGE_STATE, /* A reload event has occurred */
|
SM_RELOAD_CHANGE_STATE, /* A reload event has occurred */
|
||||||
SM_RELOAD_WAIT_STATE, /* Waiting for all stopped reload processes to be halted */
|
SM_RELOAD_WAIT_STATE, /* Waiting for all stopped processes to halt */
|
||||||
|
SM_RELOAD_CLEAN_STATE, /* Wait for post:scripts and cleanup:scripts */
|
||||||
} sm_state_t;
|
} sm_state_t;
|
||||||
|
|
||||||
typedef struct sm {
|
typedef struct sm {
|
||||||
|
|||||||
@@ -348,6 +348,43 @@ svc_t *svc_stop_completed(void)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* svc_clean_completed - Have post: and cleanup: scripts finished?
|
||||||
|
*
|
||||||
|
* Called late in runlevel and reload transitions to check if all post: and
|
||||||
|
* cleanup:scripts have completed. A removed service should end up in the
|
||||||
|
* DEAD state, while a service with a post:script ends up in HALTED.
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* %NULL if post: and cleanup: scripts have run, otherwise a pointer to
|
||||||
|
* the first found svc_t waiting for post: or cleanup:script.
|
||||||
|
*/
|
||||||
|
svc_t *svc_clean_completed(void)
|
||||||
|
{
|
||||||
|
svc_t *svc, *iter = NULL;
|
||||||
|
|
||||||
|
for (svc = svc_iterator(&iter, 1); svc; svc = svc_iterator(&iter, 0)) {
|
||||||
|
if (svc_enabled(svc))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (svc_is_runtask(svc) && svc->state == SVC_DONE_STATE)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (svc_is_removed(svc)) {
|
||||||
|
if (svc->state == SVC_DEAD_STATE)
|
||||||
|
continue; /* any cleanup:script done */
|
||||||
|
} else {
|
||||||
|
if (svc->state == SVC_HALTED_STATE)
|
||||||
|
continue; /* any post:script done */
|
||||||
|
}
|
||||||
|
|
||||||
|
return svc;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* svc_find - Find a service object by its full path name
|
* svc_find - Find a service object by its full path name
|
||||||
* @name: Full path name, e.g., /sbin/syslogd
|
* @name: Full path name, e.g., /sbin/syslogd
|
||||||
@@ -580,7 +617,7 @@ void svc_clean_dynamic(void (*cb)(svc_t *))
|
|||||||
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->removed && cb)
|
if (svc_is_removed(svc) && cb)
|
||||||
cb(svc);
|
cb(svc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -52,14 +52,16 @@ typedef enum {
|
|||||||
} svc_type_t;
|
} svc_type_t;
|
||||||
|
|
||||||
#define SVC_TYPE_ANY (-1)
|
#define SVC_TYPE_ANY (-1)
|
||||||
#define SVC_TYPE_RESPAWN (SVC_TYPE_SERVICE | SVC_TYPE_TTY)
|
#define SVC_TYPE_RESPAWN (SVC_TYPE_SERVICE | SVC_TYPE_SYSV | SVC_TYPE_TTY)
|
||||||
#define SVC_TYPE_RUNTASK (SVC_TYPE_RUN | SVC_TYPE_TASK | SVC_TYPE_SYSV)
|
#define SVC_TYPE_RUNTASK (SVC_TYPE_RUN | SVC_TYPE_TASK)
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
SVC_HALTED_STATE = 0, /* Not allowed in runlevel, or not enabled. */
|
SVC_HALTED_STATE = 0, /* Not allowed in runlevel, or not enabled. */
|
||||||
SVC_DONE_STATE, /* Task/Run job has been run */
|
SVC_DONE_STATE, /* Task/Run job has been run */
|
||||||
|
SVC_DEAD_STATE, /* Process is dead and scheduled for removal */
|
||||||
|
SVC_CLEANUP_STATE, /* Running cleanup: script */
|
||||||
|
SVC_TEARDOWN_STATE, /* Running post: script */
|
||||||
SVC_STOPPING_STATE, /* Waiting to collect the child process */
|
SVC_STOPPING_STATE, /* Waiting to collect the child process */
|
||||||
SVC_CLEANUP_STATE, /* Running post: script */
|
|
||||||
SVC_SETUP_STATE, /* Running pre: script */
|
SVC_SETUP_STATE, /* Running pre: script */
|
||||||
SVC_PAUSED_STATE, /* Condition is in flux, process SIGSTOPed */
|
SVC_PAUSED_STATE, /* Condition is in flux, process SIGSTOPed */
|
||||||
SVC_WAITING_STATE, /* Enabled but condition not satisfied */
|
SVC_WAITING_STATE, /* Enabled but condition not satisfied */
|
||||||
@@ -146,7 +148,7 @@ typedef struct svc {
|
|||||||
char cond[MAX_COND_LEN];
|
char cond[MAX_COND_LEN];
|
||||||
|
|
||||||
/* Instance specifics */
|
/* Instance specifics */
|
||||||
int job; /* For intenal use only, canonical ref is NAME:ID */
|
int job; /* For internal use only, canonical ref is NAME:ID */
|
||||||
char name[MAX_ARG_LEN];
|
char name[MAX_ARG_LEN];
|
||||||
char id[MAX_ID_LEN]; /* :ID */
|
char id[MAX_ID_LEN]; /* :ID */
|
||||||
char ifstmt[MAX_IDENT_LEN];
|
char ifstmt[MAX_IDENT_LEN];
|
||||||
@@ -196,13 +198,19 @@ typedef struct svc {
|
|||||||
char conflict[MAX_ARG_LEN];
|
char conflict[MAX_ARG_LEN];
|
||||||
char desc[MAX_STR_LEN];
|
char desc[MAX_STR_LEN];
|
||||||
char env[MAX_CMD_LEN];
|
char env[MAX_CMD_LEN];
|
||||||
|
|
||||||
char pre_script[MAX_CMD_LEN];
|
char pre_script[MAX_CMD_LEN];
|
||||||
int pre_tmo;
|
int pre_tmo;
|
||||||
|
|
||||||
char post_script[MAX_CMD_LEN];
|
char post_script[MAX_CMD_LEN];
|
||||||
int post_tmo;
|
int post_tmo;
|
||||||
|
|
||||||
char ready_script[MAX_CMD_LEN];
|
char ready_script[MAX_CMD_LEN];
|
||||||
int ready_tmo;
|
int ready_tmo;
|
||||||
|
|
||||||
|
char cleanup_script[MAX_CMD_LEN];
|
||||||
|
int cleanup_tmo;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Used to forcefully kill services that won't shutdown on
|
* Used to forcefully kill services that won't shutdown on
|
||||||
* termination and to delay restarts of crashing services.
|
* termination and to delay restarts of crashing services.
|
||||||
@@ -240,6 +248,7 @@ void svc_foreach (int (*cb)(svc_t *));
|
|||||||
void svc_foreach_type (int types, int (*cb)(svc_t *));
|
void svc_foreach_type (int types, int (*cb)(svc_t *));
|
||||||
|
|
||||||
svc_t *svc_stop_completed (void);
|
svc_t *svc_stop_completed (void);
|
||||||
|
svc_t *svc_clean_completed (void);
|
||||||
|
|
||||||
void svc_mark (svc_t *svc);
|
void svc_mark (svc_t *svc);
|
||||||
void svc_mark_dynamic (void);
|
void svc_mark_dynamic (void);
|
||||||
@@ -270,12 +279,14 @@ static inline int svc_has_pidfile (svc_t *svc) { return svc_is_daemon(svc) && s
|
|||||||
static inline int svc_has_pre (svc_t *svc) { return svc->pre_script[0]; }
|
static inline int svc_has_pre (svc_t *svc) { return svc->pre_script[0]; }
|
||||||
static inline int svc_has_post (svc_t *svc) { return svc->post_script[0]; }
|
static inline int svc_has_post (svc_t *svc) { return svc->post_script[0]; }
|
||||||
static inline int svc_has_ready (svc_t *svc) { return svc->ready_script[0];}
|
static inline int svc_has_ready (svc_t *svc) { return svc->ready_script[0];}
|
||||||
|
static inline int svc_has_cleanup (svc_t *svc) { return svc->cleanup_script[0]; }
|
||||||
|
|
||||||
static inline void svc_starting (svc_t *svc) { if (svc) svc->starting = 1; }
|
static inline void svc_starting (svc_t *svc) { if (svc) svc->starting = 1; }
|
||||||
static inline void svc_started (svc_t *svc) { if (svc) svc->starting = 0; }
|
static inline void svc_started (svc_t *svc) { if (svc) svc->starting = 0; }
|
||||||
static inline int svc_is_starting (svc_t *svc) { return svc && 0 != svc->starting; }
|
static inline int svc_is_starting (svc_t *svc) { return svc && 0 != svc->starting; }
|
||||||
static inline int svc_is_running (svc_t *svc) { return svc && svc->state == SVC_RUNNING_STATE; }
|
static inline int svc_is_running (svc_t *svc) { return svc && svc->state == SVC_RUNNING_STATE; }
|
||||||
static inline int svc_is_stopping (svc_t *svc) { return svc && svc->state == SVC_STOPPING_STATE; }
|
static inline int svc_is_stopping (svc_t *svc) { return svc && svc->state == SVC_STOPPING_STATE; }
|
||||||
|
static inline int svc_is_stopped (svc_t *svc) { return svc && svc->block == SVC_BLOCK_USER; }
|
||||||
|
|
||||||
static inline int svc_is_removed (svc_t *svc) { return svc && svc->removed; }
|
static inline int svc_is_removed (svc_t *svc) { return svc && svc->removed; }
|
||||||
static inline int svc_is_changed (svc_t *svc) { return svc && 0 != svc->dirty; }
|
static inline int svc_is_changed (svc_t *svc) { return svc && 0 != svc->dirty; }
|
||||||
@@ -390,12 +401,15 @@ static inline char *svc_status(svc_t *svc)
|
|||||||
return "stopping";
|
return "stopping";
|
||||||
}
|
}
|
||||||
|
|
||||||
case SVC_CLEANUP_STATE:
|
case SVC_TEARDOWN_STATE:
|
||||||
return "cleanup";
|
return "teardown";
|
||||||
|
|
||||||
case SVC_SETUP_STATE:
|
case SVC_SETUP_STATE:
|
||||||
return "setup";
|
return "setup";
|
||||||
|
|
||||||
|
case SVC_CLEANUP_STATE:
|
||||||
|
return "cleanup";
|
||||||
|
|
||||||
case SVC_PAUSED_STATE:
|
case SVC_PAUSED_STATE:
|
||||||
return "paused";
|
return "paused";
|
||||||
|
|
||||||
@@ -408,6 +422,9 @@ static inline char *svc_status(svc_t *svc)
|
|||||||
case SVC_RUNNING_STATE:
|
case SVC_RUNNING_STATE:
|
||||||
return "running";
|
return "running";
|
||||||
|
|
||||||
|
case SVC_DEAD_STATE:
|
||||||
|
return "dead";
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return "UNKNOWN";
|
return "UNKNOWN";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -172,7 +172,7 @@ int tty_parse_args(struct tty *tty, char *cmd, char **args)
|
|||||||
passenv = 1;
|
passenv = 1;
|
||||||
else if (!strcmp(cmd, "rescue"))
|
else if (!strcmp(cmd, "rescue"))
|
||||||
tty->rescue = 1; /* for rescue shells */
|
tty->rescue = 1; /* for rescue shells */
|
||||||
else if (whichp(cmd)) /* in $PATH? */
|
else if (!tty->cmd && whichp(cmd))
|
||||||
tty->cmd = cmd;
|
tty->cmd = cmd;
|
||||||
else
|
else
|
||||||
tty->args[tty->num++] = cmd;
|
tty->args[tty->num++] = cmd;
|
||||||
@@ -229,8 +229,9 @@ int tty_parse_args(struct tty *tty, char *cmd, char **args)
|
|||||||
return errno = EINVAL;
|
return errno = EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
dbg("Registering %s getty on TTY %s at %s baud with term %s", tty->cmd ? "external" : "built-in",
|
dbg("Registering %s getty on TTY %s at %s baud with term %s",
|
||||||
tty->dev, tty->baud ?: "0", tty->term ?: "N/A");
|
tty->cmd ? "external" : "built-in",
|
||||||
|
tty->dev, tty->baud ?: "0", tty->term ?: "N/A");
|
||||||
|
|
||||||
/* Built-in getty now comes as standalone program */
|
/* Built-in getty now comes as standalone program */
|
||||||
if (!tty->cmd) {
|
if (!tty->cmd) {
|
||||||
|
|||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
# Verify handling of dependant services, bug #314
|
# Verify handling of dependent services, bug #314
|
||||||
# Two services: foo and bar, where bar depends on foo:
|
# Two services: foo and bar, where bar depends on foo:
|
||||||
#
|
#
|
||||||
# - bar must not start until foo is ready
|
# - bar must not start until foo is ready
|
||||||
|
|||||||
+1
-1
@@ -71,7 +71,7 @@ test_one()
|
|||||||
assert_status "serv" "running"
|
assert_status "serv" "running"
|
||||||
assert_cond "service/serv/ready"
|
assert_cond "service/serv/ready"
|
||||||
|
|
||||||
# Issue #343; pidfile.so inadvertedly marked systemd services as
|
# Issue #343; pidfile.so inadvertently marked systemd services as
|
||||||
# '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" != "pid" ]; then
|
if [ "$type" != "pid" ]; then
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
#
|
#
|
||||||
# Verifies that a run task can call initctl at bootstrap and runlevel 2,
|
# Verifies that a run task can call initctl at bootstrap and runlevel 2,
|
||||||
# without blocking, performing serveral tasks:
|
# without blocking, performing several tasks:
|
||||||
#
|
#
|
||||||
# 1. Query running services
|
# 1. Query running services
|
||||||
# 2. Stop/Start a running service
|
# 2. Stop/Start a running service
|
||||||
|
|||||||
Reference in New Issue
Block a user