Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4f01856313 | ||
|
|
2aa9e5bad6 | ||
|
|
b897c62a73 | ||
|
|
6c133e85f2 | ||
|
|
d30959e909 | ||
|
|
2badd840fa | ||
|
|
e00476250f | ||
|
|
c3f758de96 | ||
|
|
29761b69ea | ||
|
|
e08d56af71 | ||
|
|
a370ddc3c0 | ||
|
|
8377f0e736 | ||
|
|
f42a1fd356 | ||
|
|
ab82e6f696 | ||
|
|
cd0ddd6bfc | ||
|
|
31b78817dd | ||
|
|
5599aca0a3 | ||
|
|
d77773d8ee | ||
|
|
efadbb0694 | ||
|
|
de4be1557b | ||
|
|
a73e02afac | ||
|
|
a3c5dfd543 | ||
|
|
4c208c18e2 | ||
|
|
0a9ac65609 | ||
|
|
167d75ac4a | ||
|
|
0cd51fb7d3 | ||
|
|
bf2c0542ca | ||
|
|
0bef874cf3 | ||
|
|
eadd01da1f | ||
|
|
80b0750523 | ||
|
|
4525aec118 | ||
|
|
61be1ef880 | ||
|
|
a7428ababa | ||
|
|
b4b7ee1b71 | ||
|
|
ff91d5c836 | ||
|
|
d652211621 | ||
|
|
9f95934df9 | ||
|
|
261d604ea3 | ||
|
|
085fc4c660 |
@@ -8,14 +8,22 @@ on:
|
|||||||
- '**'
|
- '**'
|
||||||
- '!dev'
|
- '!dev'
|
||||||
pull_request:
|
pull_request:
|
||||||
branches:
|
types: [opened, synchronize, reopened, labeled]
|
||||||
- '**'
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: ${{ github.workflow }}-${{ github.head_ref || github.ref }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
# Verify we can build on latest Ubuntu with both gcc and clang
|
# Verify we can build on latest Ubuntu with both gcc and clang
|
||||||
name: ${{ matrix.compiler }}
|
name: ${{ matrix.compiler }}
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
# Skip redundant builds for PRs - prefer PR builds over push builds
|
||||||
|
if: github.event_name != 'push' || github.ref == 'refs/heads/master'
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
compiler: [gcc, clang]
|
compiler: [gcc, clang]
|
||||||
|
|||||||
@@ -6,6 +6,9 @@ on:
|
|||||||
- 'dev'
|
- 'dev'
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
env:
|
env:
|
||||||
PROJECT_NAME: finit
|
PROJECT_NAME: finit
|
||||||
CONTACT_EMAIL: troglobit@gmail.com
|
CONTACT_EMAIL: troglobit@gmail.com
|
||||||
|
|||||||
@@ -0,0 +1,68 @@
|
|||||||
|
name: Dotty the Documenteer
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
paths:
|
||||||
|
- 'doc/**'
|
||||||
|
- 'README.md'
|
||||||
|
- 'mkdocs.yml'
|
||||||
|
- '.github/workflows/docs.yml'
|
||||||
|
pull_request:
|
||||||
|
types: [opened, synchronize, reopened, labeled]
|
||||||
|
paths:
|
||||||
|
- 'doc/**'
|
||||||
|
- 'README.md'
|
||||||
|
- 'mkdocs.yml'
|
||||||
|
- '.github/workflows/docs.yml'
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
pages: write
|
||||||
|
id-token: write
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: "pages"
|
||||||
|
cancel-in-progress: false
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-depth: 0 # Needed for git-revision-date-localized plugin
|
||||||
|
|
||||||
|
- name: Setup Python
|
||||||
|
uses: actions/setup-python@v4
|
||||||
|
with:
|
||||||
|
python-version: '3.x'
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: |
|
||||||
|
pipx install mkdocs
|
||||||
|
pipx inject mkdocs mkdocs-material
|
||||||
|
pipx inject mkdocs pymdown-extensions
|
||||||
|
pipx inject mkdocs mkdocs-callouts
|
||||||
|
|
||||||
|
- name: Build documentation
|
||||||
|
run: mkdocs build
|
||||||
|
|
||||||
|
- name: Upload Pages artifact
|
||||||
|
uses: actions/upload-pages-artifact@v3
|
||||||
|
with:
|
||||||
|
path: site/
|
||||||
|
|
||||||
|
deploy:
|
||||||
|
if: github.ref == 'refs/heads/master' && github.event_name == 'push'
|
||||||
|
needs: build
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
environment:
|
||||||
|
name: github-pages
|
||||||
|
url: ${{ steps.deployment.outputs.page_url }}
|
||||||
|
steps:
|
||||||
|
- name: Deploy to GitHub Pages
|
||||||
|
id: deployment
|
||||||
|
uses: actions/deploy-pages@v4
|
||||||
@@ -5,6 +5,9 @@ on:
|
|||||||
tags:
|
tags:
|
||||||
- '[0-9]+.[0-9]+*'
|
- '[0-9]+.[0-9]+*'
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
release:
|
release:
|
||||||
name: Build and upload release tarball
|
name: Build and upload release tarball
|
||||||
@@ -50,7 +53,7 @@ jobs:
|
|||||||
mv ../*.tar.* artifacts/
|
mv ../*.tar.* artifacts/
|
||||||
- name: Extract ChangeLog entry ...
|
- name: Extract ChangeLog entry ...
|
||||||
run: |
|
run: |
|
||||||
awk '/-----*/{if (x == 1) exit; x=1;next}x' ChangeLog.md \
|
awk '/-----*/{if (x == 1) exit; x=1;next}x' doc/ChangeLog.md \
|
||||||
|head -n -1 > release.md
|
|head -n -1 > release.md
|
||||||
cat release.md
|
cat release.md
|
||||||
- uses: ncipollo/release-action@v1
|
- uses: ncipollo/release-action@v1
|
||||||
|
|||||||
@@ -7,6 +7,9 @@ on:
|
|||||||
- cron: '0 0 * * 0'
|
- cron: '0 0 * * 0'
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
schedule:
|
schedule:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|||||||
@@ -1,7 +1,15 @@
|
|||||||
# GNU Global .conf file, see /etc/gtags/gtags.conf for details.
|
# GNU Global .conf file, see /etc/gtags/gtags.conf for details.
|
||||||
|
# This configuration is optimized for the Finit project structure.
|
||||||
|
|
||||||
default:\
|
default:\
|
||||||
:tc=default@/etc/gtags/gtags.conf:\
|
:tc=default@/etc/gtags/gtags.conf:\
|
||||||
:tc=common:
|
:tc=common:
|
||||||
|
|
||||||
common:\
|
common:\
|
||||||
:skip=tags,TAGS,ID,y.tab.c,y.tab.h,gtags.files,cscope.files,cscope.out,cscope.po.out,cscope.in.out,,{arch}/,autom4te.cache/,*.orig,*.rej,*.bak,*~,#*#,*.swp,*.tmp,*_flymake.*,*_flymake,*.o,*.a,*.so,*.lo,*.zip,*.gz,*.bz2,*.xz,*.lzh,*.Z,*.tgz,*.min.js,*min.css,sysroot/:
|
:skip=tags,TAGS,ID,y.tab.c,y.tab.h,gtags.files,cscope.files,cscope.out,cscope.po.out,cscope.in.out,\
|
||||||
|
{arch}/,autom4te.cache/,\
|
||||||
|
*.orig,*.rej,*.bak,*~,#*#,*.swp,*.tmp,*_flymake.*,*_flymake,\
|
||||||
|
*.o,*.a,*.so,*.lo,*.la,\
|
||||||
|
*.zip,*.gz,*.bz2,*.xz,*.lzh,*.Z,*.tgz,\
|
||||||
|
*.log,*.trs,test-suite.log,stamp-*,\
|
||||||
|
sysroot/:
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
Copyright (c) 2008-2010 Claudio Matsuoka <cmatsuoka@gmail.com>
|
Copyright (c) 2008-2010 Claudio Matsuoka <cmatsuoka@gmail.com>
|
||||||
Copyright (c) 2008-2024 Joachim Wiberg <troglobit@gmail.com>
|
Copyright (c) 2008-2025 Joachim Wiberg <troglobit@gmail.com>
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
ACLOCAL_AMFLAGS = -I m4
|
ACLOCAL_AMFLAGS = -I m4
|
||||||
SUBDIRS = man plugins src system tmpfiles.d
|
SUBDIRS = man plugins src system tmpfiles.d
|
||||||
doc_DATA = README.md LICENSE contrib/finit.conf
|
dist_doc_DATA = README.md LICENSE contrib/finit.conf
|
||||||
EXTRA_DIST = README.md LICENSE ChangeLog.md contrib/finit.conf
|
|
||||||
|
|
||||||
if CONTRIB
|
if CONTRIB
|
||||||
SUBDIRS += contrib
|
SUBDIRS += contrib
|
||||||
@@ -21,10 +20,6 @@ else
|
|||||||
SUBDIRS += test
|
SUBDIRS += test
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if BASH
|
|
||||||
bashdir = $(BASH_DIR)
|
|
||||||
dist_bash_DATA = initctl
|
|
||||||
endif
|
|
||||||
# Compat hook
|
# Compat hook
|
||||||
install-dev:
|
install-dev:
|
||||||
@make -C src install-pkgincludeHEADERS
|
@make -C src install-pkgincludeHEADERS
|
||||||
|
|||||||
@@ -1,723 +1,46 @@
|
|||||||
[![License Badge][]][License] [![GitHub Status][]][GitHub] [![Coverity Status][]][Coverity Scan]
|
[![License Badge][]][License] [![GitHub Status][]][GitHub] [![Coverity Status][]][Coverity Scan]
|
||||||
<img align="right" src="img/finit3.png" alt="Finit: Fast Init">
|
<img align="right" src="doc/img/finit3.png" alt="Finit: Fast Init">
|
||||||
|
|
||||||
* [Introduction](#introduction)
|
Finit is an alternative to [SysV init](https://en.wikipedia.org/wiki/Init)
|
||||||
* [Features](#features)
|
and [systemd](https://www.freedesktop.org/wiki/Software/systemd/), focused
|
||||||
* [Runlevels](#runlevels)
|
on small and embedded Linux systems, although fully usable on server and
|
||||||
* [Syntax](doc/config.md#syntax)
|
[desktop systems][finix].
|
||||||
* [Runparts & /etc/rc.local](#runparts--etcrclocal)
|
|
||||||
* [Hooks, Callbacks & Plugins](doc/plugins.md#hooks-callbacks--plugins)
|
|
||||||
* [Rebooting & Halting](#rebooting--halting)
|
|
||||||
* [Commands & Status](#commands--status)
|
|
||||||
* [Tips & Tricks with the kernel cmdline](doc/cmdline.md)
|
|
||||||
* [Building](doc/build.md#building)
|
|
||||||
* [Running](doc/build.md#running)
|
|
||||||
* [Recovery](doc/build.md#recovery)
|
|
||||||
* [Debugging](doc/build.md#debugging)
|
|
||||||
* [Requirements](#requirements)
|
|
||||||
* [Origin & References](#origin--references)
|
|
||||||
|
|
||||||
|
> Reverse engineered from the [EeePC fastinit][]
|
||||||
|
> "gaps filled with frog DNA …"
|
||||||
|
> — [Claudio Matsuoka][]
|
||||||
|
|
||||||
Introduction
|
For detailed information, explore our extensive documentation
|
||||||
------------
|
:books: **<https://troglobit.github.io/finit/>**
|
||||||
|
|
||||||
Fast init for Linux systems. Reverse engineered from the [EeePC
|
<div align="center">
|
||||||
fastinit][] by [Claudio Matsuoka][] — "gaps filled with frog DNA …"
|
<img src="doc/img/alpine-screenshot2.png" alt="Alpine screenshot"><br/>
|
||||||
|
</div>
|
||||||
|
|
||||||

|
For working examples, see the :rocket: [contrib/](contrib/) section or these
|
||||||
*Figure 1: Screenshot of Finit booting [Alpine Linux (HowTo)](https://github.com/troglobit/finit/tree/master/contrib/alpine).*
|
tutorials:
|
||||||
|
|
||||||
Features include:
|
* :hammer_and_wrench: [Buildroot embedded Linux](https://troglobit.com/post/2022-12-26-buildroot-demo-of-fastinit-finit/),
|
||||||
|
* :package: [Debian GNU/Linux](contrib/debian/),
|
||||||
* Runlevels, defined per service
|
* :mountain: [Alpine Linux](contrib/alpine/), and
|
||||||
* One-shot tasks, services (daemons), or [SysV init][4] start/stop scripts
|
* :milky_way: [Void Linux](contrib/void/)
|
||||||
* Runparts and `/etc/rc.local` support
|
|
||||||
* Process supervision similar to [systemd][]
|
|
||||||
* Sourcing environment files
|
|
||||||
* Conditions for network/process/custom dependencies
|
|
||||||
* Readiness notification; PID files (native) for synchronizing system
|
|
||||||
startup, support for systemd [sd_notify()][], or [s6 style][] too
|
|
||||||
* Limited support for [tmpfiles.d(5)][] (no aging, attributes, or subvolumes)
|
|
||||||
* Pre/Post script actions
|
|
||||||
* Rudimentary [templating support](doc/config.md#templating)
|
|
||||||
* Tooling to enable/disable services
|
|
||||||
* Built-in getty
|
|
||||||
* Built-in watchdog, with support for hand-over to [watchdogd](https://troglobit.com/watchdogd.html)
|
|
||||||
* Built-in support for Debian/BusyBox `/etc/network/interfaces`
|
|
||||||
* Cgroups v2, both configuration and monitoring in `initctl top`
|
|
||||||
* Plugin support for customization
|
|
||||||
* Proper rescue mode with bundled `sulogin` for protected maintenance shell
|
|
||||||
* Integration with [watchdogd][] for full system supervision
|
|
||||||
* Logging to kernel ring buffer before `syslogd` has started, see the
|
|
||||||
recommended [sysklogd][] project for complete logging integration
|
|
||||||
and how to log to the kernel ring buffer from scripts using `logger`
|
|
||||||
|
|
||||||
Focus is on small and embedded systems, although Finit is fully usable
|
|
||||||
on server and desktop systems as well. For working examples, see the
|
|
||||||
[contrib/](contrib/) section with tutorials for the following Linux
|
|
||||||
distributions:
|
|
||||||
|
|
||||||
* [Void Linux](contrib/void/),
|
|
||||||
* [Alpine Linux](contrib/alpine/), and
|
|
||||||
* [Debian GNU/Linux](contrib/debian/), also works on Ubuntu/Linux Mint
|
|
||||||
|
|
||||||
> [!NOTE]
|
> [!NOTE]
|
||||||
> Support for various Linux distributions does not mean Finit installs
|
> Support for various Linux distributions does not mean Finit installs
|
||||||
> easily on all architectures. The bundled install scripts are examples
|
> easily on all architectures. Bundled install scripts are examples for
|
||||||
> for standard installations, tested on amd64 (x86_64) systems. Custom
|
> standard installations, tested on amd64 (x86_64) systems. Custom
|
||||||
> setups, e.g., for embedded systems, can be found in the following
|
> setups, e.g., for embedded systems, can be found in the following
|
||||||
> [Buildroot][] based examples: [myLinux][], [Infix][], or the plain
|
> [Buildroot][] based examples: [myLinux][], [Infix][], or the plain
|
||||||
> [br2-finit-demo](https://github.com/troglobit/br2-finit-demo).
|
> [br2-finit-demo](https://github.com/troglobit/br2-finit-demo).
|
||||||
|
|
||||||
|
[finix]: https://github.com/aanderse/finix
|
||||||
Example
|
|
||||||
-------
|
|
||||||
|
|
||||||
This example `/etc/finit.conf` can also be split up in multiple `.conf`
|
|
||||||
files in `/etc/finit.d`. Available, but not yet enabled, services can
|
|
||||||
be placed in `/etc/finit.d/available` and enabled by an operator using
|
|
||||||
the [initctl](#commands--status) tool. See the above mentioned Linux
|
|
||||||
distributions, or [myLinux][].
|
|
||||||
|
|
||||||
> [!TIP]
|
|
||||||
> As of Finit v4.4, `.conf` lines can be broken up using the standard
|
|
||||||
> 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,
|
|
||||||
> see the [finit.conf(5)][] manual or [doc/config.md](doc/config.md).
|
|
||||||
|
|
||||||
```ApacheConf
|
|
||||||
# Fallback if /etc/hostname is missing
|
|
||||||
host default
|
|
||||||
|
|
||||||
# Runlevel to start after bootstrap, 'S', default: 2
|
|
||||||
#runlevel 2
|
|
||||||
|
|
||||||
# Support for setting global environment variables, using foo=bar syntax
|
|
||||||
# be careful though with variables like PATH, SHELL, LOGNAME, etc.
|
|
||||||
#PATH=/usr/bin:/bin:/usr/sbin:/sbin
|
|
||||||
|
|
||||||
# Max file size for each log file: 100 kiB, rotate max 4 copies:
|
|
||||||
# log => log.1 => log.2.gz => log.3.gz => log.4.gz
|
|
||||||
log size=100k count=4
|
|
||||||
|
|
||||||
# Services to be monitored and respawned as needed
|
|
||||||
service [S12345] env:-/etc/conf.d/watchdog watchdog $WATCHDOG_OPTS $WATCHDOG_DEV -- System watchdog daemon
|
|
||||||
service [S12345] env:-/etc/conf.d/syslog syslogd -n $SYSLOGD_OPTS -- System log daemon
|
|
||||||
service [S12345] <pid/syslogd> env:-/etc/conf.d/klogd klogd -n $KLOGD_OPTS -- Kernel log daemon
|
|
||||||
service [2345] env:-/etc/conf.d/lldpd lldpd -d $LLDPD_OPTS -- LLDP daemon (IEEE 802.1ab)
|
|
||||||
|
|
||||||
# The BusyBox ntpd does not use syslog when running in the foreground
|
|
||||||
# So we use this trick to redirect stdout/stderr to a log file. The
|
|
||||||
# log file is rotated with the above settings. The condition declares
|
|
||||||
# a dependency on a system default route (gateway) to be set. A single
|
|
||||||
# <!> at the beginning means ntpd does not respect SIGHUP for restart.
|
|
||||||
service [2345] log:/var/log/ntpd.log <!net/route/default> ntpd -n -l -I eth0 -- NTP daemon
|
|
||||||
|
|
||||||
# For multiple instances of the same service, add :ID somewhere between
|
|
||||||
# the service/run/task keyword and the command.
|
|
||||||
service :80 [2345] merecat -n -p 80 /var/www -- Web server
|
|
||||||
service :8080 [2345] merecat -n -p 8080 /var/www -- Old web server
|
|
||||||
|
|
||||||
# Alternative method instead of below runparts, can also use /etc/rc.local
|
|
||||||
#sysv [S] /etc/init.d/keyboard-setup -- Setting up preliminary keymap
|
|
||||||
#sysv [S] /etc/init.d/acpid -- Starting ACPI Daemon
|
|
||||||
#task [S] /etc/init.d/kbd -- Preparing console
|
|
||||||
|
|
||||||
# Hidden from boot progress, using empty `--` description
|
|
||||||
#sysv [S] /etc/init.d/keyboard-setup --
|
|
||||||
#sysv [S] /etc/init.d/acpid --
|
|
||||||
#task [S] /etc/init.d/kbd --
|
|
||||||
|
|
||||||
# Run start scripts from this directory
|
|
||||||
# runparts /etc/start.d
|
|
||||||
|
|
||||||
# Virtual consoles run BusyBox getty, keep kernel default speed
|
|
||||||
tty [12345] /sbin/getty -L 0 /dev/tty1 linux nowait noclear
|
|
||||||
tty [2345] /sbin/getty -L 0 /dev/tty2 linux nowait noclear
|
|
||||||
tty [2345] /sbin/getty -L 0 /dev/tty3 linux nowait noclear
|
|
||||||
|
|
||||||
# Use built-in getty for serial port and USB serial
|
|
||||||
#tty [12345] /dev/ttyAMA0 noclear nowait
|
|
||||||
#tty [12345] /dev/ttyUSB0 noclear
|
|
||||||
|
|
||||||
# Just give me a shell, I need to debug this embedded system!
|
|
||||||
#tty [12345] console noclear nologin
|
|
||||||
```
|
|
||||||
|
|
||||||
The `service` stanza, as well as `task`, `run` and others are described
|
|
||||||
in full in [doc/config.md](doc/config.md). Here's a quick overview of
|
|
||||||
some of the most common components needed to start a UNIX daemon:
|
|
||||||
|
|
||||||
```
|
|
||||||
service [LVLS] <COND> log env:[-]/etc/default/daemon daemon ARGS -- Daemon daemon
|
|
||||||
^ ^ ^ ^ ^ ^ ^ ^
|
|
||||||
| | | | | | | `---------- Optional description
|
|
||||||
| | | | | | `------------------ Daemon arguments
|
|
||||||
| | | | | `------------------------- Path to daemon
|
|
||||||
| | | | `---------------------------------------------------- Optional env. file
|
|
||||||
| | | `-------------------------------------------------------- Redirect output to log
|
|
||||||
| | `--------------------------------------------------------------- Optional conditions
|
|
||||||
| `---------------------------------------------------------------------- Optional Runlevels
|
|
||||||
`------------------------------------------------------------------------------ Monitored application
|
|
||||||
```
|
|
||||||
|
|
||||||
Some components are optional: runlevel(s), condition(s) and description,
|
|
||||||
making it easy to create simple start scripts and still possible for more
|
|
||||||
advanced uses as well:
|
|
||||||
|
|
||||||
service /usr/sbin/sshd -D
|
|
||||||
|
|
||||||
Dependencies are handled using [conditions](doc/conditions.md). One of
|
|
||||||
the most common conditions is to wait for basic networking to become
|
|
||||||
available:
|
|
||||||
|
|
||||||
service <net/route/default> nginx -- High performance HTTP server
|
|
||||||
|
|
||||||
Here is another example where we instruct Finit to not start BusyBox
|
|
||||||
`ntpd` until `syslogd` has started properly. Finit waits for `syslogd`
|
|
||||||
to create its PID file, by default `/var/run/syslogd.pid`.
|
|
||||||
|
|
||||||
service [2345] log <!pid/syslogd> ntpd -n -N -p pool.ntp.org
|
|
||||||
service [S12345] syslogd -n -- Syslog daemon
|
|
||||||
|
|
||||||
Notice the `log` keyword, BusyBox `ntpd` uses `stderr` for logging when
|
|
||||||
run in the foreground. With `log` Finit redirects `stdout` + `stderr`
|
|
||||||
to the system log daemon using the command line `logger(1)` tool.
|
|
||||||
|
|
||||||
A service, or task, can have multiple dependencies listed. Here we wait
|
|
||||||
for *both* `syslogd` to have started and basic networking to be up:
|
|
||||||
|
|
||||||
service [2345] log <pid/syslogd,net/route/default> ntpd -n -N -p pool.ntp.org
|
|
||||||
|
|
||||||
If either condition fails, e.g. loss of networking, `ntpd` is stopped
|
|
||||||
and as soon as it comes back up again `ntpd` is restarted automatically.
|
|
||||||
|
|
||||||
**Note:** Make sure daemons *do not* fork and detach themselves from the
|
|
||||||
controlling TTY, usually an `-n` or `-f` flag, or `-D` as in the case
|
|
||||||
of OpenSSH above. If it detaches itself, Finit cannot monitor it and
|
|
||||||
will instead try to restart it.
|
|
||||||
|
|
||||||
|
|
||||||
Features
|
|
||||||
--------
|
|
||||||
|
|
||||||
**Process Supervision**
|
|
||||||
|
|
||||||
Start, monitor and restart services should they fail.
|
|
||||||
|
|
||||||
|
|
||||||
**Getty**
|
|
||||||
|
|
||||||
Finit supports external getty but also comes with a limited built-in
|
|
||||||
Getty, useful for really small systems. A getty sets up the TTY and
|
|
||||||
waits for user input before handing over to `/bin/login`, which is
|
|
||||||
responsible for handling the actual authentication.
|
|
||||||
|
|
||||||
```conf
|
|
||||||
tty [12345] /dev/tty1 nowait linux
|
|
||||||
tty [12345] /dev/ttyAMA0 noclear vt100
|
|
||||||
tty [12345] /sbin/getty -L /dev/ttyAMA0 vt100
|
|
||||||
```
|
|
||||||
|
|
||||||
Users of embedded systems may want to enable automatic serial console
|
|
||||||
with the special `@console` device. This works regardless weather the
|
|
||||||
system uses `ttyS0`, `ttyAMA0`, `ttyMXC0`, or anything else. Finit
|
|
||||||
figures it out by querying sysfs: `/sys/class/tty/console/active`.
|
|
||||||
|
|
||||||
```conf
|
|
||||||
tty [12345] @console linux noclear
|
|
||||||
```
|
|
||||||
|
|
||||||
Notice the optional `noclear`, `nowait`, and `nologin` flags. The
|
|
||||||
latter is for skipping the login process entirely. For more information,
|
|
||||||
see [doc/config.md](doc/config.md#syntax).
|
|
||||||
|
|
||||||
|
|
||||||
**Runlevels**
|
|
||||||
|
|
||||||
Support for SysV init-style [runlevels][5] is available, in the same
|
|
||||||
minimal style as everything else in Finit. The `[2345]` syntax can be
|
|
||||||
applied to service, task, run, and TTY stanzas.
|
|
||||||
|
|
||||||
Reserved runlevels are 0 and 6, halt and reboot, respectively just like
|
|
||||||
SysV init. Runlevel 1 can be configured freely, but is recommended to
|
|
||||||
be kept as the system single-user runlevel since Finit will not start
|
|
||||||
networking here. The configured `runlevel NUM` from `/etc/finit.conf`
|
|
||||||
is what Finit changes to after bootstrap, unless 'single' (or 'S') is
|
|
||||||
given on the kernel cmdline, in which case runlevel 1 is started.
|
|
||||||
|
|
||||||
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
|
|
||||||
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
|
|
||||||
[`initctl`](#commands--status) tool.
|
|
||||||
|
|
||||||
|
|
||||||
**Conditions**
|
|
||||||
|
|
||||||
As mentioned previously, Finit has an advanced dependency system to
|
|
||||||
handle synchronization, called [conditions](doc/conditions.md). It can
|
|
||||||
be used in many ways; depend on another service, network availability,
|
|
||||||
etc.
|
|
||||||
|
|
||||||
One *really cool* example useful for embedded systems is to run certain
|
|
||||||
scripts if a board has a certain feature encoded in its device tree. At
|
|
||||||
bootstrap we run the following `ident` script:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
#!/bin/sh
|
|
||||||
conddir=/var/run/finit/cond/hw/model
|
|
||||||
dtmodel=/sys/firmware/devicetree/base/model
|
|
||||||
|
|
||||||
if ! test -e $dtmodel; then
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
model=$(cat $dtmodel | tr "[A-Z] " "[a-z]-")
|
|
||||||
mkdir -p $conddir && ln -s ../../reconf $conddir/$model
|
|
||||||
```
|
|
||||||
|
|
||||||
Provided the device tree node exists, and is a string, we can then use
|
|
||||||
the condition `<hw/model/foo>` when starting other scripts. Here is an
|
|
||||||
example:
|
|
||||||
|
|
||||||
```
|
|
||||||
run [S] /path/to/ident --
|
|
||||||
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`
|
|
||||||
> in the Finit progress output.
|
|
||||||
|
|
||||||
|
|
||||||
**Plugins**
|
|
||||||
|
|
||||||
Plugins can *extend* the functionality of Finit and *hook into* the
|
|
||||||
different stages of the boot process and at runtime. Plugins are
|
|
||||||
written in C and compiled into a dynamic library loaded automatically by
|
|
||||||
finit at boot. A basic set of plugins are bundled in the `plugins/`
|
|
||||||
directory.
|
|
||||||
|
|
||||||
Capabilities:
|
|
||||||
|
|
||||||
- **Hooks**
|
|
||||||
Hook into the boot at predefined points to extend Finit
|
|
||||||
- **I/O**
|
|
||||||
Listen to external events and control Finit behavior/services
|
|
||||||
|
|
||||||
Extensions and functionality not purely related to what an `/sbin/init`
|
|
||||||
needs to start a system are available as a set of plugins that either
|
|
||||||
hook into the boot process or respond to various I/O.
|
|
||||||
|
|
||||||
For more information, see [doc/plugins.md](doc/plugins.md).
|
|
||||||
|
|
||||||
|
|
||||||
**Automatic Reload**
|
|
||||||
|
|
||||||
By default, Finit monitors `/etc/finit.d/` and `/etc/finit.d/enabled/`
|
|
||||||
registering any changes to `.conf` files. To activate a change the user
|
|
||||||
must call `initctl reload`, which reloads all modified files, stops any
|
|
||||||
removed services, starts new ones, and restarts any modified ones. If the
|
|
||||||
command line arguments of a service have changed, the process will be
|
|
||||||
terminated and then started again with the updated arguments. If the arguments
|
|
||||||
have not been modified and the process supports SIGHUP, the process will
|
|
||||||
receive a SIGHUP rather than being terminated and started.
|
|
||||||
|
|
||||||
For some use-cases the extra step of calling `initctl reload` creates an
|
|
||||||
unnecessary overhead, which can be removed at build-time using:
|
|
||||||
|
|
||||||
configure --enable-auto-reload
|
|
||||||
|
|
||||||
|
|
||||||
**Cgroups**
|
|
||||||
|
|
||||||
Finit supports cgroups v2 and comes with the following default groups in
|
|
||||||
which services and user sessions are placed in:
|
|
||||||
|
|
||||||
/sys/fs/cgroup
|
|
||||||
|-- init/ # cpu.weight:100
|
|
||||||
|-- system/ # cpu.weight:9800
|
|
||||||
`-- user/ # cpu.weight:100
|
|
||||||
|
|
||||||
Finit itself and its helper scripts and services are placed in the
|
|
||||||
top-level leaf-node group `init/`, which also is _reserved_.
|
|
||||||
|
|
||||||
All run/task/service/sysv processes are placed in their own sub-group
|
|
||||||
in `system/`. The name of each sub-group is taken from the respective
|
|
||||||
`.conf` file from `/etc/finit.d`.
|
|
||||||
|
|
||||||
All getty/tty processes are placed in their own sub-group in `user/`.
|
|
||||||
The name of each sub-group is taken from the username.
|
|
||||||
|
|
||||||
A fourth group also exists, the `root` group. It is also _reserved_ and
|
|
||||||
primarily intended for RT tasks. If you have RT tasks they need to be
|
|
||||||
declared as such in their service stanza like this:
|
|
||||||
|
|
||||||
service [...] <...> cgroup.root /path/to/foo args -- description
|
|
||||||
|
|
||||||
or
|
|
||||||
|
|
||||||
cgroup.root
|
|
||||||
service [...] <...> /path/to/foo args -- description
|
|
||||||
service [...] <...> /path/to/bar args -- description
|
|
||||||
|
|
||||||
See [doc/config.md](doc/config.md#cgroups) for more information, e.g.,
|
|
||||||
how to configure per-group limits.
|
|
||||||
|
|
||||||
The `initctl` tool has three commands to help debug and optimize the
|
|
||||||
setup and monitoring of cgroups. See the `ps`, `top`, and `cgroup`
|
|
||||||
commands for details.
|
|
||||||
|
|
||||||
> [!NOTE]
|
|
||||||
> Systems that do not support cgroups, specifically version 2, are
|
|
||||||
> automatically detected. On such systems the above functionality is
|
|
||||||
> disabled early at boot.
|
|
||||||
|
|
||||||
|
|
||||||
Runparts & /etc/rc.local
|
|
||||||
------------------------
|
|
||||||
|
|
||||||
At the end of the boot, when all bootstrap (`S`) tasks and services have
|
|
||||||
started, but not networking, Finit calls its built-in [run-parts(8)][]
|
|
||||||
command on any configured `runparts <DIR>` directory. This happens just
|
|
||||||
before changing to the configured runlevel (default 2). (Networking is
|
|
||||||
enabled just prior to changing from single user mode.)
|
|
||||||
|
|
||||||
```shell
|
|
||||||
runparts /etc/rc.d/
|
|
||||||
```
|
|
||||||
|
|
||||||
Right after the runlevel change when all services have started properly,
|
|
||||||
`/etc/rc.local` is called.
|
|
||||||
|
|
||||||
No configuration stanza in `/etc/finit.conf` is required for `rc.local`.
|
|
||||||
If it exists and is an executable shell script Finit calls it at the very
|
|
||||||
end of the boot, before calling the `HOOK_SYSTEM_UP`. See more on hooks
|
|
||||||
in [doc/plugins.md](doc/plugins.md#hooks).
|
|
||||||
|
|
||||||
|
|
||||||
### Limitations
|
|
||||||
|
|
||||||
It is not possible to call Finit via signals or use `initctl` in any
|
|
||||||
runparts or `/etc/rc.local` script. This because Finit is single
|
|
||||||
threaded and is calling these scripts in a blocking fashion at the end
|
|
||||||
of runlevel S, at which point the event loop has not yet been started.
|
|
||||||
|
|
||||||
The event loop is the whole thing which Finit is built around, except
|
|
||||||
for runlevel S, which remains a slow procession through a lot of set up,
|
|
||||||
with a few hooks and blocking call outs to external scripts.
|
|
||||||
|
|
||||||
However, not all `initctl` commands are prohibited. Supported commands:
|
|
||||||
|
|
||||||
- `inictl cond`: only operate of files in `/run/finit/cond`
|
|
||||||
- `initctl enable/disable`: enabled run/task/service is activated on
|
|
||||||
the runlevel change from S to 2
|
|
||||||
- `initctl touch/show/create/delete/list`: `create`, provided the
|
|
||||||
non-interactive mode is used, again changes take effect in the
|
|
||||||
runlevel change directly after bootstrap
|
|
||||||
- `initctl -f reboot/poweroff/halt`: provided the `-f` flag is used to
|
|
||||||
force direct kernel commands
|
|
||||||
|
|
||||||
**Example:** you can set a `usr/` condition in `/etc/rc.local` and have
|
|
||||||
a service/task in runlevel 2 depend on it to execute.
|
|
||||||
|
|
||||||
|
|
||||||
Runlevels
|
|
||||||
---------
|
|
||||||
|
|
||||||
Basic support for [runlevels][5] is included in Finit from v1.8. By
|
|
||||||
default all services, tasks, run commands and TTYs listed without a set
|
|
||||||
of runlevels get a default set `[234]` assigned. The default runlevel
|
|
||||||
after boot is 2.
|
|
||||||
|
|
||||||
Finit supports runlevels 0-9, and S, with 0 reserved for halt, 6 reboot
|
|
||||||
and S for services to only run at bootstrap. Runlevel 1 is the single
|
|
||||||
user level, where usually no networking is enabled. In Finit this is
|
|
||||||
more of a policy for the user to define. Normally only runlevels 1-6
|
|
||||||
are used, and even more commonly, only the default runlevel is used.
|
|
||||||
|
|
||||||
To specify an allowed set of runlevels for a `service`, `run` command,
|
|
||||||
`task`, or `tty`, add `[NNN]` to your `/etc/finit.conf`, like this:
|
|
||||||
|
|
||||||
```
|
|
||||||
service [S12345] syslogd -n -x -- System log daemon
|
|
||||||
run [S] /etc/init.d/acpid start -- Starting ACPI Daemon
|
|
||||||
task [S] /etc/init.d/kbd start -- Preparing console
|
|
||||||
service [S12345] <pid/syslogd> klogd -n -x -- Kernel log daemon
|
|
||||||
|
|
||||||
tty [12345] /dev/tty1
|
|
||||||
tty [2] /dev/tty2
|
|
||||||
tty [2] /dev/tty3
|
|
||||||
tty [2] /dev/tty4
|
|
||||||
tty [2] /dev/tty5
|
|
||||||
tty [2] /dev/tty6
|
|
||||||
```
|
|
||||||
|
|
||||||
In this example syslogd is first started, in parallel, and then acpid is
|
|
||||||
called using a conventional SysV init script. It is called with the run
|
|
||||||
command, meaning the following task command to start the kbd script is
|
|
||||||
not called until the acpid init script has fully completed. Then the
|
|
||||||
keyboard setup script is called in parallel with klogd as a monitored
|
|
||||||
service.
|
|
||||||
|
|
||||||
Again, tasks and services are started in parallel, while run commands
|
|
||||||
are called in the order listed and subsequent commands are not started
|
|
||||||
until a run command has completed. Also, task and run commands are run
|
|
||||||
in a shell, so pipes and redirects can be used.
|
|
||||||
|
|
||||||
The following examples illustrate this. Bootstrap task and run commands
|
|
||||||
are also removed when they have completed, `initctl show` will not list
|
|
||||||
them.
|
|
||||||
|
|
||||||
```
|
|
||||||
task [S] echo "foo" | cat >/tmp/bar
|
|
||||||
run [S] echo "$HOME" >/tmp/secret
|
|
||||||
```
|
|
||||||
|
|
||||||
Switching between runlevels can be done by calling init with a single
|
|
||||||
argument, e.g. <kbd>init 5</kbd>, or using `initctl runlevel 5`, both
|
|
||||||
switch to runlevel 5. When changing runlevels Finit also automatically
|
|
||||||
reloads all `.conf` files in the `/etc/finit.d/` directory. So if you
|
|
||||||
want to set a new system config, switch to runlevel 1, change all config
|
|
||||||
files in the system, and touch all `.conf` files in `/etc/finit.d`
|
|
||||||
before switching back to the previous runlevel again — that way Finit
|
|
||||||
can both stop old services and start any new ones for you, without
|
|
||||||
rebooting the system.
|
|
||||||
|
|
||||||
|
|
||||||
Rebooting & Halting
|
|
||||||
-------------------
|
|
||||||
|
|
||||||
Traditionally, rebooting and halting a UNIX system is done by changing
|
|
||||||
its runlevel. Finit comes with its own tooling providing: `shutdown`,
|
|
||||||
`reboot`, `poweroff`, and `suspend`, but also the `initctl` tool,
|
|
||||||
detailed in the next section.
|
|
||||||
|
|
||||||
For compatibility reasons Finit listens to the same set of signals as
|
|
||||||
BusyBox init. This is not 100% compatible with SysV init, but clearly
|
|
||||||
the more common combination for Finit. For more details, see
|
|
||||||
[doc/signals.md](doc/signals.md).
|
|
||||||
|
|
||||||
|
|
||||||
Commands & Status
|
|
||||||
-----------------
|
|
||||||
|
|
||||||
Finit also implements a modern API to query status, and start/stop
|
|
||||||
services, called `initctl`. Unlike `telinit` the `initctl` tool does
|
|
||||||
not return until the given command has fully completed.
|
|
||||||
|
|
||||||
```
|
|
||||||
Usage: initctl [OPTIONS] [COMMAND]
|
|
||||||
|
|
||||||
Options:
|
|
||||||
-b, --batch Batch mode, no screen size probing
|
|
||||||
-c, --create Create missing paths (and files) as needed
|
|
||||||
-f, --force Ignore missing files and arguments, never prompt
|
|
||||||
-h, --help This help text
|
|
||||||
-j, --json JSON output in 'status' and 'cond' commands
|
|
||||||
-1, --once Only one lap in commands like 'top'
|
|
||||||
-p, --plain Use plain table headings, no ctrl chars
|
|
||||||
-q, --quiet Silent, only return status of command
|
|
||||||
-t, --no-heading Skip table headings
|
|
||||||
-v, --verbose Verbose output
|
|
||||||
-V, --version Show program version
|
|
||||||
|
|
||||||
Commands:
|
|
||||||
debug Toggle Finit (daemon) debug
|
|
||||||
help This help text
|
|
||||||
version Show program version
|
|
||||||
|
|
||||||
ls | list List all .conf in /etc/finit.d
|
|
||||||
create <CONF> Create .conf in /etc/finit.d/available
|
|
||||||
delete <CONF> Delete .conf in /etc/finit.d/available
|
|
||||||
show <CONF> Show .conf in /etc/finit.d/available
|
|
||||||
edit <CONF> Edit .conf in /etc/finit.d/available
|
|
||||||
touch <CONF> Change .conf in /etc/finit.d/available
|
|
||||||
enable <CONF> Enable .conf in /etc/finit.d/available
|
|
||||||
disable <CONF> Disable .conf in /etc/finit.d/enabled
|
|
||||||
reload Reload *.conf in /etc/finit.d (activate changes)
|
|
||||||
|
|
||||||
cond set <COND> Set (assert) user-defined conditions +usr/COND
|
|
||||||
cond get <COND> Get status of user-defined condition, see $? and -v
|
|
||||||
cond clear <COND> Clear (deassert) user-defined conditions -usr/COND
|
|
||||||
cond status Show condition status, default cond command
|
|
||||||
cond dump [TYPE] Dump all, or a type of, conditions and their status
|
|
||||||
|
|
||||||
log [NAME] Show ten last Finit, or NAME, messages from syslog
|
|
||||||
start <NAME>[:ID] Start service by name, with optional ID
|
|
||||||
stop <NAME>[:ID] Stop/Pause a running service by name
|
|
||||||
reload <NAME>[:ID] Reload service as if .conf changed (SIGHUP or restart)
|
|
||||||
This allows restart of run/tasks that have already run
|
|
||||||
Note: Finit .conf file(s) are *not* reloaded!
|
|
||||||
restart <NAME>[:ID] Restart (stop/start) service by name
|
|
||||||
signal <NAME>[:ID] <S> Send signal S to service by name, with optional ID
|
|
||||||
ident [NAME] Show matching identities for NAME, or all
|
|
||||||
status <NAME>[:ID] Show service status, by name
|
|
||||||
status Show status of services, default command
|
|
||||||
|
|
||||||
cgroup List cgroup config overview
|
|
||||||
ps List processes based on cgroups
|
|
||||||
top Show top-like listing based on cgroups
|
|
||||||
|
|
||||||
plugins List installed plugins
|
|
||||||
|
|
||||||
runlevel [0-9] Show or set runlevel: 0 halt, 6 reboot
|
|
||||||
reboot Reboot system
|
|
||||||
halt Halt system
|
|
||||||
poweroff Halt and power off system
|
|
||||||
suspend Suspend system
|
|
||||||
|
|
||||||
utmp show Raw dump of UTMP/WTMP db
|
|
||||||
```
|
|
||||||
|
|
||||||
For services *not* supporting `SIGHUP` the `<!>` notation in the .conf
|
|
||||||
file must be used to tell Finit to stop and start it on `reload` and
|
|
||||||
`runlevel` changes. If `<>` holds more [conditions](doc/conditions.md),
|
|
||||||
these will also affect how a service is maintained.
|
|
||||||
|
|
||||||
> [!NOTE]
|
|
||||||
> Even though it is possible to start services not belonging in the
|
|
||||||
> 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.
|
|
||||||
|
|
||||||
The `status` command is the default, it displays a quick overview of all
|
|
||||||
monitored run/task/services. Here we call `initctl -p`, suitable for
|
|
||||||
scripting and documentation:
|
|
||||||
|
|
||||||
```
|
|
||||||
alpine:~# initctl -p
|
|
||||||
PID IDENT STATUS RUNLEVELS DESCRIPTION
|
|
||||||
======================================================================
|
|
||||||
1506 acpid running [---2345----] ACPI daemon
|
|
||||||
1509 crond running [---2345----] Cron daemon
|
|
||||||
1489 dropbear running [---2345----] Dropbear SSH daemon
|
|
||||||
1511 klogd running [S-12345----] Kernel log daemon
|
|
||||||
1512 ntpd running [---2345----] NTP daemon
|
|
||||||
1473 syslogd running [S-12345----] Syslog daemon
|
|
||||||
|
|
||||||
alpine:~# initctl -pv
|
|
||||||
PID IDENT STATUS RUNLEVELS COMMAND
|
|
||||||
======================================================================
|
|
||||||
1506 acpid running [---2345----] acpid -f
|
|
||||||
1509 crond running [---2345----] crond -f -S $CRON_OPTS
|
|
||||||
1489 dropbear running [---2345----] dropbear -R -F $DROPBEAR_OPTS
|
|
||||||
1511 klogd running [S-12345----] klogd -n $KLOGD_OPTS
|
|
||||||
1512 ntpd running [---2345----] ntpd -n $NTPD_OPTS
|
|
||||||
1473 syslogd running [S-12345----] syslogd -n
|
|
||||||
```
|
|
||||||
|
|
||||||
The environment variables to each of the services above are read from,
|
|
||||||
in the case of Alpine Linux, `/etc/conf.d/`. Other distributions may
|
|
||||||
have other directories, e.g., Debian use `/etc/default/`.
|
|
||||||
|
|
||||||
The `status` command takes an optional `NAME:ID` argument. Here we
|
|
||||||
check the status of `dropbear`, which only has one instance in this
|
|
||||||
system:
|
|
||||||
|
|
||||||
```
|
|
||||||
alpine:~# initctl -p status dropbear
|
|
||||||
Status : running
|
|
||||||
Identity : dropbear
|
|
||||||
Description : Dropbear SSH daemon
|
|
||||||
Origin : /etc/finit.d/enabled/dropbear.conf
|
|
||||||
Environment : -/etc/conf.d/dropbear
|
|
||||||
Condition(s):
|
|
||||||
Command : dropbear -R -F $DROPBEAR_OPTS
|
|
||||||
PID file : !/run/dropbear.pid
|
|
||||||
PID : 1485
|
|
||||||
User : root
|
|
||||||
Group : root
|
|
||||||
Uptime : 2 hour 46 min 56 sec
|
|
||||||
Runlevels : [---2345----]
|
|
||||||
Memory : 1.2M
|
|
||||||
CGroup : /system/dropbear cpu 0 [100, max] mem [--.--, max]
|
|
||||||
|- 1485 dropbear -R -F
|
|
||||||
|- 2634 dropbear -R -F
|
|
||||||
|- 2635 ash
|
|
||||||
`- 2652 initctl -p status dropbear
|
|
||||||
|
|
||||||
Apr 8 12:19:49 alpine authpriv.info dropbear[1485]: Not backgrounding
|
|
||||||
Apr 8 12:37:45 alpine authpriv.info dropbear[2300]: Child connection from 192.168.121.1:47834
|
|
||||||
Apr 8 12:37:46 alpine authpriv.notice dropbear[2300]: Password auth succeeded for 'root' from 192.168.121.1:47834
|
|
||||||
Apr 8 12:37:46 alpine authpriv.info dropbear[2300]: Exit (root) from <192.168.121.1:47834>: Disconnect received
|
|
||||||
Apr 8 15:02:11 alpine authpriv.info dropbear[2634]: Child connection from 192.168.121.1:48576
|
|
||||||
Apr 8 15:02:12 alpine authpriv.notice dropbear[2634]: Password auth succeeded for 'root' from 192.168.121.1:48576
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
Requirements
|
|
||||||
------------
|
|
||||||
|
|
||||||
Finit is capable of running on both desktop/server systems with udev and
|
|
||||||
embedded systems that usually come with BusyBox mdev. Some systems have
|
|
||||||
systemd-udev or eudev today instead of the original udev, Finit probes
|
|
||||||
for all of them at runtime and expects `/dev/` to be a writable file
|
|
||||||
system using `devtmpfs`. It is also possible to run on a statically set
|
|
||||||
up `/dev` if needed. It is however not a good idea to have both udev
|
|
||||||
and mdev installed at the same time, this will lead to unpredictable
|
|
||||||
results.
|
|
||||||
|
|
||||||
At boot Finit calls either `mdev` or `udevd` to populate `/dev`, this is
|
|
||||||
done slightly differently and on systems with udev you might want to add
|
|
||||||
the following one-shot task early in your `/etc/finit.conf`:
|
|
||||||
|
|
||||||
```conf
|
|
||||||
run [S] udevadm settle --timeout=120 -- Waiting for udev
|
|
||||||
```
|
|
||||||
|
|
||||||
Finit has a built-in Getty for TTYs, but requires a working `/bin/login`
|
|
||||||
or `/bin/sh`, if no TTYs are configured in `/etc/finit.conf`.
|
|
||||||
|
|
||||||
For a fully operational system `/var`, `/run` and `/tmp` must be set up
|
|
||||||
properly in `/etc/fstab` -- which is iterated over at boot.
|
|
||||||
|
|
||||||
|
|
||||||
Origin & References
|
|
||||||
-------------------
|
|
||||||
|
|
||||||
This project is based on the [original finit][] by [Claudio Matsuoka][]
|
|
||||||
which was reverse engineered from syscalls of the [EeePC fastinit][] —
|
|
||||||
"gaps filled with frog DNA …"
|
|
||||||
|
|
||||||
Finit is developed and maintained by [Joachim Wiberg][] at [GitHub][6].
|
|
||||||
Please file bug reports, clone it, or send pull requests for bug fixes
|
|
||||||
and proposed extensions.
|
|
||||||
|
|
||||||
|
|
||||||
[1]: https://en.wikipedia.org/wiki/Process_supervision
|
|
||||||
[2]: https://cr.yp.to/daemontools.html
|
|
||||||
[3]: https://smarden.org/runit/
|
|
||||||
[4]: https://en.wikipedia.org/wiki/Init
|
|
||||||
[5]: https://en.wikipedia.org/wiki/Runlevel
|
|
||||||
[6]: https://github.com/troglobit/finit
|
|
||||||
[RFC862]: https://tools.ietf.org/html/rfc862
|
|
||||||
[RFC863]: https://tools.ietf.org/html/rfc863
|
|
||||||
[RFC864]: https://tools.ietf.org/html/rfc864
|
|
||||||
[RFC867]: https://tools.ietf.org/html/rfc867
|
|
||||||
[RFC868]: https://tools.ietf.org/html/rfc868
|
|
||||||
[init]: https://en.wikipedia.org/wiki/Init
|
|
||||||
[upstart]: https://upstart.ubuntu.com/
|
|
||||||
[systemd]: https://www.freedesktop.org/wiki/Software/systemd/
|
|
||||||
[openrc]: https://www.gentoo.org/proj/en/base/openrc/
|
|
||||||
[sd_notify()]: https://www.freedesktop.org/software/systemd/man/sd_notify.html
|
|
||||||
[s6 style]: https://skarnet.org/software/s6/notifywhenup.html
|
|
||||||
[run-parts(8)]: https://manpages.debian.org/cgi-bin/man.cgi?query=run-parts
|
|
||||||
[tmpfiles.d(5)]: https://www.freedesktop.org/software/systemd/man/tmpfiles.d.html
|
|
||||||
[original finit]: http://helllabs.org/finit/
|
|
||||||
[EeePC fastinit]: https://web.archive.org/web/20071208212450/http://wiki.eeeuser.com/boot_process:the_boot_process
|
|
||||||
[Claudio Matsuoka]: https://github.com/cmatsuoka
|
|
||||||
[Joachim Wiberg]: https://troglobit.com
|
|
||||||
[Buildroot]: https://buildroot.org
|
[Buildroot]: https://buildroot.org
|
||||||
[Infix]: https://kernelkit.github.io
|
[Infix]: https://kernelkit.github.io
|
||||||
[finit.conf(5)]: https://man.troglobit.com/man5/finit.conf.5.html
|
[myLinux]: https://github.com/troglobit/myLinux/
|
||||||
|
[EeePC fastinit]: https://web.archive.org/web/20071208212450/http://wiki.eeeuser.com/boot_process:the_boot_process
|
||||||
|
[Claudio Matsuoka]: https://github.com/cmatsuoka
|
||||||
[License]: https://en.wikipedia.org/wiki/MIT_License
|
[License]: https://en.wikipedia.org/wiki/MIT_License
|
||||||
[License Badge]: https://img.shields.io/badge/License-MIT-teal.svg
|
[License Badge]: https://img.shields.io/badge/License-MIT-teal.svg
|
||||||
[myLinux]: https://github.com/troglobit/myLinux/
|
|
||||||
[watchdogd]: https://github.com/troglobit/watchdogd/
|
|
||||||
[sysklogd]: https://github.com/troglobit/sysklogd/
|
|
||||||
[GitHub]: https://github.com/troglobit/finit/actions/workflows/build.yml/
|
[GitHub]: https://github.com/troglobit/finit/actions/workflows/build.yml/
|
||||||
[GitHub Status]: https://github.com/troglobit/finit/actions/workflows/build.yml/badge.svg
|
[GitHub Status]: https://github.com/troglobit/finit/actions/workflows/build.yml/badge.svg
|
||||||
[Coverity Scan]: https://scan.coverity.com/projects/3545
|
[Coverity Scan]: https://scan.coverity.com/projects/3545
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
AC_INIT([Finit], [4.13-pre], [https://github.com/troglobit/finit/issues],
|
AC_INIT([Finit], [4.13-rc1], [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 subdir-objects])
|
||||||
AM_SILENT_RULES([yes])
|
AM_SILENT_RULES([yes])
|
||||||
|
|
||||||
AC_CONFIG_SRCDIR([src/finit.c])
|
AC_CONFIG_SRCDIR([src/finit.c])
|
||||||
@@ -11,7 +11,7 @@ AC_CONFIG_FILES([Makefile
|
|||||||
contrib/alpine/Makefile contrib/alpine/finit.d/Makefile contrib/alpine/finit.d/available/Makefile
|
contrib/alpine/Makefile contrib/alpine/finit.d/Makefile contrib/alpine/finit.d/available/Makefile
|
||||||
contrib/debian/Makefile contrib/debian/finit.d/Makefile contrib/debian/finit.d/available/Makefile
|
contrib/debian/Makefile contrib/debian/finit.d/Makefile contrib/debian/finit.d/available/Makefile
|
||||||
contrib/void/Makefile contrib/void/finit.d/Makefile contrib/void/finit.d/available/Makefile
|
contrib/void/Makefile contrib/void/finit.d/Makefile contrib/void/finit.d/available/Makefile
|
||||||
doc/Makefile
|
doc/Makefile doc/config/Makefile
|
||||||
libsystemd/Makefile libsystemd/libsystemd.pc
|
libsystemd/Makefile libsystemd/libsystemd.pc
|
||||||
man/Makefile
|
man/Makefile
|
||||||
plugins/Makefile
|
plugins/Makefile
|
||||||
|
|||||||
@@ -3,3 +3,8 @@ bin_SCRIPT = service
|
|||||||
docsdir := @docdir@/contrib
|
docsdir := @docdir@/contrib
|
||||||
docs_DATA = README.md finit.conf procmon.sh
|
docs_DATA = README.md finit.conf procmon.sh
|
||||||
EXTRA_DIST = $(docs_DATA)
|
EXTRA_DIST = $(docs_DATA)
|
||||||
|
|
||||||
|
if BASH
|
||||||
|
bashdir = $(BASH_DIR)
|
||||||
|
dist_bash_DATA = initctl
|
||||||
|
endif
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ install and try out Finit on various Linux distributions.
|
|||||||
|
|
||||||
* [Alpine](alpine/)
|
* [Alpine](alpine/)
|
||||||
* [Debian](debian/)
|
* [Debian](debian/)
|
||||||
|
* [Void](void/)
|
||||||
|
|
||||||
If you have ideas on how to simplify, extend, or even add new example
|
If you have ideas on how to simplify, extend, or even add new example
|
||||||
configurations for other distributions you are most welcome! :)
|
configurations for other distributions you are most welcome! :)
|
||||||
|
|||||||
@@ -4,6 +4,41 @@ Change Log
|
|||||||
All relevant changes are documented in this file.
|
All relevant changes are documented in this file.
|
||||||
|
|
||||||
|
|
||||||
|
[4.13][] - 2025-07-10
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
> [!NOTE]
|
||||||
|
> This release introduce a bare bones `libsystemd` replacement with an
|
||||||
|
> `<systemd/sd-daemon>.h` include file. Other systemd features are the
|
||||||
|
> `reload:script` and `stop:script`, mimicking ExecReload and ExecStop.
|
||||||
|
|
||||||
|
### Changes
|
||||||
|
- Drop xz tarballs from distribution, gzip is good enough
|
||||||
|
- New `tmpfiles` stand-alone program, refactored from the existing
|
||||||
|
tmpfiles.d support in Finit, by Aaron Andersen, PR #439
|
||||||
|
- `--remove` command runs only the `r` and `R` rules
|
||||||
|
- `--create` is used for all other cases (bootstrap)
|
||||||
|
- All `notify:systemd` services now log with `logit` by default. This
|
||||||
|
because it supports systemd style log severity, leading `"<NUM>"`
|
||||||
|
- Support for quoted arguments to run/task/service options, issue #441
|
||||||
|
- Clear command line arguments after bootstrap, issue #442
|
||||||
|
- Support for `stop:'script [args]'` to stop a sysv/service instead of
|
||||||
|
the common `foo-stop-start.sh stop`, or `SIGTERM`, issue #412
|
||||||
|
- Support for `reload:'script [args]'` to trigger a configuration
|
||||||
|
reload in a service, issue #446
|
||||||
|
|
||||||
|
### Fixes
|
||||||
|
- Fix #437: buffer overflow in `initctl status`
|
||||||
|
- Fix #438: support very long command lines in `initctl ps/top`
|
||||||
|
- Fix #440: broken systemd and s6 readiness notification
|
||||||
|
- Fix #443: build warnings, by Ming Liu, Atlas Copco
|
||||||
|
- Fix #444: handle loooooong arguments, by Aaron Andersen
|
||||||
|
- Fix service's redirected stdout/stderr log priority in fallback mode,
|
||||||
|
when neither `logger` or `logit` is available. This fix also checks
|
||||||
|
for systemd style log severity, leading `"<NUM>"` in log messages
|
||||||
|
- Ensure API socket used by `initctl` is non-blocking (event loop)
|
||||||
|
|
||||||
|
|
||||||
[4.12][] - 2025-04-28
|
[4.12][] - 2025-04-28
|
||||||
---------------------
|
---------------------
|
||||||
|
|
||||||
@@ -1797,7 +1832,8 @@ Major bug fix release.
|
|||||||
|
|
||||||
* Initial release
|
* Initial release
|
||||||
|
|
||||||
[UNRELEASED]: https://github.com/troglobit/finit/compare/4.11...HEAD
|
[UNRELEASED]: https://github.com/troglobit/finit/compare/4.12...HEAD
|
||||||
|
[4.13]: https://github.com/troglobit/finit/compare/4.12...4.13
|
||||||
[4.12]: https://github.com/troglobit/finit/compare/4.11...4.12
|
[4.12]: https://github.com/troglobit/finit/compare/4.11...4.12
|
||||||
[4.11]: https://github.com/troglobit/finit/compare/4.10...4.11
|
[4.11]: https://github.com/troglobit/finit/compare/4.10...4.11
|
||||||
[4.10]: https://github.com/troglobit/finit/compare/4.9...4.10
|
[4.10]: https://github.com/troglobit/finit/compare/4.9...4.10
|
||||||
@@ -1,4 +1,11 @@
|
|||||||
docsdir := @docdir@/doc
|
SUBDIRS = config
|
||||||
docs_DATA = config.md conditions.md distro.md plugins.md \
|
EXTRA_DIST = AUTHORS ChangeLog.md
|
||||||
service.md signals.md svc-machine.png cmdline.md
|
|
||||||
EXTRA_DIST = $(docs_DATA)
|
docsdir := @docdir@/doc
|
||||||
|
dist_docs_DATA = build.md cmdline.md commands.md conditions.md \
|
||||||
|
distro.md example.md features.md index.md initctl.md \
|
||||||
|
keventd.md plugins.md requirements.md runlevels.md \
|
||||||
|
runparts.md service.md signals.md state-machine.md \
|
||||||
|
watchdog.md
|
||||||
|
dist_docs_DATA += img/logo.png img/svc-machine.png img/svc-machine.svg \
|
||||||
|
img/alpine-screenshot2.png
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
config.md
|
|
||||||
@@ -1,16 +1,6 @@
|
|||||||
Building Finit
|
Building Finit
|
||||||
==============
|
==============
|
||||||
|
|
||||||
* [Introduction](#introduction)
|
|
||||||
* [Configure](#configure)
|
|
||||||
* [Example](#example)
|
|
||||||
* [Running](#running)
|
|
||||||
* [Debugging](#debugging)
|
|
||||||
|
|
||||||
|
|
||||||
Introduction
|
|
||||||
------------
|
|
||||||
|
|
||||||
Finit comes with a traditional configure script to control features and
|
Finit comes with a traditional configure script to control features and
|
||||||
optional plugins to enable. It depends on two external libraries:
|
optional plugins to enable. It depends on two external libraries:
|
||||||
|
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ The `bool` setting is one of `on, off, true false, 1, 0`.
|
|||||||
system bootstrap.
|
system bootstrap.
|
||||||
|
|
||||||
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][rescue].
|
||||||
|
|
||||||
> [!NOTE]
|
> [!NOTE]
|
||||||
> `<boot/...>` conditions cannot be cleared with `initctl`!
|
> `<boot/...>` conditions cannot be cleared with `initctl`!
|
||||||
@@ -39,10 +39,10 @@ The `bool` setting is one of `on, off, true false, 1, 0`.
|
|||||||
|
|
||||||
./configure --with-config=/etc/finit.conf
|
./configure --with-config=/etc/finit.conf
|
||||||
|
|
||||||
Useful when starting up in various rescue mode, factory, or
|
Useful when starting up in various [rescue mode][rescue], factory, or
|
||||||
production test setups. Use the top-level configuration file
|
production test setups. Use the top-level configuration file
|
||||||
directive `rcsd /path/to/finit.d` to override the default
|
directive `rcsd /path/to/finit.d` to override the default rcS.d
|
||||||
rcS.d directory.
|
directory.
|
||||||
|
|
||||||
* `finit.debug[=bool]`: Enable finit debug. This is operated
|
* `finit.debug[=bool]`: Enable finit debug. This is operated
|
||||||
independently of the kernel `debug` setting. New as of Finit v4.
|
independently of the kernel `debug` setting. New as of Finit v4.
|
||||||
@@ -75,7 +75,7 @@ The `bool` setting is one of `on, off, true false, 1, 0`.
|
|||||||
* `init=/bin/sh`: Bypass system default init and tell kernel to start a
|
* `init=/bin/sh`: Bypass system default init and tell kernel to start a
|
||||||
shell. Note, this shell is very limited and does not support
|
shell. Note, this shell is very limited and does not support
|
||||||
signals and has no job control. Recommend using, and modifying,
|
signals and has no job control. Recommend using, and modifying,
|
||||||
`rescue` mode instead.
|
[`rescue` mode][rescue] instead.
|
||||||
|
|
||||||
* `loglevel=<0-7>`, sets the kernel's log level, which is more granular
|
* `loglevel=<0-7>`, sets the kernel's log level, which is more granular
|
||||||
than `debug`. Also, when `loglevel=7`, Finit will *not disable*
|
than `debug`. Also, when `loglevel=7`, Finit will *not disable*
|
||||||
@@ -90,12 +90,11 @@ The `bool` setting is one of `on, off, true false, 1, 0`.
|
|||||||
* `quiet`: Suppress kernel logging to console, except for warnings and
|
* `quiet`: Suppress kernel logging to console, except for warnings and
|
||||||
errors. Also, see `loglevel` and `quiet` above.
|
errors. Also, see `loglevel` and `quiet` above.
|
||||||
|
|
||||||
* `rescue`: Start rescue/maintenance mode. If your system comes with
|
* `rescue`: Start [rescue/maintenance mode][rescue]. If your system
|
||||||
the bundled `sulogin` program (Finit, or from util-linux/Busybox),
|
comes with the bundled `sulogin` program (Finit, or from util-linux,
|
||||||
you will be given a root login to a maintenance shell. However, if
|
or Busybox), you will be given a root login to a maintenance shell.
|
||||||
`sulogin` is missing, the file `/lib/finit/rescue.conf` is read and
|
However, if `sulogin` is missing, the file `/lib/finit/rescue.conf`
|
||||||
the system booted in a limited fallback mode. See [config.md][]
|
is read and the system booted in a limited fallback mode.
|
||||||
for more information.
|
|
||||||
|
|
||||||
This option can be disabled with `configure --without-rescue`
|
This option can be disabled with `configure --without-rescue`
|
||||||
|
|
||||||
@@ -116,5 +115,5 @@ The `bool` setting is one of `on, off, true false, 1, 0`.
|
|||||||
|
|
||||||
For more on kernel boot parameters, see the man page [bootparam(7)][].
|
For more on kernel boot parameters, see the man page [bootparam(7)][].
|
||||||
|
|
||||||
[config.md]: config.md#rescue-mode
|
[rescue]: config/rescue.md
|
||||||
[bootparam(7)]: https://www.man7.org/linux/man-pages/man7/bootparam.7.html
|
[bootparam(7)]: https://www.man7.org/linux/man-pages/man7/bootparam.7.html
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
Rebooting & Halting
|
||||||
|
===================
|
||||||
|
|
||||||
|
Traditionally, rebooting and halting a UNIX system is done by switching
|
||||||
|
to the corresponding runlevel (0 or 6). Over time this has changed and
|
||||||
|
Finit comes with its own tooling providing: `shutdown`, `reboot`,
|
||||||
|
`poweroff`, and `suspend`. These commands are also available from the
|
||||||
|
[`initctl`](initctl.md) tool.
|
||||||
|
|
||||||
|
For compatibility reasons Finit listens to the same set of signals as
|
||||||
|
BusyBox init. This is not 100% compatible with SysV init, but clearly
|
||||||
|
the more common combination for Finit. For more details, see the
|
||||||
|
[Signal](signals.md) section.
|
||||||
@@ -1,21 +1,8 @@
|
|||||||
Finit Conditions
|
Conditions
|
||||||
================
|
==========
|
||||||
|
|
||||||

|
Conditions were added to Finit in v3 with the intention of providing a
|
||||||
|
mechanism for common synchronization problems. For example:
|
||||||
* [Introduction](#introduction)
|
|
||||||
* [Triggering](#triggering)
|
|
||||||
* [Built-in Conditions](#built-in--conditions)
|
|
||||||
* [Debugging](#debugging)
|
|
||||||
* [Internals](#internals)
|
|
||||||
|
|
||||||
|
|
||||||
Introduction
|
|
||||||
------------
|
|
||||||
|
|
||||||
Conditions are a relatively new addition to Finit, introduced in v3,
|
|
||||||
with the intention of providing a mechanism for common synchronization
|
|
||||||
problems. For example:
|
|
||||||
|
|
||||||
- *"wait for service A to start before starting service B"*, or
|
- *"wait for service A to start before starting service B"*, or
|
||||||
- *"wait for basic network access to be available"*
|
- *"wait for basic network access to be available"*
|
||||||
@@ -89,7 +76,8 @@ User-defined conditions are controlled using the `initctl cond set` and
|
|||||||
|
|
||||||
The purpose of user-defined conditions is to be able to start or stop
|
The purpose of user-defined conditions is to be able to start or stop
|
||||||
services, or run/task jobs, on external site-dependent stimuli.
|
services, or run/task jobs, on external site-dependent stimuli.
|
||||||
Example:
|
|
||||||
|
**Example:**
|
||||||
|
|
||||||
service [2345] <usr/foo> alarm --arg foo -- Foo alarm
|
service [2345] <usr/foo> alarm --arg foo -- Foo alarm
|
||||||
|
|
||||||
@@ -277,6 +265,8 @@ A condition is always in one of three states:
|
|||||||
All conditions that have not explicitly been set are interpreted as
|
All conditions that have not explicitly been set are interpreted as
|
||||||
being in the `off` state.
|
being in the `off` state.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
When a reconfiguration is requested, Finit transitions all conditions to
|
When a reconfiguration is requested, Finit transitions all conditions to
|
||||||
the `flux` state. As a result, services that depend on a condition are
|
the `flux` state. As a result, services that depend on a condition are
|
||||||
sent `SIGSTOP`. Once the new state of the condition is asserted, the
|
sent `SIGSTOP`. Once the new state of the condition is asserted, the
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
docsdir := @docdir@/doc/config
|
||||||
|
dist_docs_DATA = cgroups.md env.md files.md index.md limitations.md \
|
||||||
|
logging.md rescue.md runlevels.md runparts.md \
|
||||||
|
service-env.md service-opts.md service-sync.md \
|
||||||
|
service-wrappers.md services.md sysv.md \
|
||||||
|
task-and-run.md templating.md tty.md
|
||||||
@@ -0,0 +1,65 @@
|
|||||||
|
There are three major cgroup configuration directives:
|
||||||
|
|
||||||
|
1. Global top-level group: `init`, `system`, `user`, or a custom group
|
||||||
|
2. Selecting a top-level group for a set of run/task/services
|
||||||
|
3. Per run/task/service limits
|
||||||
|
|
||||||
|
> [!NOTE]
|
||||||
|
> Linux cgroups and details surrounding values are not explained in the
|
||||||
|
> Finit documentation. The Linux admin-guide cover this well:
|
||||||
|
> <https://www.kernel.org/doc/html/latest/admin-guide/cgroup-v2.html>
|
||||||
|
|
||||||
|
Top-level Group Configuration
|
||||||
|
-----------------------------
|
||||||
|
|
||||||
|
# Top-level cgroups and their default settings. All groups mandatory
|
||||||
|
# but more can be added, max 8 groups in total currently. The cgroup
|
||||||
|
# 'root' is also available, reserved for RT processes. Settings are
|
||||||
|
# as-is, only one shorthand 'mem.' exists, other than that it's the
|
||||||
|
# cgroup v2 controller default names.
|
||||||
|
cgroup init cpu.weight:100
|
||||||
|
cgroup user cpu.weight:100
|
||||||
|
cgroup system cpu.weight:9800
|
||||||
|
|
||||||
|
Adding an extra cgroup `maint/` will require you to adjust the weight of
|
||||||
|
the above three. We leave `init/` and `user/` as-is reducing weight of
|
||||||
|
`system/` to 9700.
|
||||||
|
|
||||||
|
cgroup system cpu.weight:9700
|
||||||
|
|
||||||
|
# Example extra cgroup 'maint'
|
||||||
|
cgroup maint cpu.weight:100
|
||||||
|
|
||||||
|
By default, the `system/` cgroup is selected for almost everything. The
|
||||||
|
`init/` cgroup is reserved for PID 1 itself and its closest relatives.
|
||||||
|
The `user/` cgroup is for local TTY logins spawned by getty.
|
||||||
|
|
||||||
|
Selecting Cgroups
|
||||||
|
------------------
|
||||||
|
|
||||||
|
To select a different top-level cgroup, e.g. `maint/`, one can either
|
||||||
|
define it for a group of run/task/service directives in a `.conf` or per
|
||||||
|
each stanza:
|
||||||
|
|
||||||
|
cgroup.maint
|
||||||
|
service [...] <...> /path/to/foo args -- description
|
||||||
|
service [...] <...> /path/to/bar args -- description
|
||||||
|
|
||||||
|
or
|
||||||
|
|
||||||
|
service [...] <...> cgroup.maint /path/to/foo args -- description
|
||||||
|
|
||||||
|
The latter form also allows per-stanza limits on the form:
|
||||||
|
|
||||||
|
service [...] <...> cgroup.maint:cpu.max:10000,mem.max:655360 /path/to/foo args -- description
|
||||||
|
|
||||||
|
Notice the comma separation and the `mem.` exception to the rule: every
|
||||||
|
cgroup setting maps directly to cgroup v2 syntax. I.e., `cpu.max` maps
|
||||||
|
to the file `/sys/fs/cgroup/maint/foo/cpu.max`. There is no filtering,
|
||||||
|
except for expanding the shorthand `mem.` to `memory.`, if the file is
|
||||||
|
not available, either the cgroup controller is not available in your
|
||||||
|
Linux kernel, or the name is misspelled.
|
||||||
|
|
||||||
|
A daemon using `SCHED_RR` currently need to run outside the default cgroups.
|
||||||
|
|
||||||
|
service [...] <...> cgroup.root /path/to/daemon arg -- Real-Time process
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
Environment Variables
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
In Finit v4.3 support for setting environment variables in `finit.conf`,
|
||||||
|
and any `*.conf`, was added. It is worth noting that these are global
|
||||||
|
and *shared with all* services -- the only way to have a service-local
|
||||||
|
environment is detailed in [Services Environment](service-env.md).
|
||||||
|
|
||||||
|
The syntax for global environment variables is straight forward. In
|
||||||
|
Finit v4.4 the `set` keyword was added for completeness, but the old
|
||||||
|
syntax (without the `set ` prefix) is still honored:
|
||||||
|
|
||||||
|
set foo=bar
|
||||||
|
set baz="qux"
|
||||||
|
|
||||||
|
On reload of .conf files, all tracked environment variables are cleared
|
||||||
|
so if `foo=bar` is removed from `finit.conf`, or any `finit.d/*.conf`
|
||||||
|
file, it will no longer be used by Finit or any new (!) started
|
||||||
|
run/tasks or services. The environment of already started processes can
|
||||||
|
not be changed.
|
||||||
|
|
||||||
|
The only variables reset to sane defaults on .conf reload are:
|
||||||
|
|
||||||
|
PATH=_PATH_STDPATH
|
||||||
|
SHELL=_PATH_BSHELL
|
||||||
|
LOGNAME=root
|
||||||
|
USER=root
|
||||||
|
|
||||||
|
It is entirely possible to override these as well from the .conf files,
|
||||||
|
but be careful. Changing SHELL changes the behavior of `system()` and a
|
||||||
|
lot of other commands as well.
|
||||||
@@ -0,0 +1,208 @@
|
|||||||
|
Files & Layout
|
||||||
|
==============
|
||||||
|
|
||||||
|
Originally Finit was configured using a single file, `/etc/finit.conf`,
|
||||||
|
and although still possible to use a single configuration file, today
|
||||||
|
the following layout is recommended:
|
||||||
|
|
||||||
|
/
|
||||||
|
|- etc/
|
||||||
|
| |- finit.d/
|
||||||
|
| | |- available/
|
||||||
|
| | | `- my-service.conf
|
||||||
|
| : |- enabled/
|
||||||
|
| : | `- my-service.conf -> ../available/my-service.conf
|
||||||
|
| : :
|
||||||
|
| : |- static-service.conf
|
||||||
|
| : `- another-static.conf
|
||||||
|
| :
|
||||||
|
| `- finit.conf
|
||||||
|
|- lib
|
||||||
|
| `- finit/
|
||||||
|
| `- system/
|
||||||
|
| |- 10-hotplug.conf
|
||||||
|
| `- ...
|
||||||
|
`- run/
|
||||||
|
`- finit/
|
||||||
|
`- system/
|
||||||
|
|- dbus.conf
|
||||||
|
|- keventd.conf
|
||||||
|
|- runparts.conf
|
||||||
|
|- watchdogd.conf
|
||||||
|
`- ...
|
||||||
|
|
||||||
|
Configuration files in `/etc` are provided by the user, or projects like
|
||||||
|
[finit-skel](https://github.com/troglobit/finit-skel) and extended by
|
||||||
|
the user.
|
||||||
|
|
||||||
|
The files in `/lib/finit/system/*.conf` are system critical services and
|
||||||
|
setup provided by Finit, e.g. udev/mdev that must run very early at system
|
||||||
|
bootstrap. This system directory was introduced in Finit v4.4 to replace
|
||||||
|
the hard-coded services provided by plugins before. All .conf files in this
|
||||||
|
directory be either replaced by a system administrator or overridden by a
|
||||||
|
file with the same name in `/etc/finit.d/`.
|
||||||
|
|
||||||
|
The files in `/run/finit/system/*.conf` are created by plugins and Finit
|
||||||
|
bundled services like runparts, [watchdog](../watchdog.md), and
|
||||||
|
[`keventd`](../keventd.md) if they are enabled. Like
|
||||||
|
`/lib/finit/system/*.conf`, these files can be overridden by file with
|
||||||
|
the same name in `/etc/finit.d/`.
|
||||||
|
|
||||||
|
Services in the `available/` and `enabled/` sub-directories are called
|
||||||
|
dynamic services, in contrast to static services -- the only difference
|
||||||
|
being where they are installed and if the `initctl` tool can manage them
|
||||||
|
with the `enable` and `disable` commands. An administrator can always
|
||||||
|
create files and symlinks manually.
|
||||||
|
|
||||||
|
At bootstrap, and `initctl reload`, all .conf files are read, starting
|
||||||
|
with `finit.conf`, then `/lib/finit/system/*.conf`, `finit.d/*.conf`,
|
||||||
|
and finally all `finit.d/enabled/*.conf` files. Each directory is a
|
||||||
|
unique group, where files within each group are sorted alphabetically.
|
||||||
|
|
||||||
|
**Example:**
|
||||||
|
|
||||||
|
/lib/finit/system/10-hotplug.conf
|
||||||
|
/lib/finit/system/90-testserv.conf
|
||||||
|
/run/finit/system/dbus.conf
|
||||||
|
/run/finit/system/runparts.conf
|
||||||
|
/etc/finit.d/10-abc.conf
|
||||||
|
/etc/finit.d/20-abc.conf
|
||||||
|
/etc/finit.d/enabled/1-aaa.conf
|
||||||
|
/etc/finit.d/enabled/1-abc.conf
|
||||||
|
|
||||||
|
The resulting combined configuration is read line by line, each `run`,
|
||||||
|
`task`, and `service` added to an ordered list that ensures they are
|
||||||
|
started in the same order. This is important because of the blocking
|
||||||
|
properties of the `run` statement. For an example on the relation of
|
||||||
|
`service` and `run` statements, and dependency handling between them,
|
||||||
|
see [Conditional Loading](services.md#conditional-loading), below.
|
||||||
|
|
||||||
|
> [!NOTE]
|
||||||
|
> 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`.
|
||||||
|
>
|
||||||
|
> They can also be overridden from the [kernel command line](../cmdline.md)
|
||||||
|
> using: `-- finit.config=/etc/bar.conf` and in that file use the
|
||||||
|
> top-level configuration directive `rcsd /path/to/finit.d`.
|
||||||
|
|
||||||
|
Filesystem Layout
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
Finit is most comfortable with a traditional style Linux filesystem
|
||||||
|
layout, as specified in the [FHS][]:
|
||||||
|
|
||||||
|
/.
|
||||||
|
|- bin/
|
||||||
|
|- dev/ # Mounted automatically if devtmpfs is available
|
||||||
|
| |- pts/ # Mounted automatically by Finit if it exists
|
||||||
|
| `- shm/ # Mounted automatically by Finit if it exists
|
||||||
|
|- etc/
|
||||||
|
| |- finit.d/
|
||||||
|
| | |- available/
|
||||||
|
| | `- enabled/
|
||||||
|
| `- finit.conf
|
||||||
|
|- home/
|
||||||
|
|- lib/
|
||||||
|
|- libexec/
|
||||||
|
|- mnt/
|
||||||
|
|- proc/ # Mounted automatically by Finit if it exists
|
||||||
|
|- root/
|
||||||
|
|- run/ # Mounted automatically by Finit if it exists
|
||||||
|
| `- lock/ # Created automatically if Finit mounts /run
|
||||||
|
|- sbin/
|
||||||
|
|- sys/ # Mounted automatically by Finit if it exists
|
||||||
|
|- tmp/ # Mounted automatically by Finit if it exists
|
||||||
|
|- usr/
|
||||||
|
`- var/
|
||||||
|
|- cache/
|
||||||
|
|- db/
|
||||||
|
|- lib/
|
||||||
|
| `- misc/
|
||||||
|
|- lock/
|
||||||
|
|- log/
|
||||||
|
|- run -> ../run
|
||||||
|
|- spool/
|
||||||
|
`- tmp/
|
||||||
|
|
||||||
|
Finit starts by mounting the critical file systems `/dev`, `/proc/`, and
|
||||||
|
`/sys`, unless they are already mounted. When all plugins and other,
|
||||||
|
core Finit functions, have been set up, all relevant filesystems (where
|
||||||
|
`PASS > 0`) are checked and mounted from the selected `fstab`, either
|
||||||
|
the default `/etc/fstab`, or any custom one selected from the command
|
||||||
|
line, or at build time.
|
||||||
|
|
||||||
|
To provide a smooth ride, file system not listed in the given `fstab`,
|
||||||
|
e.g. `/tmp` and `/run`, are automatically mounted by Finit, as listed
|
||||||
|
above, provided their respective mount point exists.
|
||||||
|
|
||||||
|
With all filesystems mounted, Finit calls `swapon`.
|
||||||
|
|
||||||
|
> [!TIP]
|
||||||
|
> To see what happens when all filesystems are mounted, have a look at
|
||||||
|
> the [`bootmisc.so` plugin](../plugins.md).
|
||||||
|
|
||||||
|
At shutdown, and after having stopped all services and other lingering
|
||||||
|
processes have been killed, filesystems are unmounted in the reverse
|
||||||
|
order, and `swapoff` is called.
|
||||||
|
|
||||||
|
[FHS]: https://refspecs.linuxfoundation.org/FHS_3.0/fhs/index.html
|
||||||
|
|
||||||
|
Managing Services
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
Using `initctl disable my-service` the symlink (above) is removed and
|
||||||
|
the service is queued for removal. Several changes can be made to the
|
||||||
|
system, but it is not until `initctl reload` is called that the changes
|
||||||
|
are activated.
|
||||||
|
|
||||||
|
To add a new static service, drop a `.conf` file in `/etc/finit.d/` and
|
||||||
|
run `initctl reload`. (It is also possible to `SIGHUP` PID 1, or call
|
||||||
|
`finit q`, but that has been deprecated with the `initctl` tool). Finit
|
||||||
|
monitors all known active `.conf` files, so if you want to force a
|
||||||
|
restart of any service you can touch its corresponding `.conf` file in
|
||||||
|
`/etc/finit.d` and call `initctl reload`. Finit handles all conditions
|
||||||
|
and dependencies between services automatically, see the section on
|
||||||
|
[Service Synchronization](service-sync.md) for more details.
|
||||||
|
|
||||||
|
On `initctl reload` the following is checked for all services:
|
||||||
|
|
||||||
|
- If a service's `.conf` file has been removed, or its conditions are no
|
||||||
|
longer satisfied, the service is stopped.
|
||||||
|
- If the file is modified, or a service it depends on has been reloaded,
|
||||||
|
the service is reloaded (stopped and started).
|
||||||
|
- If a new service is added it is automatically started — respecting
|
||||||
|
runlevels and return values from any callbacks.
|
||||||
|
|
||||||
|
For more info on the different states of a service, see the separate
|
||||||
|
document [Finit Services](../service.md).
|
||||||
|
|
||||||
|
Alternate finit.d/
|
||||||
|
------------------
|
||||||
|
|
||||||
|
**Syntax:** `rcsd /path/to/finit.d`
|
||||||
|
|
||||||
|
The Finit rcS.d directory is set at compile time with:
|
||||||
|
|
||||||
|
./configure --with-rcsd=/etc/finit.d
|
||||||
|
|
||||||
|
A system with multiple use-cases may be bootstrapped with different
|
||||||
|
configurations, starting with the kernel command line option:
|
||||||
|
|
||||||
|
-- finit.config=/etc/factory.conf
|
||||||
|
|
||||||
|
This file in turn can use the `rcsd` directive to tell Finit to use
|
||||||
|
another set of .conf files, e.g.:
|
||||||
|
|
||||||
|
rcsd /etc/factory.d
|
||||||
|
|
||||||
|
> [!NOTE]
|
||||||
|
> This directive is only available from the top-level bootstrap .conf
|
||||||
|
> file, usually `/etc/finit.conf`.
|
||||||
|
|
||||||
|
Including Finit Configs
|
||||||
|
------------------------
|
||||||
|
|
||||||
|
**Syntax:** `include <CONF>`
|
||||||
|
|
||||||
|
Include another configuration file. Absolute path required.
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
This section provides an overview of Finit's configuration system. For
|
||||||
|
detailed information on specific topics, see the individual sections in
|
||||||
|
the navigation menu.
|
||||||
|
|
||||||
|
|
||||||
|
Configuration File Syntax
|
||||||
|
--------------------------
|
||||||
|
|
||||||
|
The file format is line based, empty lines and comments, lines starting
|
||||||
|
with `#`, are ignored. A configuration directive starts with a keyword
|
||||||
|
followed by a space and the rest of the line is treated as the value.
|
||||||
|
|
||||||
|
As of Finit v4.4, configuration directives can be broken up in multiple
|
||||||
|
lines using the continuation character `\`, and trailing comments are
|
||||||
|
also allowed. Example:
|
||||||
|
|
||||||
|
```aconf
|
||||||
|
# Escape \# chars if you want them literal in, e.g., descriptions
|
||||||
|
service name:sysklogd [S123456789] \
|
||||||
|
env:-/etc/default/sysklogd \
|
||||||
|
syslogd -F $SYSLOGD_ARGS \
|
||||||
|
-- System log daemon \# 1 # Comments allowed
|
||||||
|
```
|
||||||
|
|
||||||
|
The .conf files `/etc/finit.conf` and `/etc/finit.d/*` support many
|
||||||
|
directives. Some are restricted, e.g., only available at bootstrap,
|
||||||
|
runlevel `S`. Read on in [Files & Layout](files.md) for more on how
|
||||||
|
to structure your .conf files.
|
||||||
|
|
||||||
|
For details on restrictions, see [Limitations](limitations.md).
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
Limitations
|
||||||
|
===========
|
||||||
|
|
||||||
|
As of Finit v4 there are no limitations to where `.conf` settings can be
|
||||||
|
placed. Except for the system/global `rlimit` and `cgroup` top-level
|
||||||
|
group declarations, which can only be set from `/etc/finit.conf`, since
|
||||||
|
it is the first `.conf` file Finit reads.
|
||||||
|
|
||||||
|
Originally, `/etc/finit.conf` was the only way to set up a Finit system.
|
||||||
|
Today it is mainly used for bootstrap settings like system hostname,
|
||||||
|
early module loading for watchdogd, network bringup and system shutdown.
|
||||||
|
These can now also be set in any `.conf` file in `/etc/finit.d`.
|
||||||
|
|
||||||
|
There is, however, nothing preventing you from having all configuration
|
||||||
|
settings in `/etc/finit.conf`.
|
||||||
|
|
||||||
|
> [!IMPORTANT]
|
||||||
|
> The default `rcsd`, i.e., `/etc/finit.d`, was previously the Finit
|
||||||
|
> [runparts](runparts.md) directory. Finit >=v4.0 no longer has a
|
||||||
|
> default `runparts` directory, make sure to update your setup, or the
|
||||||
|
> finit configuration, accordingly.
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
General Logging
|
||||||
|
===============
|
||||||
|
|
||||||
|
**Syntax:** `log size:200k count:5`
|
||||||
|
|
||||||
|
Log rotation for run/task/services using the `log` sub-option with
|
||||||
|
redirection to a log file. Global setting, applies to all services.
|
||||||
|
|
||||||
|
The size can be given as bytes, without a specifier, or in `k`, `M`,
|
||||||
|
or `G`, e.g. `size:10M`, or `size:3G`. A value of `size:0` disables
|
||||||
|
log rotation. The default is `200k`.
|
||||||
|
|
||||||
|
The count value is recommended to be between 1-5, with a default 5.
|
||||||
|
Setting count to 0 means the logfile will be truncated when the MAX
|
||||||
|
size limit is reached.
|
||||||
|
|
||||||
|
Redirecting Output
|
||||||
|
------------------
|
||||||
|
|
||||||
|
The `run`, `task`, and `service` stanzas also allow the keyword `log` to
|
||||||
|
redirect `stderr` and `stdout` of the application to a file or syslog
|
||||||
|
using the native `logit` tool. This is useful for programs that do not
|
||||||
|
support syslog on their own, which is sometimes the case when running
|
||||||
|
in the foreground.
|
||||||
|
|
||||||
|
The full syntax is:
|
||||||
|
|
||||||
|
log:/path/to/file
|
||||||
|
log:prio:facility.level,tag:ident
|
||||||
|
log:console
|
||||||
|
log:null
|
||||||
|
log
|
||||||
|
|
||||||
|
Default `prio` is `daemon.info` and default `tag` is the basename of the
|
||||||
|
service or run/task command.
|
||||||
|
|
||||||
|
Log rotation is controlled using the global `log` setting.
|
||||||
|
|
||||||
|
**Example:**
|
||||||
|
|
||||||
|
service log:prio:user.warn,tag:ntpd /sbin/ntpd pool.ntp.org -- NTP daemon
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
Rescue Mode
|
||||||
|
===========
|
||||||
|
|
||||||
|
Finit supports a rescue mode which is activated by the `rescue` option
|
||||||
|
on the kernel command line. See [cmdline docs](../cmdline.md) for how to
|
||||||
|
activate it.
|
||||||
|
|
||||||
|
This rescue mode can be disabled at configure time using:
|
||||||
|
|
||||||
|
configure --without-rescue
|
||||||
|
|
||||||
|
The rescue mode comes in two flavors; *traditional* and *fallback*.
|
||||||
|
|
||||||
|
> [!NOTE]
|
||||||
|
> In this mode `initctl` will not work. Use the `-f` flag to force
|
||||||
|
> `reboot`, `shutdown`, or `poweroff`.
|
||||||
|
|
||||||
|
Traditional
|
||||||
|
-----------
|
||||||
|
|
||||||
|
This is what most users expect. A very early maintenance login prompt,
|
||||||
|
served by the system `sulogin` program from util-linux, or BusyBox. If
|
||||||
|
that is not found in `$PATH`, the bundled `/libexec/finit/sulogin`
|
||||||
|
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
|
||||||
|
normally.
|
||||||
|
|
||||||
|
> [!WARNING]
|
||||||
|
> The bundled sulogin in Finit can at configure time be given another
|
||||||
|
> user than the default (root). If the sulogin user does not have a
|
||||||
|
> password, or __the account is locked__, the user is presented with a
|
||||||
|
> prompt: `"Press enter to enter maintenance mode."`, which will open
|
||||||
|
> up a root shell *without prompting for password*!
|
||||||
|
|
||||||
|
Fallback
|
||||||
|
--------
|
||||||
|
|
||||||
|
If no `sulogin` program is found, Finit tries to bring up as much of its
|
||||||
|
own functionality as possible, yet limiting many aspects, meaning; no
|
||||||
|
network, no `fsck` of file systems in `/etc/fstab`, no `/etc/rc.local`,
|
||||||
|
no `runparts`, and most plugins are skipped (except those that provide
|
||||||
|
functionality for the condition subsystem).
|
||||||
|
|
||||||
|
Instead of reading `/etc/finit.conf` et al, system configuration is read
|
||||||
|
from `/lib/finit/rescue.conf`, which can be freely modified by the
|
||||||
|
system administrator.
|
||||||
|
|
||||||
|
The bundled default `rescue.conf` contains nothing more than:
|
||||||
|
|
||||||
|
runlevel 1
|
||||||
|
tty [12345] rescue
|
||||||
|
|
||||||
|
The `tty` has the `rescue` option set, which works similar to the board
|
||||||
|
bring-up tty option `notty`. The major difference being that `sulogin`
|
||||||
|
is started to query for root/admin password. If `sulogin` is not found,
|
||||||
|
`rescue` behaves like `notty` and gives a plain root shell prompt.
|
||||||
|
|
||||||
|
If Finit cannot find `/lib/finit/rescue.conf` it defaults to:
|
||||||
|
|
||||||
|
tty [12345] rescue
|
||||||
|
|
||||||
|
There is no way to exit the *fallback* rescue mode.
|
||||||
@@ -0,0 +1,168 @@
|
|||||||
|
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
|
||||||
|
- ` 1`: Single user mode
|
||||||
|
- `2-5`: traditional multi-user mode
|
||||||
|
- ` 6`: reboot
|
||||||
|
- `7-9`: multi-user mode (extra)
|
||||||
|
- ` 0`: shutdown
|
||||||
|
|
||||||
|
Runlevel S (bootStrap), is for tasks supposed to run once at boot, and
|
||||||
|
services like `syslogd`, which need to start early and run throughout
|
||||||
|
the lifetime of your system.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
task [S] /lib/console-setup/console-setup.sh
|
||||||
|
service [S12345] env:-/etc/default/rsyslog rsyslogd -n $RSYSLOGD_ARGS
|
||||||
|
|
||||||
|
When bootstrap has completed, Finit moves to runlevel 2. This can be
|
||||||
|
changed in `/etc/finit.conf` using the `runlevel N` directive, or by a
|
||||||
|
script running in runlevel S that calls, e.g., `initctl runlevel 9`.
|
||||||
|
The latter is useful if startup scripts detect problems outside of
|
||||||
|
Finit's control, e.g., critical services/devices missing or hardware
|
||||||
|
problems.
|
||||||
|
|
||||||
|
Each runlevel must be allowed to "complete". Meaning, all services in
|
||||||
|
runlevel S must have started and all run/tasks have been started and
|
||||||
|
collected (exited). Finit waits 120 seconds for all run/tasks in S to
|
||||||
|
complete before proceeding to 2.
|
||||||
|
|
||||||
|
Finit first stops everything that is not allowed to run in 2, and then
|
||||||
|
brings up networking. Networking is expected to be available in all
|
||||||
|
runlevels except: S, 1 (single user level), 6, and 0. Networking is
|
||||||
|
enabled either by the `network script` directive, or if you have an
|
||||||
|
`/etc/network/interfaces` file, Finit calls `ifup -a` -- at the very
|
||||||
|
least the loopback interface is brought up.
|
||||||
|
|
||||||
|
> [!NOTE]
|
||||||
|
> When moving from runlevel S to 2, all run/task/services that were
|
||||||
|
> constrained to runlevel S only are dropped from bookkeeping. So 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.
|
||||||
|
|
||||||
|
Runlevel Configuration
|
||||||
|
----------------------
|
||||||
|
|
||||||
|
**Syntax:** `runlevel <N>`
|
||||||
|
|
||||||
|
The system runlevel to go to after bootstrap (S) has completed. `N` is
|
||||||
|
the runlevel number 0-9, where 6 is reserved for reboot and 0 for 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
|
||||||
|
Finit disables networking in this mode.
|
||||||
|
|
||||||
|
*Default:* 2
|
||||||
|
|
||||||
|
> [!NOTE]
|
||||||
|
> Only read and executed in runlevel S (bootstrap).
|
||||||
|
|
||||||
|
Networking
|
||||||
|
----------
|
||||||
|
|
||||||
|
**Syntax:** `network <PATH>`
|
||||||
|
|
||||||
|
Script or program to bring up networking, with optional arguments.
|
||||||
|
|
||||||
|
Deprecated. We recommend using dedicated task/run stanzas per runlevel,
|
||||||
|
or `/etc/network/interfaces` if you have a system with `ifupdown`, like
|
||||||
|
Debian, Ubuntu, Linux Mint, or an embedded BusyBox system.
|
||||||
|
|
||||||
|
> [!NOTE]
|
||||||
|
> Only read and executed in runlevel S (bootstrap).
|
||||||
|
|
||||||
|
System Hostname
|
||||||
|
---------------
|
||||||
|
|
||||||
|
**Syntax:** `host <NAME>`, or `hostname <NAME>`
|
||||||
|
|
||||||
|
Set system hostname to NAME, unless `/etc/hostname` exists in which case
|
||||||
|
the contents of that file is used.
|
||||||
|
|
||||||
|
Deprecated. We recommend using `/etc/hostname` instead.
|
||||||
|
|
||||||
|
> [!NOTE]
|
||||||
|
> Only read and executed in runlevel S (bootstrap).
|
||||||
|
|
||||||
|
Kernel Modules
|
||||||
|
--------------
|
||||||
|
|
||||||
|
**Syntax:** `module <MODULE> [ARGS]`
|
||||||
|
|
||||||
|
Load a kernel module, with optional arguments. Similar to `insmod`
|
||||||
|
command line tool.
|
||||||
|
|
||||||
|
Deprecated, there is both a `modules-load.so` and a `modprobe.so` plugin
|
||||||
|
that can handle module loading better. The former supports loading from
|
||||||
|
`/etc/modules-load.d/`, the latter uses kernel modinfo to automatically
|
||||||
|
load (or coldplug) every required module. For hotplug we recommend the
|
||||||
|
BusyBox mdev tool, add to `/etc/mdev.conf`:
|
||||||
|
|
||||||
|
$MODALIAS=.* root:root 0660 @modprobe -b "$MODALIAS"
|
||||||
|
|
||||||
|
> [!NOTE]
|
||||||
|
> Only read and executed in runlevel S (bootstrap).
|
||||||
|
|
||||||
|
Resource Limits
|
||||||
|
---------------
|
||||||
|
|
||||||
|
**Syntax:** `rlimit [hard|soft] RESOURCE <LIMIT|unlimited>`
|
||||||
|
|
||||||
|
Set the hard or soft limit for a resource, or both if that argument is
|
||||||
|
omitted. `RESOURCE` is the lower-case `RLIMIT_` string constants from
|
||||||
|
`setrlimit(2)`, without prefix. E.g. to set `RLIMIT_CPU`, use `cpu`.
|
||||||
|
|
||||||
|
LIMIT is an integer that depends on the resource being modified, see
|
||||||
|
the man page, or the kernel `/proc/PID/limits` file, for details.
|
||||||
|
Finit versions before v3.1 used `infinity` for `unlimited`, which is
|
||||||
|
still supported, albeit deprecated.
|
||||||
|
|
||||||
|
# No process is allowed more than 8MB of address space
|
||||||
|
rlimit hard as 8388608
|
||||||
|
|
||||||
|
# Core dumps may be arbitrarily large
|
||||||
|
rlimit soft core infinity
|
||||||
|
|
||||||
|
# CPU limit for all services, soft & hard = 10 sec
|
||||||
|
rlimit cpu 10
|
||||||
|
|
||||||
|
`rlimit` can be set globally, in `/etc/finit.conf`, or locally per
|
||||||
|
each `/etc/finit.d/*.conf` read. I.e., a set of task/run/service
|
||||||
|
stanzas can share the same rlimits if they are in the same .conf.
|
||||||
|
|
||||||
|
Miscellaneous Settings
|
||||||
|
----------------------
|
||||||
|
|
||||||
|
**Syntax:** `reboot-delay <0-60>`
|
||||||
|
|
||||||
|
Optional delay at reboot (or shutdown or halt) to allow kernel
|
||||||
|
filesystem threads to complete after calling `sync(2)` before
|
||||||
|
rebooting. This applies primarily to filesystems that do not
|
||||||
|
have a reboot notifier implemented. At the point of writing,
|
||||||
|
the only known filesystems affected are: ubifs, jffs2.
|
||||||
|
|
||||||
|
*Default:* 0 (disabled)
|
||||||
|
|
||||||
|
When enabled (non-zero), this delay runs after file systems have been
|
||||||
|
unmounted and the root filesystem has been remounted read-only, and
|
||||||
|
sync(2) has been called, twice.
|
||||||
|
|
||||||
|
> "On Linux, sync is only guaranteed to schedule the dirty blocks for
|
||||||
|
> writing; it can actually take a short time before all the blocks are
|
||||||
|
> finally written.
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
Run-parts Scripts
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
**Syntax:** `runparts [progress] [sysv] <DIR>`
|
||||||
|
|
||||||
|
Call [run-parts(8)][] on `DIR` to run start scripts. All executable
|
||||||
|
files in the directory are called, in alphabetic order. The scripts in
|
||||||
|
this directory are executed at the very end of runlevel `S`.
|
||||||
|
|
||||||
|
A common use-case for runparts scripts is to create and enable/disable
|
||||||
|
services, which Finit will then apply when changing runlevel from S to
|
||||||
|
whatever the next runlevel is set to be (default 2). E.g., generate a
|
||||||
|
`/etc/chrony.conf` and call `initctl enable chronyd`.
|
||||||
|
|
||||||
|
**Options:**
|
||||||
|
|
||||||
|
- `progress`: display the progress of each script being executed
|
||||||
|
- `sysv`: run only SysV style scripts, i.e., `SNNfoo`, or `KNNbar`,
|
||||||
|
where `NN` is a number (0-99).
|
||||||
|
|
||||||
|
If global debug mode is enabled, the `runparts` program is also called
|
||||||
|
with the debug flag.
|
||||||
|
|
||||||
|
**Limitations:**
|
||||||
|
|
||||||
|
Scripts called from `runparts`, or hook scripts (see below), are limited
|
||||||
|
in their interaction with Finit. Like the standalone `run` stanza and
|
||||||
|
the `/etc/rc.local` shell script, Finit waits for their completion
|
||||||
|
before continuing. None of them can issue commands to start, stop, or
|
||||||
|
restart other services. Also, ensure all your services and programs
|
||||||
|
either terminate or start in the background or you will block Finit.
|
||||||
|
|
||||||
|
> [!NOTE]
|
||||||
|
> `runparts` 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.
|
||||||
|
|
||||||
|
**Recommendations:**
|
||||||
|
|
||||||
|
It can be beneficial to use `01-name`, `02-othername`, etc., to ensure
|
||||||
|
the scripts are started in that order, e.g., if there is a dependency
|
||||||
|
order between scripts. Symlinks to existing daemons can talso be used,
|
||||||
|
but make sure they daemonize (background) themselves properly, otherwise
|
||||||
|
Finit will lock up.
|
||||||
|
|
||||||
|
If `S[0-9]foo` and `K[0-9]bar` style naming is used, the executable will
|
||||||
|
be called with an extra argument, `start` and `stop`, respectively.
|
||||||
|
E.g., `S01foo` will be called as `S01foo start`. Of course, `S01foo`
|
||||||
|
and `K01foo` may be a symlink to to `another/directory/foo`.
|
||||||
|
|
||||||
|
[run-parts(8)]: http://manpages.debian.org/cgi-bin/man.cgi?query=run-parts
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
Service Environment
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
Finit supports sourcing environment variables from `/etc/default/*`, or
|
||||||
|
similar `--with-sysconfig=DIR`. This is a common pattern from SysV init
|
||||||
|
scripts, where the start-stop script is a generic script for the given
|
||||||
|
service, `foo`, and the options for the service are sourced from the
|
||||||
|
file `/etc/default/foo`. Like this:
|
||||||
|
|
||||||
|
* `/etc/default/foo`:
|
||||||
|
|
||||||
|
FOO_OPTIONS=--extra-arg="bar" -s -x
|
||||||
|
|
||||||
|
* `/etc/finit.conf`:
|
||||||
|
|
||||||
|
service [2345] env:-/etc/default/foo foo -n $FOO_OPTIONS -- Example foo daemon
|
||||||
|
|
||||||
|
Here the service `foo` is started with `-n`, to make sure it runs in the
|
||||||
|
foreground, and the with the options found in the environment file. With
|
||||||
|
the `ps` command we can see that the process is started with:
|
||||||
|
|
||||||
|
foo -n --extra-arg=bar -s -x
|
||||||
|
|
||||||
|
> [!NOTE]
|
||||||
|
> The leading `-` in `env:` determines if Finit should treat a missing
|
||||||
|
> environment file as blocking the start of the service or not. When
|
||||||
|
> `-` is used, a missing environment file does *not* block the start.
|
||||||
@@ -0,0 +1,134 @@
|
|||||||
|
Service Options
|
||||||
|
===============
|
||||||
|
|
||||||
|
The run/task/tty/service/sysv directives take modifiers, or options, to
|
||||||
|
control their behavior. This section lists them with their limitations.
|
||||||
|
All modifiers must be placed between the directive and its command.
|
||||||
|
|
||||||
|
The name of a service, shown by the `initctl` tool, defaults to the
|
||||||
|
basename of the service executable. It can be changed with the `name:`
|
||||||
|
option:
|
||||||
|
|
||||||
|
name:<service-name>
|
||||||
|
|
||||||
|
For multiple instances of a service, with the same `name`, set the
|
||||||
|
identifier `:ID` to prevent Finit from replacing previous instances:
|
||||||
|
|
||||||
|
service name:ssdp :eth1 ssdpd eth1 -- Windows discovery on eth1
|
||||||
|
service name:ssdp :eth2 ssdpd eth2 -- Windows discovery on eth2
|
||||||
|
|
||||||
|
The [`initctl`](../initctl.md) tool will list these two services as:
|
||||||
|
|
||||||
|
- ssdp:eth1
|
||||||
|
- ssdp:eth2
|
||||||
|
|
||||||
|
Conflicting services that must be prevented from starting, use the
|
||||||
|
`conflict:` option:
|
||||||
|
|
||||||
|
service [S12345789] udevd -- Device event management daemon
|
||||||
|
run [S] conflict:udevd mdev -s -- Populating device tree
|
||||||
|
|
||||||
|
Multiple conflicting services can be separated using `,`:
|
||||||
|
|
||||||
|
service :1 abc
|
||||||
|
service :2 abc
|
||||||
|
service conflict:abc:1,abc:2 cde
|
||||||
|
|
||||||
|
If a service should not be automatically started, it can be configured
|
||||||
|
as manual with the optional `manual` argument. The service can then be
|
||||||
|
started at any time by running `initctl start <service>`.
|
||||||
|
|
||||||
|
manual:yes
|
||||||
|
|
||||||
|
Other run/task/service options are:
|
||||||
|
|
||||||
|
* `cgroups:...` -- see the [Cgroups](cgroups.md) section
|
||||||
|
* `env:[-]/path/to/env` -- see the [Service Environment](service-env.md) section
|
||||||
|
* `log:...` -- see [Redirecting Output](logging.md#redirecting-output)
|
||||||
|
* `nowarn` -- see [Conditional Loading](services.md#conditional-loading)
|
||||||
|
* `notify:...` -- see [Service Synchronization](service-sync.md)
|
||||||
|
* `if:...` -- see [Conditional Execution](services.md#conditional-execution)
|
||||||
|
* `type:forking` -- see description of the [service](services.md) directive
|
||||||
|
|
||||||
|
As mentioned previously, services are automatically started, restarted,
|
||||||
|
and stopped, depending on the configuration and conditions. Within the
|
||||||
|
confines of that the following options are available:
|
||||||
|
|
||||||
|
* `restart:NUM` -- number of times Finit tries to restart a crashing
|
||||||
|
service, default: 10, max: 255. When this limit is reached the
|
||||||
|
service is marked *crashed* and must be restarted manually with
|
||||||
|
`initctl restart NAME`
|
||||||
|
* `restart_sec:SEC` -- number of seconds before Finit tries to restart
|
||||||
|
a crashing service, default: 2 seconds for the first five retries,
|
||||||
|
then back-off to 5 seconds. The maximum of this configured value
|
||||||
|
and the above (2 and 5) will be used
|
||||||
|
* `restart:always` -- no upper limit on the number of times Finit
|
||||||
|
tries to restart a crashing service. Same as `restart:-1`
|
||||||
|
* `norestart` -- dont restart on failures, same as `restart:0`
|
||||||
|
* `respawn` -- bypasses the `restart` mechanism completely, allows
|
||||||
|
endless restarts. Useful in many use-cases, but not what `service`
|
||||||
|
was originally designed for so not the default behavior
|
||||||
|
* `oncrash:reboot` -- when all retries have failed, and the service
|
||||||
|
has *crashed*, if this option is set the system is rebooted
|
||||||
|
* `oncrash:script` -- similarly, but instead of rebooting, call the
|
||||||
|
`post:script` action with exit code `crashed`, see below
|
||||||
|
* `reload:'script [args]'` -- some services do not support `SIGHUP` but
|
||||||
|
may have other ways to update the configuration of a running daemon.
|
||||||
|
When `reload:script` is defined it is preferred over `SIGHUP`. Like
|
||||||
|
systemd, Finit sets `$MAINPID` as a convenience to scripts, which in
|
||||||
|
effect also allow `reload:'kill -HUP $MAINPID'`
|
||||||
|
* `stop:'script [args]'` -- some services may require alternate methods
|
||||||
|
to be stopped. If a `stop:script` is defined it is preferred over
|
||||||
|
`SIGTERM` and `stop`, for `service` and `sysv`, respectively.
|
||||||
|
Similar to `reload:script`, Finit sets `$MAINPID`
|
||||||
|
|
||||||
|
> [!CAUTION]
|
||||||
|
> Both `reload:script` and `stop:script` are called as PID 1, without
|
||||||
|
> any timeout! Meaning, it is up to you to ensure the script is not
|
||||||
|
> blocking for seconds at a time or never terminates.
|
||||||
|
|
||||||
|
When stopping a service (run/task/sysv/service), either manually or when
|
||||||
|
moving to another runlevel, Finit starts by sending `SIGTERM`, to allow
|
||||||
|
the process to shut down gracefully (unless a `stop:'script'` is used).
|
||||||
|
However, if the process has not been collected within 3 seconds, Finit
|
||||||
|
will send `SIGKILL`. To stop the process using a different signal than
|
||||||
|
`SIGTERM`, use `halt:SIGNAL`, 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 before sending `SIGKILL`.
|
||||||
|
|
||||||
|
Services, including the `sysv` variant, support pre/post/ready and
|
||||||
|
cleanup scripts:
|
||||||
|
|
||||||
|
* `pre:[0-3600,]script` -- called before the sysv/service is stated
|
||||||
|
* `post:[0-3600,]script` -- called after the sysv/service has stopped
|
||||||
|
* `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
|
||||||
|
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
|
||||||
|
service itself, with any `env:file` sourced. The scripts are executed
|
||||||
|
from the `$HOME` of the given user. The scripts are not called with any
|
||||||
|
argument, but get a set of environment variables:
|
||||||
|
|
||||||
|
* `SERVICE_IDENT=foo:1`
|
||||||
|
* `SERVICE_NAME=foo`
|
||||||
|
* `SERVICE_ID=1`
|
||||||
|
|
||||||
|
The `post:script` is called with an additional set of environment
|
||||||
|
variables. Yes, the text is correct, the naming was an accident:
|
||||||
|
|
||||||
|
- `EXIT_CODE=[exited,signal,crashed]`: normal exit, signaled, or
|
||||||
|
crashed
|
||||||
|
- `EXIT_STATUS=[num,SIGNAME]`: 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
|
||||||
|
|
||||||
|
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]
|
||||||
|
> These script actions are intended for setup, cleanup, and readiness
|
||||||
|
> notification. It is up to the user to ensure the scripts terminate.
|
||||||
@@ -0,0 +1,74 @@
|
|||||||
|
Service Synchronization
|
||||||
|
=======================
|
||||||
|
|
||||||
|
Finit was created for fast booting systems. Faster than a regular SysV
|
||||||
|
Init based system at the time. Early on the need for a guaranteed start
|
||||||
|
order of services (daemons) arose. I.e., service `A` must be guaranteed
|
||||||
|
to have started (and be ready!) before `B`. The model that was chosen
|
||||||
|
to determine this was very simple: PID files.
|
||||||
|
|
||||||
|
Early on in UNIX daemons were controlled with basic IPC like signals,
|
||||||
|
and the way for a user to know that a daemon was ready to respond to
|
||||||
|
signals (minimally having set up its signal handler), was to tell the
|
||||||
|
user;
|
||||||
|
|
||||||
|
> "Hey, you can send signals to me using the PID in this file:
|
||||||
|
> `/var/run/daemon.pid`".
|
||||||
|
|
||||||
|
Since most systems run fairly unchanged after boot, Finit could rely on
|
||||||
|
the PID file for `A` being created before launching `B`. This method
|
||||||
|
has worked well for a long time, and for systems based on Open Source it
|
||||||
|
was easy to either add PID file support to a daemon without support for
|
||||||
|
it, or fix ordering issues (PID file created before signal handler is
|
||||||
|
set up) in existing daemons.
|
||||||
|
|
||||||
|
However, with the advent of other Init systems (Finit is rather old),
|
||||||
|
most notably systemd and s6, other methods for signaling "readiness"
|
||||||
|
arrived and daemons were adapted to these new schemes to a larger
|
||||||
|
extent.
|
||||||
|
|
||||||
|
As of Finit v4.4 partial support for systemd and s6 style readiness
|
||||||
|
notification is available, and the native PID file mode of operation is,
|
||||||
|
as of Finit v4.6 optional, by default it is still enabled, but this can
|
||||||
|
be changed in `finit.conf`:
|
||||||
|
|
||||||
|
readiness none
|
||||||
|
|
||||||
|
This will be made the default in Finit 5.0. In this mode of operation,
|
||||||
|
every service needs to explicitly declare their readiness notification,
|
||||||
|
like this:
|
||||||
|
|
||||||
|
service notify:pid watchdogd
|
||||||
|
service notify:systemd foo
|
||||||
|
service notify:s6 bar
|
||||||
|
service notify:none qux
|
||||||
|
|
||||||
|
The `notify:none` syntax is for completeness in systems which run in
|
||||||
|
`readiness pid` mode (default). Services declared with `notify:none`
|
||||||
|
will transition to ready as soon as Finit has started them, e.g.,
|
||||||
|
`service/qux/ready`.
|
||||||
|
|
||||||
|
To synchronize two services the following condition can be used:
|
||||||
|
|
||||||
|
service notify:pid watchdogd
|
||||||
|
service <service/watchdogd/ready> stress-ng --cpu 8
|
||||||
|
|
||||||
|
For details on the syntax and options, see below.
|
||||||
|
|
||||||
|
> [!NOTE]
|
||||||
|
> On `initctl reload` conditions are set in "flux", while figuring out
|
||||||
|
> which services to stop, start or restart. Services that need to be
|
||||||
|
> restarted have their `ready` condition removed before Finit issue a
|
||||||
|
> SIGHUP (if they support that), or stop-starting them. A daemon is
|
||||||
|
> 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
|
||||||
|
> are expected to close your notify descriptor after having written
|
||||||
|
> `\n`. This means s6 style daemons currently must be stop-started.
|
||||||
|
> (Declare the service with `<!>` in its condition statement.)
|
||||||
|
>
|
||||||
|
> For default, PID file style readiness notification, daemons are
|
||||||
|
> expected to either create their PID files, or touch it using
|
||||||
|
> `utimensat()` to reassert readiness. Triggering both the `<pid/>`
|
||||||
|
> and `<.../ready>` conditions.
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
Service Wrapper Scripts
|
||||||
|
=======================
|
||||||
|
|
||||||
|
If your service requires to run additional commands, executed before the
|
||||||
|
service is actually started, like the systemd `ExecStartPre`, you can
|
||||||
|
use a wrapper shell script to start your service.
|
||||||
|
|
||||||
|
The Finit service `.conf` file can be put into `/etc/finit.d/available`,
|
||||||
|
so you can control the service using `initctl`. Then use the path to
|
||||||
|
the wrapper script in the Finit `.conf` service stanza. The following
|
||||||
|
example employs a wrapper script in `/etc/start.d`.
|
||||||
|
|
||||||
|
**Example:**
|
||||||
|
|
||||||
|
* `/etc/finit.d/available/program.conf`:
|
||||||
|
|
||||||
|
service [235] <!> /etc/start.d/program -- Example Program
|
||||||
|
|
||||||
|
* `/etc/start.d/program:`
|
||||||
|
|
||||||
|
#!/bin/sh
|
||||||
|
# Prepare the command line options
|
||||||
|
OPTIONS="-u $(cat /etc/username)"
|
||||||
|
|
||||||
|
# Execute the program
|
||||||
|
exec /usr/bin/program $OPTIONS
|
||||||
|
|
||||||
|
> [!NOTE]
|
||||||
|
> The example sets `<!>` to denote that it doesn't support `SIGHUP`.
|
||||||
|
> That way Finit will stop/start the service instead of sending SIGHUP
|
||||||
|
> at restart/reload events.
|
||||||
@@ -0,0 +1,201 @@
|
|||||||
|
Services
|
||||||
|
========
|
||||||
|
|
||||||
|
**Syntax:** `service [LVLS] <COND> /path/to/daemon ARGS -- Optional description`
|
||||||
|
|
||||||
|
Service, or daemon, to be monitored and automatically restarted if it
|
||||||
|
exits prematurely. Finit tries to restart services that die, by default
|
||||||
|
10 times before giving up and marking them as *crashed*. After which
|
||||||
|
they have to be manually restarted with `initctl restart NAME`. The
|
||||||
|
limits controlling this are configurable, see the options below.
|
||||||
|
|
||||||
|
> [!TIP]
|
||||||
|
> To allow endless restarts, see the [`respawn` option](service-opts.md)
|
||||||
|
|
||||||
|
For daemons that support it, we recommend appending `--foreground`,
|
||||||
|
`--no-background`, `-n`, `-F`, or similar command line argument to
|
||||||
|
prevent them from forking off a sub-process in the background. This is
|
||||||
|
the most reliable way to monitor a service.
|
||||||
|
|
||||||
|
However, not all daemons support running in the foreground, or they may
|
||||||
|
start logging to the foreground as well, these are forking daemons and
|
||||||
|
are supported using the same syntax as forking `sysv` services, using
|
||||||
|
the `pid:!/path/to/pidfile.pid` syntax. There is an alternative syntax
|
||||||
|
that may be more intuitive, where Finit can also guess the PID file
|
||||||
|
based on the daemon's command name:
|
||||||
|
|
||||||
|
service type:forking ntpd -- NTP daemon
|
||||||
|
|
||||||
|
This example lets BusyBox `ntpd` daemonize itself. Finit uses the
|
||||||
|
basename of the binary to guess the PID file to watch for the PID:
|
||||||
|
`/var/run/ntpd.pid`. If Finit guesses wrong, you have to submit the
|
||||||
|
full `pid:!/path/to/file.pid`.
|
||||||
|
|
||||||
|
**Example:**
|
||||||
|
|
||||||
|
In the case of `ospfd` (below), we omit the `-d` flag (daemonize) to
|
||||||
|
prevent it from forking to the background:
|
||||||
|
|
||||||
|
service [2345] <pid/zebra> /sbin/ospfd -- OSPF daemon
|
||||||
|
|
||||||
|
`[2345]` denote the runlevels `ospfd` is allowed to run in, they are
|
||||||
|
optional and default to level 2-5 if omitted.
|
||||||
|
|
||||||
|
`<...>` is the condition for starting `ospfd`. In this example Finit
|
||||||
|
waits for another service, `zebra`, to have created its PID file in
|
||||||
|
`/var/run/quagga/zebra.pid` before starting `ospfd`. Finit watches
|
||||||
|
*all* files in `/var/run`, for each file named `*.pid`, or `*/pid`,
|
||||||
|
Finit opens it and find the matching `NAME:ID` using the PID.
|
||||||
|
|
||||||
|
Some services do not maintain a PID file and rather than patching each
|
||||||
|
application Finit provides a workaround. A `pid` keyword can be set
|
||||||
|
to have Finit automatically create (when starting) and later remove
|
||||||
|
(when stopping) the PID file. The file is created in the `/var/run`
|
||||||
|
directory using the `basename(1)` of the service. The default can be
|
||||||
|
modified with an optional `pid:`-argument:
|
||||||
|
|
||||||
|
pid[:[/path/to/]filename[.pid]]
|
||||||
|
|
||||||
|
For example, by adding `pid:/run/bar.pid` to the service `/sbin/bar`,
|
||||||
|
that PID file will, not only be created and removed automatically, but
|
||||||
|
also be used by the Finit condition subsystem. So a service/run/task
|
||||||
|
can depend on `<pid/bar>`, like this foo will not be started until bar
|
||||||
|
has started:
|
||||||
|
|
||||||
|
service pid:/run/bar.pid bar -- Bar Service
|
||||||
|
service <pid/bar> foo -- Foo Service
|
||||||
|
|
||||||
|
Needless to say, it is better if `bar` creates its own PID file when it
|
||||||
|
has completed starting up and is ready for service.
|
||||||
|
|
||||||
|
As an alternative "readiness" notification, Finit supports both systemd
|
||||||
|
and s6 style notification. This can be enabled by using the `notify`
|
||||||
|
option:
|
||||||
|
|
||||||
|
* `notify:systemd` -- tells Finit the service uses the `sd_notify()`
|
||||||
|
API to signal PID 1 when it has completed its startup and is ready
|
||||||
|
to service events. The [sd_notify()][] API expects `NOTIFY_SOCKET`
|
||||||
|
to be set to the socket where the application can send `"READY=1\n"`
|
||||||
|
when it is starting up or has processed a `SIGHUP`.
|
||||||
|
* `notify:s6` -- puts Finit in s6 compatibility mode. Compared to the
|
||||||
|
systemd notification, [s6 expect][] compliant daemons to send `"\n"`
|
||||||
|
and then close their socket. Finit takes care of "hard-wiring" the
|
||||||
|
READY state as long as the application is running, events across any
|
||||||
|
`SIGHUP`. Since s6 can give its applications the descriptor number
|
||||||
|
(must be >3) on then command line, Finit provides the following
|
||||||
|
syntax (`%n` is replaced by Finit with then descriptor number):
|
||||||
|
|
||||||
|
service [S12345789] notify:s6 mdevd -O 4 -D %n
|
||||||
|
|
||||||
|
[sd_notify()]: https://www.freedesktop.org/software/systemd/man/sd_notify.html
|
||||||
|
[s6 expect]: https://skarnet.org/software/s6/notifywhenup.html
|
||||||
|
|
||||||
|
When a service is ready, either by Finit detecting its PID file, or
|
||||||
|
their respective readiness mechanism has been triggered, Finit creates
|
||||||
|
then service's ready condition which other services can depend on:
|
||||||
|
|
||||||
|
$ initctl -v cond get service/mdevd/ready
|
||||||
|
on
|
||||||
|
|
||||||
|
This can be used to synchronize the start of another run/task/service:
|
||||||
|
|
||||||
|
task [S] <service/mdevd/ready> @root:root mdevd-coldplug
|
||||||
|
|
||||||
|
Finit waits for `mdevd` to notify it, before starting `mdevd-coldplug`.
|
||||||
|
Notice how both start in runlevel S, and the coldplug task only runs in
|
||||||
|
S. When the system moves to runlevel 2 (the default), coldplug is no
|
||||||
|
longer part of the running configuration (`initctl show`), this is to
|
||||||
|
ensure that coldplug is not called more than once.
|
||||||
|
|
||||||
|
> For a detailed description of conditions, and how to debug them,
|
||||||
|
> see the [Finit Conditions](../conditions.md) document.
|
||||||
|
|
||||||
|
|
||||||
|
Non-privileged Services
|
||||||
|
-----------------------
|
||||||
|
|
||||||
|
Every `run`, `task`, or `service` can also list the privileges the
|
||||||
|
`/path/to/cmd` should be executed with. Prefix the command with
|
||||||
|
`@USR[:GRP]`, group is optional, like this:
|
||||||
|
|
||||||
|
run [2345] @joe:users logger "Hello world"
|
||||||
|
|
||||||
|
For multiple instances of the same command, e.g. a DHCP client or
|
||||||
|
multiple web servers, add `:ID` somewhere between the `run`, `task`,
|
||||||
|
`service` keyword and the command, like this:
|
||||||
|
|
||||||
|
service :80 [2345] httpd -f -h /http -p 80 -- Web server
|
||||||
|
service :8080[2345] httpd -f -h /http -p 8080 -- Old web server
|
||||||
|
|
||||||
|
Without the `:ID` to the service the latter will overwrite the former
|
||||||
|
and only the old web server would be started and supervised.
|
||||||
|
|
||||||
|
|
||||||
|
Conditional Loading
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
Finit support conditional loading of stanzas. The following example is
|
||||||
|
take from the `system/hotplug.conf` file in the Finit distribution.
|
||||||
|
Here we only show a simplified subset.
|
||||||
|
|
||||||
|
Starting with the `nowarn` option.
|
||||||
|
|
||||||
|
service nowarn name:udevd pid:udevd /lib/systemd/systemd-udevd
|
||||||
|
service nowarn name:udevd pid:udevd udevd
|
||||||
|
|
||||||
|
When loading the .conf file Finit looks for `/lib/systemd/systemd-udevd`
|
||||||
|
if that is not found Finit automatically logs a warning. The `nowarn`
|
||||||
|
option disables this warning so that the second line can be evaluated,
|
||||||
|
which also provides a service named `udevd`.
|
||||||
|
|
||||||
|
run nowarn if:udevd <pid/udevd> :1 udevadm settle -t 0
|
||||||
|
|
||||||
|
This line is only loaded if we know of a service named `udevd`. Again,
|
||||||
|
we do not warn if `udevadm` is not found, execution will also stop here
|
||||||
|
until the PID condition is asserted, i.e., Finit detecting udevd has
|
||||||
|
started.
|
||||||
|
|
||||||
|
run nowarn conflict:udevd [S] mdev -s -- Populating device tree
|
||||||
|
|
||||||
|
If `udevd` is not available, we try to run `mdev`, but if that is not
|
||||||
|
found, again we do not warn.
|
||||||
|
|
||||||
|
Conditional loading statements can also be negated, so the previous stanza
|
||||||
|
can also be written as:
|
||||||
|
|
||||||
|
run nowarn if:!udevd [S] mdev -s -- Populating device tree
|
||||||
|
|
||||||
|
The reason for using `conflict` in this example is that a conflict can be
|
||||||
|
resolved. Stanzas marked with `conflict:foo` are rechecked at runtime.
|
||||||
|
|
||||||
|
|
||||||
|
Conditional Execution
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
Similar to conditional loading of stanzas there is conditional runtime
|
||||||
|
execution. This can be confusing at first, since Finit already has a
|
||||||
|
condition subsystem, but this is more akin to the qualification to a
|
||||||
|
runlevel. E.g., a `task [123]` is qualified to run only in runlevel 1,
|
||||||
|
2, and 3. It is not considered for other runlevels.
|
||||||
|
|
||||||
|
Conditional execution qualify a run/task/service based on a condition.
|
||||||
|
Consider this (simplified) example from the Infix operating system:
|
||||||
|
|
||||||
|
run [S] name:startup <pid/sysrepo> confd -b --load startup-config
|
||||||
|
run [S] if:<usr/fail-startup> name:failure <pid/sysrepo> confd --load failure-config
|
||||||
|
|
||||||
|
The two run statements reside in the same .conf file so Finit runs them
|
||||||
|
in true sequence. If loading the file `startup-config` fails confd sets
|
||||||
|
the condition `usr/fail-startup`, thus allowing the next run statement
|
||||||
|
to load `failure-config`.
|
||||||
|
|
||||||
|
Notice the critical difference between the `<pid/sysrepo>` condition and
|
||||||
|
`if:<usr/fail-startup>`. The former is a condition for starting and the
|
||||||
|
latter is a condition to check if a run/task/service is qualified to
|
||||||
|
even be considered.
|
||||||
|
|
||||||
|
Conditional execution statements can also be negated, so provided the
|
||||||
|
file loaded did the opposite, i.e., set a condition on success, the
|
||||||
|
previous stanza can also be written as:
|
||||||
|
|
||||||
|
run [S] if:<!usr/startup-ok> name:failure <pid/sysrepo> confd ...
|
||||||
@@ -0,0 +1,94 @@
|
|||||||
|
SysV Init Compatibility
|
||||||
|
=======================
|
||||||
|
|
||||||
|
It is not possible to run unmodified SysV init systems with Finit. This
|
||||||
|
was never the intention and is not the strength of Finit. However, it
|
||||||
|
comes with a few SysV Init compatibility features to ease the transition
|
||||||
|
from a serialized boot process.
|
||||||
|
|
||||||
|
SysV Init Scripts
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
**Syntax:** `sysv [LVLS] <COND> /path/to/init-script -- Optional description`
|
||||||
|
|
||||||
|
> `<COND>` is described in the [Services](services.md) section.
|
||||||
|
|
||||||
|
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
|
||||||
|
reuse much of existing setup and init scripts in Linux distributions.
|
||||||
|
|
||||||
|
When entering an allowed runlevel, Finit calls `init-script start`, when
|
||||||
|
entering a disallowed runlevel, Finit calls `init-script stop`, and if
|
||||||
|
the Finit .conf, where `sysv` stanza is declared, is modified, Finit
|
||||||
|
calls `init-script restart` on `initctl reload`. Similar to how
|
||||||
|
`service` stanzas work.
|
||||||
|
|
||||||
|
Forking services started with `sysv` scripts can be monitored by Finit
|
||||||
|
by declaring the PID file to look for: `pid:!/path/to/pidfile.pid`.
|
||||||
|
Notice the leading `!`, it signifies Finit should not try to create the
|
||||||
|
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
|
||||||
|
option to run it in the foreground, more on this below in `service`.
|
||||||
|
|
||||||
|
> [!TIP]
|
||||||
|
> See also [SysV Init Compatibility](#sysv-init-compatibility).
|
||||||
|
|
||||||
|
`runparts DIRECTORY`
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
For a directory with traditional start/stop scripts that should run, in
|
||||||
|
order, at bootstrap, Finit provides the `runparts` directive. It runs
|
||||||
|
in runlevel S, at the very end of it (before calling `/etc/rc.local`)
|
||||||
|
making it perfect for most scenarios.
|
||||||
|
|
||||||
|
For syntax details, see the [Run-parts Scripts](runparts.md) section.
|
||||||
|
Here is an example take from a Debian installation:
|
||||||
|
|
||||||
|
runparts /etc/rc2.d
|
||||||
|
|
||||||
|
Files in these directories are usually named `SNNfoo` and `KNNfoo`,
|
||||||
|
which Finit knows about and automatically appends the correct argument:
|
||||||
|
|
||||||
|
/bin/sh -c /etc/rc2.d/S01openbsd-inetd start
|
||||||
|
|
||||||
|
or
|
||||||
|
|
||||||
|
/bin/sh -c /etc/rc0.d/K01openbsd-inetd stop
|
||||||
|
|
||||||
|
Files that do not match this pattern are started similarly but without
|
||||||
|
the extra command line argument.
|
||||||
|
|
||||||
|
Start/Stop Scripts
|
||||||
|
------------------
|
||||||
|
|
||||||
|
For syntax details, see [SysV Init Scripts](#sysv-init-scripts), above.
|
||||||
|
Here follows an example taken from a Debian installation:
|
||||||
|
|
||||||
|
sysv [2345] <pid/syslogd> /etc/init.d/openbsd-inetd -- OpenBSD inet daemon
|
||||||
|
|
||||||
|
The init script header could be parsed to extract `Default-Start:` and
|
||||||
|
other parameters for the `sysv` command to Finit. There is currently no
|
||||||
|
way to detail a generic syslogd dependency in Finit, so `Should-Start:`
|
||||||
|
in the header must be mapped to the condition system in Finit using an
|
||||||
|
absolute reference, here we depend on the sysklogd project's syslogd.
|
||||||
|
|
||||||
|
`/etc/rc.local`
|
||||||
|
---------------
|
||||||
|
|
||||||
|
One often requested feature, early on, was a way to run a site specific
|
||||||
|
script to set up, e.g., static routes or firewall rules. A user can add
|
||||||
|
a `task` or `run` command in the Finit configuration for this, but for
|
||||||
|
compatibility reasons the more widely know `/etc/rc.local` is used if
|
||||||
|
it exists, and is executable. It is called very late in the boot process
|
||||||
|
when the system has left runlevel S, stopped all old and started all new
|
||||||
|
services in the target runlevel (default 2).
|
||||||
|
|
||||||
|
> In Finit releases before v4.5 this script blocked Finit execution and
|
||||||
|
> made it as good as impossible to call `initctl` during that time.
|
||||||
|
|
||||||
|
`init q`
|
||||||
|
--------
|
||||||
|
|
||||||
|
When `/sbin/finit` is installed as `/sbin/init`, it is possible to use
|
||||||
|
`init q` to reload the configuration. This is the same as calling
|
||||||
|
`initctl reload`.
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
run (sequence)
|
||||||
|
--------------
|
||||||
|
|
||||||
|
**Syntax:** `run [LVLS] <COND> /path/to/cmd ARGS -- Optional description`
|
||||||
|
|
||||||
|
> `<COND>` is described in the [Services](services.md) section.
|
||||||
|
|
||||||
|
One-shot command to run in sequence when entering a runlevel, with
|
||||||
|
optional arguments and description. `run` commands are guaranteed to be
|
||||||
|
completed before running the next command. Useful when serialization is
|
||||||
|
required.
|
||||||
|
|
||||||
|
> [!WARNING]
|
||||||
|
> Try to avoid the `run` command. It blocks much of the functionality
|
||||||
|
> in Finit, like (re)starting other (perhaps crashing) services while a
|
||||||
|
> `run` task is executing. Use other synchronization mechanisms
|
||||||
|
> instead, like conditions.
|
||||||
|
|
||||||
|
Incomplete list of unsupported `initctl` commands in `run` tasks:
|
||||||
|
|
||||||
|
- `initctl runlevel N`, setting runlevel
|
||||||
|
- `initctl reboot`
|
||||||
|
- `initctl halt`
|
||||||
|
- `initctl poweroff`
|
||||||
|
- `initctl suspend`
|
||||||
|
|
||||||
|
To prevent `initctl` from calling Finit when enabling and disabling
|
||||||
|
services from inside a `run` task, use the `--force` option. See
|
||||||
|
also the `--quiet` and `--batch` options.
|
||||||
|
|
||||||
|
task (parallel)
|
||||||
|
---------------
|
||||||
|
|
||||||
|
**Syntax:** `task [LVLS] <COND> /path/to/cmd ARGS -- Optional description`
|
||||||
|
|
||||||
|
> `<COND>` is described in the [Services](services.md) section.
|
||||||
|
|
||||||
|
One-shot like 'run', but starts in parallel with the next command.
|
||||||
|
|
||||||
|
Both `run` and `task` commands are run in a shell, so basic pipes and
|
||||||
|
redirects can be used:
|
||||||
|
|
||||||
|
task [s] echo "foo" | cat >/tmp/bar
|
||||||
|
|
||||||
|
Please note, `;`, `&&`, `||`, and similar are *not supported*. Any
|
||||||
|
non-trivial constructs are better placed in a separate shell script.
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
Templating
|
||||||
|
==========
|
||||||
|
|
||||||
|
Finit comes with rudimentary support for templating, similar to that of
|
||||||
|
systemd. Best illustrated with an example:
|
||||||
|
|
||||||
|
$ initctl show avahi-autoipd@
|
||||||
|
service :%i avahi-autoipd --syslog %i -- ZeroConf for %i
|
||||||
|
|
||||||
|
To enable ZeroConf for, e.g., `eth0`, use
|
||||||
|
|
||||||
|
$ initctl enable avahi-autoipd@eth0.conf
|
||||||
|
|
||||||
|
The enabled symlink will be set up to `avahi-autoipd@.conf` and every
|
||||||
|
instance of `%i` will in the instantiated directive be replaced with
|
||||||
|
`eth0`. Inspect the resulting instantiated template with `initctl show
|
||||||
|
avahi-autoipd:eth0` and check the status of a running instance with:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ initctl status avahi-autoipd:eth0
|
||||||
|
Status : running
|
||||||
|
Identity : avahi-autoipd:eth0
|
||||||
|
Description : ZeroConf for eth0
|
||||||
|
Origin : /etc/finit.d/enabled/avahi-autoipd@eth0.conf
|
||||||
|
Environment : -/etc/default/avahi-autoipd-eth0
|
||||||
|
Command : avahi-autoipd $AVAHI_AUTOIPD_ARGS eth0
|
||||||
|
PID file : /run/avahi-autoipd.eth0.pid
|
||||||
|
PID : 4190
|
||||||
|
User : root
|
||||||
|
Group : root
|
||||||
|
Uptime : 24 sec
|
||||||
|
Restarts : 0 (0/10)
|
||||||
|
Runlevels : [---2345-789]
|
||||||
|
Memory : 20.0k
|
||||||
|
CGroup : /system/avahi-autoipd@eth0 cpu 0 [100, max] mem [0, max]
|
||||||
|
└─ 4190 avahi-autoipd: [eth0] bound 169.254.1.9
|
||||||
|
|
||||||
|
Jul 8 11:51:42 infix-c0-ff-ee finit[1]: Starting avahi-autoipd:eth0[4190]
|
||||||
|
```
|
||||||
@@ -0,0 +1,86 @@
|
|||||||
|
TTYs and Consoles
|
||||||
|
=================
|
||||||
|
|
||||||
|
**Syntax:** `tty [LVLS] <COND> DEV [BAUD] [noclear] [nowait] [nologin] [TERM]`
|
||||||
|
`tty [LVLS] <COND> CMD <ARGS> [noclear] [nowait]`
|
||||||
|
`tty [LVLS] <COND> [notty] [rescue]`
|
||||||
|
|
||||||
|
The first variant of this option uses the built-in getty on the given
|
||||||
|
TTY device DEV, in the given runlevels. DEV may be the special keyword
|
||||||
|
`@console`, which is expanded from `/sys/class/tty/console/active`,
|
||||||
|
useful on embedded systems.
|
||||||
|
|
||||||
|
The default baud rate is 0, i.e., keep kernel default.
|
||||||
|
|
||||||
|
> The `tty` stanza inherits runlevel, condition (and other feature)
|
||||||
|
> parsing from the `service` stanza. So TTYs can run in one or many
|
||||||
|
> runlevels and depend on any condition supported by Finit. This is
|
||||||
|
> useful e.g. to depend on `<pid/elogind>` before starting a TTY.
|
||||||
|
|
||||||
|
**Example:**
|
||||||
|
|
||||||
|
tty [12345] /dev/ttyAMA0 115200 noclear vt220
|
||||||
|
|
||||||
|
The second `tty` syntax variant is for using an external getty, like
|
||||||
|
agetty or the BusyBox getty.
|
||||||
|
|
||||||
|
The third variant is for board bringup and the `rescue` boot mode. No
|
||||||
|
device node is required in this variant, the same output that the kernel
|
||||||
|
uses is reused for stdio. If the `rescue` option is omitted, a shell is
|
||||||
|
started (`nologin`, `noclear`, and `nowait` are implied), if the rescue
|
||||||
|
option is set the bundled `/libexec/finit/sulogin` is started to present
|
||||||
|
a bare-bones root login prompt. If the root (uid:0, gid:0) user does
|
||||||
|
not have a password set, no rescue is possible. For more information,
|
||||||
|
see the [Rescue Mode](rescue.md) section.
|
||||||
|
|
||||||
|
By default, the first two syntax variants *clear* the TTY and *wait* for
|
||||||
|
the user to press enter before starting getty.
|
||||||
|
|
||||||
|
**Example:**
|
||||||
|
|
||||||
|
tty [12345] /sbin/getty -L 115200 /dev/ttyAMA0 vt100
|
||||||
|
tty [12345] /sbin/agetty -L ttyAMA0 115200 vt100 nowait
|
||||||
|
|
||||||
|
The `noclear` option disables clearing the TTY after each session.
|
||||||
|
Clearing the TTY when a user logs out is usually preferable.
|
||||||
|
|
||||||
|
The `nowait` option disables the `press Enter to activate console`
|
||||||
|
message before actually starting the getty program. On small and
|
||||||
|
embedded systems running multiple unused getty wastes both memory
|
||||||
|
and CPU cycles, so `wait` is the preferred default.
|
||||||
|
|
||||||
|
The `nologin` option disables getty and `/bin/login`, and gives the
|
||||||
|
user a root (login) shell on the given TTY `<DEV>` immediately.
|
||||||
|
Needless to say, this is a rather insecure option, but can be very
|
||||||
|
useful for developer builds, during board bringup, or similar.
|
||||||
|
|
||||||
|
Notice the ordering, the `TERM` option to the built-in getty must be
|
||||||
|
the last argument.
|
||||||
|
|
||||||
|
Embedded systems may want to enable automatic `DEV` by supplying the
|
||||||
|
special `@console` device. This works regardless weather the system
|
||||||
|
uses `ttyS0`, `ttyAMA0`, `ttyMXC0`, or anything else. Finit figures
|
||||||
|
it out by querying sysfs: `/sys/class/tty/console/active`. The speed
|
||||||
|
can be omitted to keep the kernel default.
|
||||||
|
|
||||||
|
> Most systems get by fine by just using `console`, which will evaluate
|
||||||
|
> to `/dev/console`. If you have to use `@console` to get any output,
|
||||||
|
> you may have some issue with your kernel config.
|
||||||
|
|
||||||
|
**Example:**
|
||||||
|
|
||||||
|
tty [12345] @console noclear vt220
|
||||||
|
|
||||||
|
On really bare bones systems, or for board bringup, Finit can give you a
|
||||||
|
shell prompt as soon as bootstrap is done, without opening any device
|
||||||
|
node:
|
||||||
|
|
||||||
|
tty [12345789] notty
|
||||||
|
|
||||||
|
This should of course not be enabled on production systems. Because it
|
||||||
|
may give a user root access without having to log in. However, for
|
||||||
|
board bringup and system debugging it can come in handy.
|
||||||
|
|
||||||
|
One can also use the `service` stanza to start a stand-alone shell:
|
||||||
|
|
||||||
|
service [12345] /bin/sh -l
|
||||||
@@ -0,0 +1,137 @@
|
|||||||
|
Configuration Example
|
||||||
|
=====================
|
||||||
|
|
||||||
|
This example `/etc/finit.conf` can also be split up in multiple `.conf`
|
||||||
|
files in `/etc/finit.d`. Available, but not yet enabled, services can
|
||||||
|
be placed in `/etc/finit.d/available` and enabled by an operator using
|
||||||
|
the [initctl](initctl.md) tool.
|
||||||
|
|
||||||
|
See the [contrib/][contrib] directory on GitHub for examples, or take a
|
||||||
|
peek at systems using Finit, like [Infix OS][infix] and [myLinux][].
|
||||||
|
|
||||||
|
> [!TIP]
|
||||||
|
> As of Finit v4.4, `.conf` lines can be broken up using the standard UNIX
|
||||||
|
> continuation character (`\`), trailing comments are also supported. The
|
||||||
|
> latter means you must escape any hashes used in directives and descriptions
|
||||||
|
> (`\#`). For more on this and examples, see the [finit.conf(5)][] manual or
|
||||||
|
> the [Configuration](config/index.md) section.
|
||||||
|
|
||||||
|
```ApacheConf
|
||||||
|
# Fallback if /etc/hostname is missing
|
||||||
|
host default
|
||||||
|
|
||||||
|
# Runlevel to start after bootstrap, 'S', default: 2
|
||||||
|
#runlevel 2
|
||||||
|
|
||||||
|
# Support for setting global environment variables, using foo=bar syntax
|
||||||
|
# be careful though with variables like PATH, SHELL, LOGNAME, etc.
|
||||||
|
#PATH=/usr/bin:/bin:/usr/sbin:/sbin
|
||||||
|
|
||||||
|
# Max file size for each log file: 100 kiB, rotate max 4 copies:
|
||||||
|
# log => log.1 => log.2.gz => log.3.gz => log.4.gz
|
||||||
|
log size=100k count=4
|
||||||
|
|
||||||
|
# Services to be monitored and respawned as needed
|
||||||
|
service [S12345] env:-/etc/conf.d/watchdog watchdog $WATCHDOG_OPTS $WATCHDOG_DEV -- System watchdog daemon
|
||||||
|
service [S12345] env:-/etc/conf.d/syslog syslogd -n $SYSLOGD_OPTS -- System log daemon
|
||||||
|
service [S12345] <pid/syslogd> env:-/etc/conf.d/klogd klogd -n $KLOGD_OPTS -- Kernel log daemon
|
||||||
|
service [2345] env:-/etc/conf.d/lldpd lldpd -d $LLDPD_OPTS -- LLDP daemon (IEEE 802.1ab)
|
||||||
|
|
||||||
|
# The BusyBox ntpd does not use syslog when running in the foreground
|
||||||
|
# So we use this trick to redirect stdout/stderr to a log file. The
|
||||||
|
# log file is rotated with the above settings. The condition declares
|
||||||
|
# a dependency on a system default route (gateway) to be set. A single
|
||||||
|
# <!> at the beginning means ntpd does not respect SIGHUP for restart.
|
||||||
|
service [2345] log:/var/log/ntpd.log <!net/route/default> ntpd -n -l -I eth0 -- NTP daemon
|
||||||
|
|
||||||
|
# For multiple instances of the same service, add :ID somewhere between
|
||||||
|
# the service/run/task keyword and the command.
|
||||||
|
service :80 [2345] merecat -n -p 80 /var/www -- Web server
|
||||||
|
service :8080 [2345] merecat -n -p 8080 /var/www -- Old web server
|
||||||
|
|
||||||
|
# Alternative method instead of below runparts, can also use /etc/rc.local
|
||||||
|
#sysv [S] /etc/init.d/keyboard-setup -- Setting up preliminary keymap
|
||||||
|
#sysv [S] /etc/init.d/acpid -- Starting ACPI Daemon
|
||||||
|
#task [S] /etc/init.d/kbd -- Preparing console
|
||||||
|
|
||||||
|
# Hidden from boot progress, using empty `--` description
|
||||||
|
#sysv [S] /etc/init.d/keyboard-setup --
|
||||||
|
#sysv [S] /etc/init.d/acpid --
|
||||||
|
#task [S] /etc/init.d/kbd --
|
||||||
|
|
||||||
|
# Run start scripts from this directory
|
||||||
|
# runparts /etc/start.d
|
||||||
|
|
||||||
|
# Virtual consoles run BusyBox getty, keep kernel default speed
|
||||||
|
tty [12345] /sbin/getty -L 0 /dev/tty1 linux nowait noclear
|
||||||
|
tty [2345] /sbin/getty -L 0 /dev/tty2 linux nowait noclear
|
||||||
|
tty [2345] /sbin/getty -L 0 /dev/tty3 linux nowait noclear
|
||||||
|
|
||||||
|
# Use built-in getty for serial port and USB serial
|
||||||
|
#tty [12345] /dev/ttyAMA0 noclear nowait
|
||||||
|
#tty [12345] /dev/ttyUSB0 noclear
|
||||||
|
|
||||||
|
# Just give me a shell, I need to debug this embedded system!
|
||||||
|
#tty [12345] console noclear nologin
|
||||||
|
```
|
||||||
|
|
||||||
|
The `service` stanza, as well as `task`, `run` and others are described in
|
||||||
|
full in the [Services Syntax](config/services.md) section.
|
||||||
|
|
||||||
|
Here's a quick overview of some of the most common components needed to start
|
||||||
|
a UNIX daemon:
|
||||||
|
|
||||||
|
```
|
||||||
|
service [LVLS] <COND> log env:[-]/etc/default/daemon daemon ARGS -- Example daemon
|
||||||
|
^ ^ ^ ^ ^ ^ ^ ^
|
||||||
|
| | | | | | | `---------- Optional description
|
||||||
|
| | | | | | `------------------ Daemon arguments
|
||||||
|
| | | | | `------------------------- Path to daemon
|
||||||
|
| | | | `---------------------------------------------------- Optional env. file
|
||||||
|
| | | `-------------------------------------------------------- Redirect output to log
|
||||||
|
| | `--------------------------------------------------------------- Optional conditions
|
||||||
|
| `---------------------------------------------------------------------- Optional Runlevels
|
||||||
|
`------------------------------------------------------------------------------ Supervised program (daemon)
|
||||||
|
```
|
||||||
|
|
||||||
|
Some components are optional: runlevel(s), condition(s) and description,
|
||||||
|
making it easy to create simple start scripts and still possible for more
|
||||||
|
advanced uses as well:
|
||||||
|
|
||||||
|
service /usr/sbin/sshd -D
|
||||||
|
|
||||||
|
Dependencies are handled using [conditions](conditions.md). One of
|
||||||
|
the most common conditions is to wait for basic networking to become
|
||||||
|
available:
|
||||||
|
|
||||||
|
service <net/route/default> nginx -- High performance HTTP server
|
||||||
|
|
||||||
|
Here is another example where we instruct Finit to not start BusyBox
|
||||||
|
`ntpd` until `syslogd` has started properly. Finit waits for `syslogd`
|
||||||
|
to create its PID file, by default `/var/run/syslogd.pid`.
|
||||||
|
|
||||||
|
service [2345] log <!pid/syslogd> ntpd -n -N -p pool.ntp.org
|
||||||
|
service [S12345] syslogd -n -- Syslog daemon
|
||||||
|
|
||||||
|
Notice the `log` keyword, BusyBox `ntpd` uses `stderr` for logging when
|
||||||
|
run in the foreground. With `log` Finit redirects `stdout` + `stderr`
|
||||||
|
to the system log daemon using the command line `logger(1)` tool.
|
||||||
|
|
||||||
|
A service, or task, can have multiple dependencies listed. Here we wait
|
||||||
|
for *both* `syslogd` to have started and basic networking to be up:
|
||||||
|
|
||||||
|
service [2345] log <pid/syslogd,net/route/default> ntpd -n -N -p pool.ntp.org
|
||||||
|
|
||||||
|
If either condition fails, e.g. loss of networking, `ntpd` is stopped
|
||||||
|
and as soon as it comes back up again `ntpd` is restarted automatically.
|
||||||
|
|
||||||
|
> [!NOTE]
|
||||||
|
> Make sure daemons do *not* fork and detach themselves from the controlling
|
||||||
|
> TTY, usually an `-n` or `-f` flag, or `-D` as in the case of OpenSSH above.
|
||||||
|
> If it detaches itself, Finit cannot monitor it and will instead try to
|
||||||
|
> restart it.
|
||||||
|
|
||||||
|
[finit.conf(5)]: https://man.troglobit.com/man5/finit.conf.5.html
|
||||||
|
[infix]: https://kernelkit.github.io
|
||||||
|
[myLinux]: https://github.com/troglobit/myLinux/
|
||||||
|
[contrib]: https://github.com/troglobit/finit/tree/master/contrib
|
||||||
@@ -0,0 +1,178 @@
|
|||||||
|
Finit Features
|
||||||
|
==============
|
||||||
|
|
||||||
|
**Process Supervision**
|
||||||
|
|
||||||
|
Start, monitor and restart services should they fail.
|
||||||
|
|
||||||
|
|
||||||
|
**Getty**
|
||||||
|
|
||||||
|
Finit supports external getty but also comes with a limited built-in
|
||||||
|
Getty, useful for really small systems. A getty sets up the TTY and
|
||||||
|
waits for user input before handing over to `/bin/login`, which is
|
||||||
|
responsible for handling the actual authentication.
|
||||||
|
|
||||||
|
```conf
|
||||||
|
tty [12345] /dev/tty1 nowait linux
|
||||||
|
tty [12345] /dev/ttyAMA0 noclear vt100
|
||||||
|
tty [12345] /sbin/getty -L /dev/ttyAMA0 vt100
|
||||||
|
```
|
||||||
|
|
||||||
|
Users of embedded systems may want to enable automatic serial console
|
||||||
|
with the special `@console` device. This works regardless whether the
|
||||||
|
system uses `ttyS0`, `ttyAMA0`, `ttyMXC0`, or anything else. Finit
|
||||||
|
figures it out by querying sysfs: `/sys/class/tty/console/active`.
|
||||||
|
|
||||||
|
```conf
|
||||||
|
tty [12345] @console linux noclear
|
||||||
|
```
|
||||||
|
|
||||||
|
Notice the optional `noclear`, `nowait`, and `nologin` flags. The
|
||||||
|
latter is for skipping the login process entirely. For more information,
|
||||||
|
see the [TTY and Consoles](config/tty.md) section.
|
||||||
|
|
||||||
|
|
||||||
|
**Runlevels**
|
||||||
|
|
||||||
|
Support for SysV init-style [runlevels][5] is available, in the same
|
||||||
|
minimal style as everything else in Finit. The `[2345]` syntax can be
|
||||||
|
applied to service, task, run, and TTY stanzas.
|
||||||
|
|
||||||
|
Reserved runlevels are 0 and 6, halt and reboot, respectively just like
|
||||||
|
SysV init. Runlevel 1 can be configured freely, but is recommended to
|
||||||
|
be kept as the system single-user runlevel since Finit will not start
|
||||||
|
networking here. The configured `runlevel NUM` from `/etc/finit.conf`
|
||||||
|
is what Finit changes to after bootstrap, unless 'single' (or 'S') is
|
||||||
|
given on the kernel cmdline, in which case runlevel 1 is started.
|
||||||
|
|
||||||
|
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
|
||||||
|
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
|
||||||
|
[`initctl`](initctl.md) tool.
|
||||||
|
|
||||||
|
|
||||||
|
**Conditions**
|
||||||
|
|
||||||
|
As mentioned previously, Finit has an advanced dependency system to
|
||||||
|
handle synchronization, called [conditions](conditions.md). It can
|
||||||
|
be used in many ways; depend on another service, network availability,
|
||||||
|
etc.
|
||||||
|
|
||||||
|
One *really cool* example useful for embedded systems is to run certain
|
||||||
|
scripts if a board has a certain feature encoded in its device tree. At
|
||||||
|
bootstrap we run the following `ident` script:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
#!/bin/sh
|
||||||
|
conddir=/var/run/finit/cond/hw/model
|
||||||
|
dtmodel=/sys/firmware/devicetree/base/model
|
||||||
|
|
||||||
|
if ! test -e $dtmodel; then
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
model=$(cat $dtmodel | tr "[A-Z] " "[a-z]-")
|
||||||
|
mkdir -p $conddir && ln -s ../../reconf $conddir/$model
|
||||||
|
```
|
||||||
|
|
||||||
|
Provided the device tree node exists, and is a string, we can then use
|
||||||
|
the condition `<hw/model/foo>` when starting other scripts. Here is an
|
||||||
|
example:
|
||||||
|
|
||||||
|
```
|
||||||
|
run [S] /path/to/ident --
|
||||||
|
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`
|
||||||
|
> in the Finit progress output.
|
||||||
|
|
||||||
|
|
||||||
|
**Plugins**
|
||||||
|
|
||||||
|
Plugins can *extend* the functionality of Finit and *hook into* the
|
||||||
|
different stages of the boot process and at runtime. Plugins are
|
||||||
|
written in C and compiled into a dynamic library loaded automatically by
|
||||||
|
finit at boot. A basic set of plugins are bundled in the `plugins/`
|
||||||
|
directory.
|
||||||
|
|
||||||
|
Capabilities:
|
||||||
|
|
||||||
|
- **Hooks**
|
||||||
|
Hook into the boot at predefined points to extend Finit
|
||||||
|
- **I/O**
|
||||||
|
Listen to external events and control Finit behavior/services
|
||||||
|
|
||||||
|
Extensions and functionality not purely related to what an `/sbin/init`
|
||||||
|
needs to start a system are available as a set of plugins that either
|
||||||
|
hook into the boot process or respond to various I/O.
|
||||||
|
|
||||||
|
For more information, see the [Plugins](plugins.md) section.
|
||||||
|
|
||||||
|
|
||||||
|
**Automatic Reload**
|
||||||
|
|
||||||
|
By default, Finit monitors `/etc/finit.d/` and `/etc/finit.d/enabled/`
|
||||||
|
registering any changes to `.conf` files. To activate a change the user
|
||||||
|
must call `initctl reload`, which reloads all modified files, stops any
|
||||||
|
removed services, starts new ones, and restarts any modified ones. If the
|
||||||
|
command line arguments of a service have changed, the process will be
|
||||||
|
terminated and then started again with the updated arguments. If the arguments
|
||||||
|
have not been modified and the process supports SIGHUP, the process will
|
||||||
|
receive a SIGHUP rather than being terminated and started.
|
||||||
|
|
||||||
|
For some use-cases the extra step of calling `initctl reload` creates an
|
||||||
|
unnecessary overhead, which can be removed at build-time using:
|
||||||
|
|
||||||
|
configure --enable-auto-reload
|
||||||
|
|
||||||
|
|
||||||
|
**Cgroups**
|
||||||
|
|
||||||
|
Finit supports cgroups v2 and comes with the following default groups in
|
||||||
|
which services and user sessions are placed in:
|
||||||
|
|
||||||
|
/sys/fs/cgroup
|
||||||
|
|-- init/ # cpu.weight:100
|
||||||
|
|-- system/ # cpu.weight:9800
|
||||||
|
`-- user/ # cpu.weight:100
|
||||||
|
|
||||||
|
Finit itself and its helper scripts and services are placed in the
|
||||||
|
top-level leaf-node group `init/`, which also is _reserved_.
|
||||||
|
|
||||||
|
All run/task/service/sysv processes are placed in their own sub-group
|
||||||
|
in `system/`. The name of each sub-group is taken from the respective
|
||||||
|
`.conf` file from `/etc/finit.d`.
|
||||||
|
|
||||||
|
All getty/tty processes are placed in their own sub-group in `user/`.
|
||||||
|
The name of each sub-group is taken from the username.
|
||||||
|
|
||||||
|
A fourth group also exists, the `root` group. It is also _reserved_ and
|
||||||
|
primarily intended for RT tasks. If you have RT tasks they need to be
|
||||||
|
declared as such in their service stanza like this:
|
||||||
|
|
||||||
|
service [...] <...> cgroup.root /path/to/foo args -- description
|
||||||
|
|
||||||
|
or
|
||||||
|
|
||||||
|
cgroup.root
|
||||||
|
service [...] <...> /path/to/foo args -- description
|
||||||
|
service [...] <...> /path/to/bar args -- description
|
||||||
|
|
||||||
|
See the [Cgroups](config/cgroups.md) section for more information, e.g.,
|
||||||
|
how to configure per-group limits.
|
||||||
|
|
||||||
|
The `initctl` tool has three commands to help debug and optimize the
|
||||||
|
setup and monitoring of cgroups. See the `ps`, `top`, and `cgroup`
|
||||||
|
commands for details.
|
||||||
|
|
||||||
|
> [!NOTE]
|
||||||
|
> Systems that do not support cgroups, specifically version 2, are
|
||||||
|
> automatically detected. On such systems the above functionality is
|
||||||
|
> disabled early at boot.
|
||||||
|
|
||||||
|
|
||||||
|
[5]: https://en.wikipedia.org/wiki/Runlevel
|
||||||
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 69 KiB After Width: | Height: | Size: 69 KiB |
|
Before Width: | Height: | Size: 35 KiB After Width: | Height: | Size: 35 KiB |
|
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 23 KiB |
|
Before Width: | Height: | Size: 8.6 KiB After Width: | Height: | Size: 8.6 KiB |
|
Before Width: | Height: | Size: 7.6 KiB After Width: | Height: | Size: 7.6 KiB |
|
After Width: | Height: | Size: 5.8 KiB |
|
Before Width: | Height: | Size: 320 KiB After Width: | Height: | Size: 320 KiB |
|
Before Width: | Height: | Size: 814 KiB After Width: | Height: | Size: 814 KiB |
@@ -0,0 +1,76 @@
|
|||||||
|
Introduction
|
||||||
|
============
|
||||||
|
|
||||||
|
{ align=right }
|
||||||
|
|
||||||
|
> Reverse engineered from the [EeePC fastinit][]
|
||||||
|
> "gaps filled with frog DNA …"
|
||||||
|
> — [Claudio Matsuoka][]
|
||||||
|
|
||||||
|
Finit is a process starter and [supervisor][1] designed to run as PID 1
|
||||||
|
on Linux systems. It consists of a set of [plugins](plugins.md) and can
|
||||||
|
be set up using [configuration files](config/files.md). Plugins start
|
||||||
|
at [hook points](plugins.md#hooks) and can run various set up tasks
|
||||||
|
and/or install event handlers that later provide runtime services, e.g.,
|
||||||
|
PID file monitoring, or [conditions](conditions.md).
|
||||||
|
|
||||||
|
Features
|
||||||
|
--------
|
||||||
|
|
||||||
|
* [Runlevels][5], defined per service
|
||||||
|
* One-shot tasks, services (daemons), or [SysV init][4] start/stop scripts
|
||||||
|
* Runparts and `/etc/rc.local` support
|
||||||
|
* Process supervision similar to [systemd][]
|
||||||
|
* Sourcing environment files
|
||||||
|
* Conditions for network/process/custom dependencies
|
||||||
|
* Readiness notification; PID files (native) for synchronizing system
|
||||||
|
startup, support for systemd [sd_notify()][], or [s6 style][] too
|
||||||
|
* Limited support for [tmpfiles.d(5)][] (no aging, attributes, or subvolumes)
|
||||||
|
* Pre/Post script actions
|
||||||
|
* Rudimentary [templating support](config/templating.md)
|
||||||
|
* Tooling to enable/disable services
|
||||||
|
* Built-in getty
|
||||||
|
* Built-in watchdog, with support for hand-over to [watchdogd][]
|
||||||
|
* Built-in support for Debian/BusyBox [`/etc/network/interfaces`][3]
|
||||||
|
* Cgroups v2, both configuration and monitoring in `initctl top`
|
||||||
|
* Plugin support for customization
|
||||||
|
* Proper rescue mode with bundled `sulogin` for protected maintenance shell
|
||||||
|
* Integration with [watchdogd][] for full system supervision
|
||||||
|
* Logging to kernel ring buffer before `syslogd` has started, see the
|
||||||
|
recommended [sysklogd][] project for complete logging integration
|
||||||
|
and how to log to the kernel ring buffer from scripts using `logger`
|
||||||
|
|
||||||
|
For a more thorough overview, see the [Features](features.md) section.
|
||||||
|
|
||||||
|
> [!TIP]
|
||||||
|
> See [SysV Init Compatibility](config/sysv.md) for help to
|
||||||
|
> quickly get going with an existing SysV or BusyBox init setup.
|
||||||
|
|
||||||
|
|
||||||
|
Origin
|
||||||
|
------
|
||||||
|
|
||||||
|
This project is based on the [original finit][] by [Claudio Matsuoka][]
|
||||||
|
which was reverse engineered from syscalls of the [EeePC fastinit][].
|
||||||
|
|
||||||
|
Finit is developed and maintained by [Joachim Wiberg][] at [GitHub][6].
|
||||||
|
Please file bug reports, clone it, or send pull requests for bug fixes
|
||||||
|
and proposed extensions.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
[1]: https://en.wikipedia.org/wiki/Process_supervision
|
||||||
|
[3]: https://manpages.debian.org/unstable/ifupdown2/interfaces.5.en.html
|
||||||
|
[4]: https://en.wikipedia.org/wiki/Init
|
||||||
|
[5]: https://en.wikipedia.org/wiki/Runlevel
|
||||||
|
[6]: https://github.com/troglobit/finit
|
||||||
|
[systemd]: https://www.freedesktop.org/wiki/Software/systemd/
|
||||||
|
[sd_notify()]: https://www.freedesktop.org/software/systemd/man/sd_notify.html
|
||||||
|
[s6 style]: https://skarnet.org/software/s6/notifywhenup.html
|
||||||
|
[tmpfiles.d(5)]: https://www.freedesktop.org/software/systemd/man/tmpfiles.d.html
|
||||||
|
[EeePC fastinit]: https://web.archive.org/web/20071208212450/http://wiki.eeeuser.com/boot_process:the_boot_process
|
||||||
|
[original finit]: http://helllabs.org/finit/
|
||||||
|
[Claudio Matsuoka]: https://github.com/cmatsuoka
|
||||||
|
[Joachim Wiberg]: https://troglobit.com
|
||||||
|
[watchdogd]: https://troglobit.com/watchdogd.html
|
||||||
|
[sysklogd]: https://github.com/troglobit/sysklogd/
|
||||||
@@ -0,0 +1,145 @@
|
|||||||
|
Commands & Status
|
||||||
|
=================
|
||||||
|
|
||||||
|
Finit also implements a modern API to query status, and start/stop
|
||||||
|
services, called `initctl`. Unlike `telinit` the `initctl` tool does
|
||||||
|
not return until the given command has fully completed.
|
||||||
|
|
||||||
|
```
|
||||||
|
Usage: initctl [OPTIONS] [COMMAND]
|
||||||
|
|
||||||
|
Options:
|
||||||
|
-b, --batch Batch mode, no screen size probing
|
||||||
|
-c, --create Create missing paths (and files) as needed
|
||||||
|
-f, --force Ignore missing files and arguments, never prompt
|
||||||
|
-h, --help This help text
|
||||||
|
-j, --json JSON output in 'status' and 'cond' commands
|
||||||
|
-1, --once Only one lap in commands like 'top'
|
||||||
|
-p, --plain Use plain table headings, no ctrl chars
|
||||||
|
-q, --quiet Silent, only return status of command
|
||||||
|
-t, --no-heading Skip table headings
|
||||||
|
-v, --verbose Verbose output
|
||||||
|
-V, --version Show program version
|
||||||
|
|
||||||
|
Commands:
|
||||||
|
debug Toggle Finit (daemon) debug
|
||||||
|
help This help text
|
||||||
|
version Show program version
|
||||||
|
|
||||||
|
ls | list List all .conf in /etc/finit.d
|
||||||
|
create <CONF> Create .conf in /etc/finit.d/available
|
||||||
|
delete <CONF> Delete .conf in /etc/finit.d/available
|
||||||
|
show <CONF> Show .conf in /etc/finit.d/available
|
||||||
|
edit <CONF> Edit .conf in /etc/finit.d/available
|
||||||
|
touch <CONF> Change .conf in /etc/finit.d/available
|
||||||
|
enable <CONF> Enable .conf in /etc/finit.d/available
|
||||||
|
disable <CONF> Disable .conf in /etc/finit.d/enabled
|
||||||
|
reload Reload *.conf in /etc/finit.d (activate changes)
|
||||||
|
|
||||||
|
cond set <COND> Set (assert) user-defined conditions +usr/COND
|
||||||
|
cond get <COND> Get status of user-defined condition, see $? and -v
|
||||||
|
cond clear <COND> Clear (deassert) user-defined conditions -usr/COND
|
||||||
|
cond status Show condition status, default cond command
|
||||||
|
cond dump [TYPE] Dump all, or a type of, conditions and their status
|
||||||
|
|
||||||
|
log [NAME] Show ten last Finit, or NAME, messages from syslog
|
||||||
|
start <NAME>[:ID] Start service by name, with optional ID
|
||||||
|
stop <NAME>[:ID] Stop/Pause a running service by name
|
||||||
|
reload <NAME>[:ID] Reload service as if .conf changed (SIGHUP or restart)
|
||||||
|
This allows restart of run/tasks that have already run
|
||||||
|
Note: Finit .conf file(s) are *not* reloaded!
|
||||||
|
restart <NAME>[:ID] Restart (stop/start) service by name
|
||||||
|
signal <NAME>[:ID] <S> Send signal S to service by name, with optional ID
|
||||||
|
ident [NAME] Show matching identities for NAME, or all
|
||||||
|
status <NAME>[:ID] Show service status, by name
|
||||||
|
status Show status of services, default command
|
||||||
|
|
||||||
|
cgroup List cgroup config overview
|
||||||
|
ps List processes based on cgroups
|
||||||
|
top Show top-like listing based on cgroups
|
||||||
|
|
||||||
|
plugins List installed plugins
|
||||||
|
|
||||||
|
runlevel [0-9] Show or set runlevel: 0 halt, 6 reboot
|
||||||
|
reboot Reboot system
|
||||||
|
halt Halt system
|
||||||
|
poweroff Halt and power off system
|
||||||
|
suspend Suspend system
|
||||||
|
|
||||||
|
utmp show Raw dump of UTMP/WTMP db
|
||||||
|
```
|
||||||
|
|
||||||
|
For services *not* supporting `SIGHUP` the `<!>` notation in the .conf
|
||||||
|
file must be used to tell Finit to stop and start it on `reload` and
|
||||||
|
`runlevel` changes. If `<>` holds more [conditions](conditions.md),
|
||||||
|
these will also affect how a service is maintained.
|
||||||
|
|
||||||
|
> [!NOTE]
|
||||||
|
> Even though it is possible to start services not belonging in the
|
||||||
|
> 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.
|
||||||
|
|
||||||
|
The `status` command is the default, it displays a quick overview of all
|
||||||
|
monitored run/task/services. Here we call `initctl -p`, suitable for
|
||||||
|
scripting and documentation:
|
||||||
|
|
||||||
|
```
|
||||||
|
alpine:~# initctl -p
|
||||||
|
PID IDENT STATUS RUNLEVELS DESCRIPTION
|
||||||
|
======================================================================
|
||||||
|
1506 acpid running [---2345----] ACPI daemon
|
||||||
|
1509 crond running [---2345----] Cron daemon
|
||||||
|
1489 dropbear running [---2345----] Dropbear SSH daemon
|
||||||
|
1511 klogd running [S-12345----] Kernel log daemon
|
||||||
|
1512 ntpd running [---2345----] NTP daemon
|
||||||
|
1473 syslogd running [S-12345----] Syslog daemon
|
||||||
|
|
||||||
|
alpine:~# initctl -pv
|
||||||
|
PID IDENT STATUS RUNLEVELS COMMAND
|
||||||
|
======================================================================
|
||||||
|
1506 acpid running [---2345----] acpid -f
|
||||||
|
1509 crond running [---2345----] crond -f -S $CRON_OPTS
|
||||||
|
1489 dropbear running [---2345----] dropbear -R -F $DROPBEAR_OPTS
|
||||||
|
1511 klogd running [S-12345----] klogd -n $KLOGD_OPTS
|
||||||
|
1512 ntpd running [---2345----] ntpd -n $NTPD_OPTS
|
||||||
|
1473 syslogd running [S-12345----] syslogd -n
|
||||||
|
```
|
||||||
|
|
||||||
|
The environment variables to each of the services above are read from,
|
||||||
|
in the case of Alpine Linux, `/etc/conf.d/`. Other distributions may
|
||||||
|
have other directories, e.g., Debian use `/etc/default/`.
|
||||||
|
|
||||||
|
The `status` command takes an optional `NAME:ID` argument. Here we
|
||||||
|
check the status of `dropbear`, which only has one instance in this
|
||||||
|
system:
|
||||||
|
|
||||||
|
```
|
||||||
|
alpine:~# initctl -p status dropbear
|
||||||
|
Status : running
|
||||||
|
Identity : dropbear
|
||||||
|
Description : Dropbear SSH daemon
|
||||||
|
Origin : /etc/finit.d/enabled/dropbear.conf
|
||||||
|
Environment : -/etc/conf.d/dropbear
|
||||||
|
Condition(s):
|
||||||
|
Command : dropbear -R -F $DROPBEAR_OPTS
|
||||||
|
PID file : !/run/dropbear.pid
|
||||||
|
PID : 1485
|
||||||
|
User : root
|
||||||
|
Group : root
|
||||||
|
Uptime : 2 hour 46 min 56 sec
|
||||||
|
Runlevels : [---2345----]
|
||||||
|
Memory : 1.2M
|
||||||
|
CGroup : /system/dropbear cpu 0 [100, max] mem [--.--, max]
|
||||||
|
|- 1485 dropbear -R -F
|
||||||
|
|- 2634 dropbear -R -F
|
||||||
|
|- 2635 ash
|
||||||
|
`- 2652 initctl -p status dropbear
|
||||||
|
|
||||||
|
Apr 8 12:19:49 alpine authpriv.info dropbear[1485]: Not backgrounding
|
||||||
|
Apr 8 12:37:45 alpine authpriv.info dropbear[2300]: Child connection from 192.168.121.1:47834
|
||||||
|
Apr 8 12:37:46 alpine authpriv.notice dropbear[2300]: Password auth succeeded for 'root' from 192.168.121.1:47834
|
||||||
|
Apr 8 12:37:46 alpine authpriv.info dropbear[2300]: Exit (root) from <192.168.121.1:47834>: Disconnect received
|
||||||
|
Apr 8 15:02:11 alpine authpriv.info dropbear[2634]: Child connection from 192.168.121.1:48576
|
||||||
|
Apr 8 15:02:12 alpine authpriv.notice dropbear[2634]: Password auth succeeded for 'root' from 192.168.121.1:48576
|
||||||
|
```
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
keventd
|
||||||
|
=======
|
||||||
|
|
||||||
|
The kernel event daemon bundled with Finit is a simple uevent monitor
|
||||||
|
for `/sys/class/power_supply`. It provides the `sys/pwr/ac` condition,
|
||||||
|
which can be useful to prevent power hungry services like anacron to run
|
||||||
|
when a laptop is only running on battery, for instance.
|
||||||
|
|
||||||
|
Since keventd is not an integral part of Finit yet it is not enabled by
|
||||||
|
default. Enable it using `./configure --with-keventd`. The bundled
|
||||||
|
`contrib/` build scripts for Debian, Alpine, and Void have this enabled.
|
||||||
|
|
||||||
|
This daemon is planned to be extended with monitoring of other uevents,
|
||||||
|
patches and ideas are welcome in the issue tracker.
|
||||||
@@ -1,12 +1,6 @@
|
|||||||
Hooks & Plugins
|
Hooks & Plugins
|
||||||
===============
|
===============
|
||||||
|
|
||||||
* [Plugins](#plugins)
|
|
||||||
* [Hooks](#hooks)
|
|
||||||
* [Bootstrap Hooks](#bootstrap-hooks)
|
|
||||||
* [Runtime Hooks](#runtime-hooks)
|
|
||||||
* [Shutdown Hooks](#shutdown-hooks)
|
|
||||||
|
|
||||||
Finit can be extended to add general functionality in the form of I/O
|
Finit can be extended to add general functionality in the form of I/O
|
||||||
monitors, or hook plugins. It is even possible to run scripts at these
|
monitors, or hook plugins. It is even possible to run scripts at these
|
||||||
hook points, see below.
|
hook points, see below.
|
||||||
@@ -65,7 +59,7 @@ For your convenience a set of *optional* plugins are available:
|
|||||||
Enabled by default.
|
Enabled by default.
|
||||||
|
|
||||||
> [!TIP]
|
> [!TIP]
|
||||||
> See the [Services](config.md#services) section in the configuration
|
> See the [Services](config/services.md) section in the configuration
|
||||||
> guide for an example how to run `mdevd`, alternative to plain mdev.
|
> guide for an example how to run `mdevd`, alternative to plain mdev.
|
||||||
|
|
||||||
* *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.
|
||||||
@@ -135,7 +129,7 @@ the second is the condition name and hook script path. A hook script is
|
|||||||
a plain shell script, or program, that does a very small dedicated job
|
a plain shell script, or program, that does a very small dedicated job
|
||||||
at the below hook points.
|
at the below hook points.
|
||||||
|
|
||||||
See [Run-parts Scripts](config.md#run-parts-scripts) for details on the
|
See [Run-parts Scripts](config/runparts.md) for details on the
|
||||||
requirements, possibilities, and *limitations* of hook scripts.
|
requirements, possibilities, and *limitations* of hook scripts.
|
||||||
|
|
||||||
All hook scripts are called with at least one environment variable set,
|
All hook scripts are called with at least one environment variable set,
|
||||||
|
|||||||
@@ -0,0 +1,25 @@
|
|||||||
|
Requirements
|
||||||
|
============
|
||||||
|
|
||||||
|
Finit is capable of running on both desktop/server systems with udev and
|
||||||
|
embedded systems that usually come with BusyBox mdev. Some systems have
|
||||||
|
systemd-udev or eudev today instead of the original udev, Finit probes
|
||||||
|
for all of them at runtime and expects `/dev/` to be a writable file
|
||||||
|
system using `devtmpfs`. It is also possible to run on a statically set
|
||||||
|
up `/dev` if needed. It is however not a good idea to have both udev
|
||||||
|
and mdev installed at the same time, this will lead to unpredictable
|
||||||
|
results.
|
||||||
|
|
||||||
|
At boot Finit calls either `mdev` or `udevd` to populate `/dev`, this is
|
||||||
|
done slightly differently and on systems with udev you might want to add
|
||||||
|
the following one-shot task early in your `/etc/finit.conf`:
|
||||||
|
|
||||||
|
```conf
|
||||||
|
run [S] udevadm settle --timeout=120 -- Waiting for udev
|
||||||
|
```
|
||||||
|
|
||||||
|
Finit has a built-in Getty for TTYs, but requires a working `/bin/login`
|
||||||
|
or `/bin/sh`, if no TTYs are configured in `/etc/finit.conf`.
|
||||||
|
|
||||||
|
For a fully operational system `/var`, `/run` and `/tmp` must be set up
|
||||||
|
properly in `/etc/fstab` -- which is iterated over at boot.
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
Runlevel Support
|
||||||
|
================
|
||||||
|
|
||||||
|
Basic support for [runlevels][5] is included in Finit from v1.8. By
|
||||||
|
default all services, tasks, run commands and TTYs listed without a set
|
||||||
|
of runlevels get a default set `[234]` assigned. The default runlevel
|
||||||
|
after boot is 2.
|
||||||
|
|
||||||
|
Finit supports runlevels 0-9, and S, with 0 reserved for halt, 6 reboot
|
||||||
|
and S for services that only run at bootstrap. Runlevel 1 is the single
|
||||||
|
user level, where usually no networking is enabled. In Finit this is
|
||||||
|
more of a policy for the user to define. Normally only runlevels 1-6
|
||||||
|
are used, and even more commonly, only the default runlevel is used.
|
||||||
|
|
||||||
|
To specify an allowed set of runlevels for a `service`, `run` command,
|
||||||
|
`task`, or `tty`, add `[NNN]` to your `/etc/finit.conf`, like this:
|
||||||
|
|
||||||
|
```
|
||||||
|
service [S12345] syslogd -n -x -- System log daemon
|
||||||
|
run [S] /etc/init.d/acpid start -- Starting ACPI Daemon
|
||||||
|
task [S] /etc/init.d/kbd start -- Preparing console
|
||||||
|
service [S12345] <pid/syslogd> klogd -n -x -- Kernel log daemon
|
||||||
|
|
||||||
|
tty [12345] /dev/tty1
|
||||||
|
tty [2] /dev/tty2
|
||||||
|
tty [2] /dev/tty3
|
||||||
|
tty [2] /dev/tty4
|
||||||
|
tty [2] /dev/tty5
|
||||||
|
tty [2] /dev/tty6
|
||||||
|
```
|
||||||
|
|
||||||
|
In this example syslogd is first started, in parallel, and then acpid is
|
||||||
|
called using a conventional SysV init script. It is called with the run
|
||||||
|
command, meaning the following task command to start the kbd script is
|
||||||
|
not called until the acpid init script has fully completed. Then the
|
||||||
|
keyboard setup script is called in parallel with klogd as a monitored
|
||||||
|
service.
|
||||||
|
|
||||||
|
Again, tasks and services are started in parallel, while run commands
|
||||||
|
are called in the order listed and subsequent commands are not started
|
||||||
|
until a run command has completed. Also, task and run commands are run
|
||||||
|
in a shell, so pipes and redirects can be used.
|
||||||
|
|
||||||
|
The following examples illustrate this. Bootstrap task and run commands
|
||||||
|
are also removed when they have completed, `initctl show` will not list
|
||||||
|
them.
|
||||||
|
|
||||||
|
```
|
||||||
|
task [S] echo "foo" | cat >/tmp/bar
|
||||||
|
run [S] echo "$HOME" >/tmp/secret
|
||||||
|
```
|
||||||
|
|
||||||
|
Switching between runlevels can be done by calling init with a single
|
||||||
|
argument, e.g. <kbd>init 5</kbd>, or using `initctl runlevel 5`, both
|
||||||
|
switch to runlevel 5. When changing runlevels Finit also automatically
|
||||||
|
reloads all `.conf` files in the `/etc/finit.d/` directory. So if you
|
||||||
|
want to set a new system config, switch to runlevel 1, change all config
|
||||||
|
files in the system, and touch all `.conf` files in `/etc/finit.d`
|
||||||
|
before switching back to the previous runlevel again — that way Finit
|
||||||
|
can both stop old services and start any new ones for you, without
|
||||||
|
rebooting the system.
|
||||||
|
|
||||||
|
|
||||||
|
[5]: https://en.wikipedia.org/wiki/Runlevel
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
Runparts & `/etc/rc.local`
|
||||||
|
==========================
|
||||||
|
|
||||||
|
At the end of the boot, when all bootstrap (`S`) tasks and services have
|
||||||
|
started, but not networking, Finit calls its built-in [run-parts(8)][]
|
||||||
|
command on any configured `runparts <DIR>` directory. This happens just
|
||||||
|
before changing to the configured runlevel (default 2). (Networking is
|
||||||
|
enabled just prior to changing from single user mode.)
|
||||||
|
|
||||||
|
```shell
|
||||||
|
runparts /etc/rc.d/
|
||||||
|
```
|
||||||
|
|
||||||
|
Right after the runlevel change when all services have started properly,
|
||||||
|
`/etc/rc.local` is called.
|
||||||
|
|
||||||
|
No configuration stanza in `/etc/finit.conf` is required for `rc.local`.
|
||||||
|
If it exists and is an executable shell script Finit calls it at the very
|
||||||
|
end of the boot, before calling the `HOOK_SYSTEM_UP`. See more in the
|
||||||
|
[Hook Scripts](plugins.md#hooks) section.
|
||||||
|
|
||||||
|
|
||||||
|
### Limitations
|
||||||
|
|
||||||
|
It is not possible to call Finit via signals or use `initctl` in any
|
||||||
|
runparts or `/etc/rc.local` script. This because Finit is single
|
||||||
|
threaded and is calling these scripts in a blocking fashion at the end
|
||||||
|
of runlevel S, at which point the event loop has not yet been started.
|
||||||
|
|
||||||
|
The event loop is the whole thing which Finit is built around, except
|
||||||
|
for runlevel S, which remains a slow procession through a lot of set up,
|
||||||
|
with a few hooks and blocking call outs to external scripts.
|
||||||
|
|
||||||
|
However, not all `initctl` commands are prohibited. Supported commands:
|
||||||
|
|
||||||
|
- `initctl cond`: only operate on files in `/run/finit/cond`
|
||||||
|
- `initctl enable/disable`: enabled run/task/service is activated on
|
||||||
|
the runlevel change from S to 2
|
||||||
|
- `initctl touch/show/create/delete/list`: `create`, provided the
|
||||||
|
non-interactive mode is used, again changes take effect in the
|
||||||
|
runlevel change directly after bootstrap
|
||||||
|
- `initctl -f reboot/poweroff/halt`: provided the `-f` flag is used to
|
||||||
|
force direct kernel commands
|
||||||
|
|
||||||
|
> [!TIP]
|
||||||
|
> you can set a `usr/` condition in `/etc/rc.local` and have a
|
||||||
|
> service/task in runlevel 2 depend on it to execute.
|
||||||
|
|
||||||
|
[run-parts(8)]: https://manpages.debian.org/cgi-bin/man.cgi?query=run-parts
|
||||||
@@ -1,15 +1,13 @@
|
|||||||
Finit Services
|
|
||||||
==============
|
|
||||||
|
|
||||||
Starting & Monitoring
|
Starting & Monitoring
|
||||||
---------------------
|
=====================
|
||||||
|
|
||||||
Finit can start and monitor the following types of daemons:
|
Finit can start and monitor the following types of daemons:
|
||||||
|
|
||||||
* Forks to background, creates a PID file
|
* Forks to background, creates a PID file
|
||||||
* Runs in foreground:
|
* Runs in foreground and signals ready by:
|
||||||
- creates a PID file
|
- creating a PID file
|
||||||
- does not create a PID file -- Finit can create it for you (optional)
|
- does not create a PID file -- Finit can create it for you (optional)
|
||||||
|
- [other mechanism][1] (systemd, s6)
|
||||||
|
|
||||||
Finit can *not* start and monitor a daemon that:
|
Finit can *not* start and monitor a daemon that:
|
||||||
|
|
||||||
@@ -24,9 +22,10 @@ Finit can *not* start and monitor a daemon that:
|
|||||||
|
|
||||||
> [!NOTE]
|
> [!NOTE]
|
||||||
> PID files is one mechanism used to assert conditions to synchronize
|
> PID files is one mechanism used to assert conditions to synchronize
|
||||||
> the start and stop of other, dependent, services.
|
> the start and stop of other, dependent, services. Other mechanisms
|
||||||
|
> are described in the [Service Synchronization][1] section.
|
||||||
|
|
||||||
### Forks to Background w/ PID File
|
### Forks to bg w/ PID file
|
||||||
|
|
||||||
There are two syntax variants, type 1 and type 2. The former is the
|
There are two syntax variants, type 1 and type 2. The former is the
|
||||||
traditional one used also for `sysv` start/stop scripts, and the latter
|
traditional one used also for `sysv` start/stop scripts, and the latter
|
||||||
@@ -40,49 +39,19 @@ In this example the resulting files to watch for are `/run/serv.pid` and
|
|||||||
`/var/run/serv.pid`, respectively. On most modern Linux systems this is
|
`/var/run/serv.pid`, respectively. On most modern Linux systems this is
|
||||||
the same directory (`/var/run` is a symlink to `../run`).
|
the same directory (`/var/run` is a symlink to `../run`).
|
||||||
|
|
||||||
### Runs in Foreground w/ PID File
|
### Runs in fg w/ PID file
|
||||||
|
|
||||||
service serv -n -p -- Foreground service w/ PID file
|
service serv -n -p -- Foreground service w/ PID file
|
||||||
|
|
||||||
### Runs in Foreground w/o PID File
|
### Runs in fg w/o PID file
|
||||||
|
|
||||||
Same as previous, but we tell Finit to create the PID file, because we
|
Same as previous, but we tell Finit to create the PID file, because we
|
||||||
need it to synchronize start/stop of a dependent service.
|
need it to synchronize start/stop of a dependent service.
|
||||||
|
|
||||||
service pid:/run/serv.pid serv -n -- Foreground service w/o PID file
|
service pid:/run/serv.pid serv -n -- Foreground service w/o PID file
|
||||||
|
|
||||||
### Runs in Foreground w/ Custom PID File
|
### Runs in fg w/ custom PID file
|
||||||
|
|
||||||
service pid:/run/servy.pid serv -n -p -P /run/servy.pid -- Foreground service w/ custom PID file
|
service pid:/run/servy.pid serv -n -p -P /run/servy.pid -- Foreground service w/ custom PID file
|
||||||
|
|
||||||
|
[1]: config/service-sync.md
|
||||||
State Machine
|
|
||||||
-------------
|
|
||||||
|
|
||||||
A service is bound to a state machine that is in one of six (6) states.
|
|
||||||
For `run`s and `task`s there is an additional end state called `DONE`,
|
|
||||||
not shown in the diagram for brevity. Services start in the `HALTED`
|
|
||||||
state.
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
The current state depends on the two following conditions:
|
|
||||||
|
|
||||||
* `E`: Service enabled. In order for `E` to be satisfied, the service
|
|
||||||
must be allowed to run in the current runlevel and not be stopped.
|
|
||||||
|
|
||||||
A service may be stopped, or blocked, for several reasons:
|
|
||||||
|
|
||||||
- The user has manually stopped the service using `initctl stop NAME`
|
|
||||||
- The program exits immediately. I.e. keeps crashing (make sure to use
|
|
||||||
the 'run this service in the foreground' command line option)
|
|
||||||
- The binary is missing in the filesystem
|
|
||||||
|
|
||||||
* `C`: Service conditions are satisfied:
|
|
||||||
|
|
||||||
- `on` (+): The condition is asserted.
|
|
||||||
- `off` (-): The condition is deasserted.
|
|
||||||
- `flux` (~): The condition state is unknown.
|
|
||||||
|
|
||||||
For a detailed description of conditions, and how to debug them,
|
|
||||||
see the [Finit Conditions](conditions.md) document.
|
|
||||||
|
|||||||
@@ -0,0 +1,30 @@
|
|||||||
|
State Machine
|
||||||
|
=============
|
||||||
|
|
||||||
|
A service is bound to a state machine that is in one of ten states. For
|
||||||
|
run/tasks there is an additional end state called `DONE`. All processes
|
||||||
|
managed by Finit start in the `HALTED` state. The image shows how both
|
||||||
|
conditions and commands drive the machine.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
The current state depends on the two following conditions:
|
||||||
|
|
||||||
|
* `E`: Service enabled. In order for `E` to be satisfied, the service
|
||||||
|
must be allowed to run in the current runlevel and not be stopped.
|
||||||
|
|
||||||
|
A service may be stopped, or blocked, for several reasons:
|
||||||
|
|
||||||
|
- The user has manually stopped the service using `initctl stop NAME`
|
||||||
|
- The program exits immediately. I.e. keeps crashing (make sure to use
|
||||||
|
the 'run this service in the foreground' command line option)
|
||||||
|
- The binary is missing in the filesystem
|
||||||
|
|
||||||
|
* `C`: Service conditions are satisfied:
|
||||||
|
|
||||||
|
- `on` (+): The condition is asserted.
|
||||||
|
- `off` (-): The condition is deasserted.
|
||||||
|
- `flux` (~): The condition state is unknown.
|
||||||
|
|
||||||
|
For a detailed description of conditions, and how to debug them,
|
||||||
|
see the [Finit Conditions](conditions.md) document.
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
Bundled Watchdog Daemon
|
||||||
|
=======================
|
||||||
|
|
||||||
|
When built `--with-watchdog` a separate service is built and installed
|
||||||
|
in `/libexec/finit/watchdogd`. If this exists at runtime, and the WDT
|
||||||
|
device node exists, Finit will start it and treat it as the elected
|
||||||
|
watchdog service to delegate its reboot to. This delegation is to
|
||||||
|
ensure that the system is rebooted by a hardware watchdog timer -- on
|
||||||
|
many embedded systems this is crucial to ensure all circuits on the
|
||||||
|
board are properly reset for the next boot, in effect ensuring the
|
||||||
|
system works the same after both a power-on and reboot event.
|
||||||
|
|
||||||
|
The delegation is performed at the very last steps of system shutdown,
|
||||||
|
if reboot has been selected and an elected watchdog is known, first a
|
||||||
|
`SIGPWR` is sent to advise watchdogd of the pending reboot. Then, when
|
||||||
|
the necessary steps of preparing the system for shutdown (umount etc.)
|
||||||
|
are completed, Finit sends `SIGTERM` to watchdogd and puts itself in a
|
||||||
|
10 sec timeout loop waiting for the WDT to reset the board. If a reset
|
||||||
|
is not done before the timeout, Finit falls back to`reboot(RB_AUTOBOOT)`
|
||||||
|
which tells the kernel to do the reboot.
|
||||||
|
|
||||||
|
An external watchdog service can also be used. The more advanced cousin
|
||||||
|
[watchdogd](https://github.com/troglobit/watchdogd/) is the recommended
|
||||||
|
option here. It can register itself with Finit using the same IPC as
|
||||||
|
`initctl`. If the bundled watchdogd is running a hand-over takes place,
|
||||||
|
so it's safe to have both services installed on a system. For the
|
||||||
|
hand-over to work it requires that the WDT driver supports the safe exit
|
||||||
|
functionality where `"V"` is written to the device before closing the
|
||||||
|
device descriptor. If the kernel driver has been built without this,
|
||||||
|
the only option is to remove `/libexec/finit/watchdogd` or build without
|
||||||
|
it at configure time.
|
||||||
@@ -2,6 +2,8 @@
|
|||||||
lib_LTLIBRARIES = libsystemd.la
|
lib_LTLIBRARIES = libsystemd.la
|
||||||
libsystemd_la_SOURCES = sd-daemon.c sd-daemon.h
|
libsystemd_la_SOURCES = sd-daemon.c sd-daemon.h
|
||||||
libsystemd_la_LDFLAGS = -version-info 0:0:0
|
libsystemd_la_LDFLAGS = -version-info 0:0:0
|
||||||
|
libsystemd_la_CFLAGS = $(lite_CFLAGS)
|
||||||
|
libsystemd_la_LIBADD = $(lite_LIBS)
|
||||||
|
|
||||||
# pkg-config support
|
# pkg-config support
|
||||||
pkgconfigdir = $(libdir)/pkgconfig
|
pkgconfigdir = $(libdir)/pkgconfig
|
||||||
@@ -9,4 +11,4 @@ pkgconfig_DATA = libsystemd.pc
|
|||||||
|
|
||||||
# Install header to systemd/ subdirectory
|
# Install header to systemd/ subdirectory
|
||||||
systemddir = $(includedir)/systemd
|
systemddir = $(includedir)/systemd
|
||||||
systemd_HEADERS = sd-daemon.h
|
systemd_HEADERS = sd-daemon.h
|
||||||
|
|||||||
@@ -23,6 +23,11 @@
|
|||||||
#include <sys/un.h>
|
#include <sys/un.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#ifdef _LIBITE_LITE
|
||||||
|
# include <libite/lite.h>
|
||||||
|
#else
|
||||||
|
# include <lite/lite.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "sd-daemon.h"
|
#include "sd-daemon.h"
|
||||||
|
|
||||||
@@ -78,10 +83,9 @@ int sd_notify(int unset_environment, const char *state)
|
|||||||
unsetenv("NOTIFY_SOCKET");
|
unsetenv("NOTIFY_SOCKET");
|
||||||
|
|
||||||
written = write(sd, state, len);
|
written = write(sd, state, len);
|
||||||
if (written != (ssize_t) len) {
|
close(sd);
|
||||||
close(sd);
|
if (written != (ssize_t) len)
|
||||||
return written < 0 ? -errno : -EPROTO;
|
return written < 0 ? -errno : -EPROTO;
|
||||||
}
|
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
.\" First parameter, NAME, should be all caps
|
.\" First parameter, NAME, should be all caps
|
||||||
.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection
|
.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection
|
||||||
.\" other parameters are allowed: see man(7), man(1)
|
.\" other parameters are allowed: see man(7), man(1)
|
||||||
.Dd Apr 22, 2023
|
.Dd Jul 9, 2025
|
||||||
.\" Please adjust this date whenever revising the manpage.
|
.\" Please adjust this date whenever revising the manpage.
|
||||||
.Dt FINIT 8 SMM
|
.Dt FINIT 8 SMM
|
||||||
.Os Linux
|
.Os Linux
|
||||||
@@ -10,30 +10,66 @@
|
|||||||
.Nm finit
|
.Nm finit
|
||||||
.Nd Fast init for Linux systems
|
.Nd Fast init for Linux systems
|
||||||
.Sh SYNOPSIS
|
.Sh SYNOPSIS
|
||||||
.Nm /sbin/finit
|
.Nm /sbin/finit --
|
||||||
.Op --
|
|
||||||
.Op debug
|
.Op debug
|
||||||
.Op finit.cond=foo[,bar[,baz]]
|
|
||||||
.Op finit.config=/path/to/alt/finit.conf
|
|
||||||
.Op finit.debug
|
|
||||||
.Op finit.fstab=/etc/fstab.alt
|
|
||||||
.Op finit.status=<on,off>
|
|
||||||
.Op finit.status_style=<classic,modern>
|
|
||||||
.Op loglevel=<0-7>
|
|
||||||
.Op panic=SEC
|
|
||||||
.Op quiet
|
.Op quiet
|
||||||
.Op rescue | recover
|
.Op rescue | recover
|
||||||
.Op single | S
|
.Op single | S
|
||||||
|
.Op panic=SEC
|
||||||
|
.Op loglevel=<0-7>
|
||||||
|
.Op fsck.mode=[auto,skip,force]
|
||||||
|
.Op fsck.repair=[no,yes,preen]
|
||||||
|
.Op finit.debug=<true,false>
|
||||||
|
.Op finit.fstab=/path/to/fstab
|
||||||
|
.Op finit.cond=foo[,bar[,baz]]
|
||||||
|
.Op finit.config=/path/to/finit.conf
|
||||||
|
.Op finit.status_style=<classic,modern>
|
||||||
|
.Op finit.status=<on,off>
|
||||||
.Nm /sbin/telinit
|
.Nm /sbin/telinit
|
||||||
.Op Fl hv
|
.Op Fl hv
|
||||||
.Op q | Q | 0-9
|
.Op q | Q | s | S | 0-9
|
||||||
.Sh DESCRIPTION
|
.Sh DESCRIPTION
|
||||||
Fast init for Linux systems. Reverse engineered from the EeePC
|
Fast init for Linux systems. Reverse engineered from the EeePC
|
||||||
fastinit, 10+ years ago by Claudio Matsuoka, "gaps filled with frog
|
fastinit, 10+ years ago by Claudio Matsuoka, "gaps filled with frog
|
||||||
DNA ...". Focus is on small and embedded systems, although Finit is
|
DNA ...". Focus is on small and embedded systems, although Finit is
|
||||||
fully usable on server and desktop systems as well.
|
fully usable on server and desktop systems as well.
|
||||||
|
.Sh OPTIONS
|
||||||
|
When
|
||||||
|
.Sy not
|
||||||
|
started as PID 1,
|
||||||
|
.Nm
|
||||||
|
behaves like
|
||||||
|
.Nm telinit ,
|
||||||
|
following classic UNIX command line syntax. The options are:
|
||||||
.Pp
|
.Pp
|
||||||
Features include:
|
.Bl -tag -width Ds -compact -offset indent
|
||||||
|
.It Fl h
|
||||||
|
Show built-in help text.
|
||||||
|
.It Fl v
|
||||||
|
Show program version.
|
||||||
|
.El
|
||||||
|
.Pp
|
||||||
|
More options are implemented for SysV init support, but are ignored.
|
||||||
|
.Sh ARGUMENTS
|
||||||
|
When
|
||||||
|
.Sy not
|
||||||
|
started as PID 1,
|
||||||
|
.Nm ,
|
||||||
|
or
|
||||||
|
.Nm telinit ,
|
||||||
|
take these arguments:
|
||||||
|
.Pp
|
||||||
|
.Bl -tag -width Ds -compact -offset indent
|
||||||
|
.It q | Q
|
||||||
|
Reload configuration, same as
|
||||||
|
.Cm initctl reload .
|
||||||
|
.It 0 - 9
|
||||||
|
Go to runlevel N, same as
|
||||||
|
.Cm initctl reload N .
|
||||||
|
.It s | S
|
||||||
|
Go to single user mode, runlevel 1.
|
||||||
|
.El
|
||||||
|
.Sh FEATURES
|
||||||
.Bl -bullet -width 1n -compact
|
.Bl -bullet -width 1n -compact
|
||||||
.It
|
.It
|
||||||
Runlevels, defined per service
|
Runlevels, defined per service
|
||||||
@@ -93,6 +129,27 @@ Enable kernel debug. Debug messages are printed to the console until
|
|||||||
Finit starts up, unless
|
Finit starts up, unless
|
||||||
.Cm loglevel=7
|
.Cm loglevel=7
|
||||||
(below) is used.
|
(below) is used.
|
||||||
|
.It Cm fsck.mode=<auto,force,skip>
|
||||||
|
Defaults to
|
||||||
|
.Cm auto ,
|
||||||
|
unless Finit is built with
|
||||||
|
.Cm configure --enable-fastboot ,
|
||||||
|
in which case the default is
|
||||||
|
.Cm skip .
|
||||||
|
.It Cm fsck.repair=<preen,yes,no>
|
||||||
|
Defaults to
|
||||||
|
.Cm preen ,
|
||||||
|
unless Finit is built with
|
||||||
|
.Cm configure --enable-fsckfix ,
|
||||||
|
in which case the default is
|
||||||
|
.Cm yes .
|
||||||
|
This configure option also sets
|
||||||
|
.Cm fsck.mode=force ,
|
||||||
|
unless fastboot is also enabled. I.e.,
|
||||||
|
.Cm configure --enable-fastboot
|
||||||
|
build option overrides the
|
||||||
|
.Cm fsck.mode
|
||||||
|
default value.
|
||||||
.It Cm finit.cond=foo[,bar[,baz]]
|
.It Cm finit.cond=foo[,bar[,baz]]
|
||||||
set
|
set
|
||||||
.Cm <boot/foo>
|
.Cm <boot/foo>
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
.\" First parameter, NAME, should be all caps
|
.\" First parameter, NAME, should be all caps
|
||||||
.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection
|
.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection
|
||||||
.\" other parameters are allowed: see man(7), man(1)
|
.\" other parameters are allowed: see man(7), man(1)
|
||||||
.Dd July 11, 2023
|
.Dd July 10, 2025
|
||||||
.Dt FINIT.CONF 5 SMM
|
.Dt FINIT.CONF 5 SMM
|
||||||
.Os Linux
|
.Os Linux
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
@@ -178,7 +178,7 @@ Similar to
|
|||||||
.Cm service
|
.Cm service
|
||||||
is the
|
is the
|
||||||
.Cm sysv
|
.Cm sysv
|
||||||
stanza, which can be used to call SysV style start/stop scripts. The
|
directive, which can be used to call SysV style start/stop scripts. The
|
||||||
primary intention for this command is to be able to re-use traditional
|
primary intention for this command is to be able to re-use traditional
|
||||||
SysV init scripts in Linux distributions.
|
SysV init scripts in Linux distributions.
|
||||||
.Pp
|
.Pp
|
||||||
@@ -194,7 +194,7 @@ on
|
|||||||
.Cm initctl reload .
|
.Cm initctl reload .
|
||||||
Similar to how
|
Similar to how
|
||||||
.Cm service
|
.Cm service
|
||||||
stanzas work.
|
directives work.
|
||||||
.Pp
|
.Pp
|
||||||
Forking services started with
|
Forking services started with
|
||||||
.Cm sysv
|
.Cm sysv
|
||||||
@@ -416,7 +416,30 @@ The post:script is called with the same environment variables
|
|||||||
for the
|
for the
|
||||||
.Cm EXIT_CODE
|
.Cm EXIT_CODE
|
||||||
variable which is set to
|
variable which is set to
|
||||||
.Cm "crashed" .
|
.Cm "crashed"
|
||||||
|
.It Cm reload:'script [args]'
|
||||||
|
some services do not support SIGHUP but may have other ways to update
|
||||||
|
the configuration of a running daemon. When
|
||||||
|
.Cm reload:script
|
||||||
|
is defined it is preferred over SIGHUP. Like systemd,
|
||||||
|
.Nm finit
|
||||||
|
sets
|
||||||
|
.Cm $MAINPID
|
||||||
|
as a convenience to scripts, which in effect also allow
|
||||||
|
.Cm reload:'kill -HUP $MAINPID'
|
||||||
|
.It Cm stop:'script [args]'
|
||||||
|
Some services may require alternate methods to be stopped. When
|
||||||
|
.Cm stop:script
|
||||||
|
is defined it is preferred over SIGTERM and stop, for
|
||||||
|
.Cm service
|
||||||
|
and
|
||||||
|
.Cm sysv
|
||||||
|
directives, respectively.
|
||||||
|
Similar to
|
||||||
|
.Cm reload:script ,
|
||||||
|
.Nm finit
|
||||||
|
sets
|
||||||
|
.Cm $MAINPID .
|
||||||
.El
|
.El
|
||||||
.Pp
|
.Pp
|
||||||
When stopping a service (run/task/sysv/service), either manually or when
|
When stopping a service (run/task/sysv/service), either manually or when
|
||||||
@@ -535,7 +558,7 @@ size limit is reached.
|
|||||||
.It Cm tty Oo LVLS Oc Ao COND Ac Ar DEV Oo BAUD Oc Oo noclear Oc Oo nowait Oc Oo nologin Oc Oo TERM Oc
|
.It Cm tty Oo LVLS Oc Ao COND Ac Ar DEV Oo BAUD Oc Oo noclear Oc Oo nowait Oc Oo nologin Oc Oo TERM Oc
|
||||||
This form of the
|
This form of the
|
||||||
.Cm tty
|
.Cm tty
|
||||||
stanza uses the built-in getty on the given TTY device
|
directive uses the built-in getty on the given TTY device
|
||||||
.Ar DEV ,
|
.Ar DEV ,
|
||||||
in the given runlevels.
|
in the given runlevels.
|
||||||
.Ar DEV may be the special keyword
|
.Ar DEV may be the special keyword
|
||||||
@@ -545,8 +568,8 @@ useful on embedded systems.
|
|||||||
.Pp
|
.Pp
|
||||||
The default baud rate is 0, i.e., keep kernel default.
|
The default baud rate is 0, i.e., keep kernel default.
|
||||||
.Pp
|
.Pp
|
||||||
The `tty` stanza inherits runlevel, condition (and other feature)
|
The `tty` directive inherits runlevel, condition (and other feature)
|
||||||
parsing from the `service` stanza. So TTYs can run in one or many
|
parsing from the `service` directive. So TTYs can run in one or many
|
||||||
runlevels and depend on any condition supported by Finit. This is
|
runlevels and depend on any condition supported by Finit. This is
|
||||||
useful e.g. to depend on `<pid/elogind>` before starting a TTY.
|
useful e.g. to depend on `<pid/elogind>` before starting a TTY.
|
||||||
.Bd -unfilled -offset indent
|
.Bd -unfilled -offset indent
|
||||||
@@ -555,7 +578,7 @@ tty [12345] /dev/ttyAMA0 115200 noclear vt220
|
|||||||
.It Cm tty Oo LVLS Oc Ao COND Ac Ar CMD DEV Oo noclear Oc Oo nowait Oc
|
.It Cm tty Oo LVLS Oc Ao COND Ac Ar CMD DEV Oo noclear Oc Oo nowait Oc
|
||||||
This form of the
|
This form of the
|
||||||
.Cm tty
|
.Cm tty
|
||||||
stanza is for using an external getty, like agetty or the BusyBox getty.
|
directive is for using an external getty, like agetty or the BusyBox getty.
|
||||||
.Pp
|
.Pp
|
||||||
By default, these first two syntax variants
|
By default, these first two syntax variants
|
||||||
.Em clear
|
.Em clear
|
||||||
@@ -625,7 +648,7 @@ board bringup and system debugging it can come in handy.
|
|||||||
.Pp
|
.Pp
|
||||||
One can also use the
|
One can also use the
|
||||||
.Cm service
|
.Cm service
|
||||||
stanza to start a stand-alone shell:
|
directive to start a stand-alone shell:
|
||||||
.Bd -unfilled -offset indent
|
.Bd -unfilled -offset indent
|
||||||
service [12345] /bin/sh -l
|
service [12345] /bin/sh -l
|
||||||
.Ed
|
.Ed
|
||||||
@@ -650,9 +673,9 @@ is started to present a bare-bones root login prompt. If the root
|
|||||||
(uid:0, gid:0) user does not have a password set, no rescue is possible.
|
(uid:0, gid:0) user does not have a password set, no rescue is possible.
|
||||||
.El
|
.El
|
||||||
.Sh COMMAND MODIFIERS
|
.Sh COMMAND MODIFIERS
|
||||||
The run/task/tty/service/sysv stanzas take modifiers, or options, to
|
The run/task/tty/service/sysv directives take modifiers, or options, to
|
||||||
control their behavior. This section lists them with their limitations.
|
control their behavior. This section lists them with their limitations.
|
||||||
All modifiers must be placed between the stanza and its command.
|
All modifiers must be placed between the directive and its command.
|
||||||
.Bl -tag -width 1n
|
.Bl -tag -width 1n
|
||||||
.It Cm @user:group
|
.It Cm @user:group
|
||||||
Every
|
Every
|
||||||
@@ -946,9 +969,10 @@ or
|
|||||||
service [...] <...> cgroup.maint /path/to/foo args -- description
|
service [...] <...> cgroup.maint /path/to/foo args -- description
|
||||||
.Ed
|
.Ed
|
||||||
.Pp
|
.Pp
|
||||||
The latter form also allows per-stanza limits on the form:
|
The latter form also allows per-stanza limits on the form (notice the
|
||||||
|
single quotes for arguments that contain spaces):
|
||||||
.Bd -unfilled -offset indent
|
.Bd -unfilled -offset indent
|
||||||
service [...] <...> cgroup.maint:cpu.max:10000,mem.max:655360 /path/to/foo args -- description
|
service [...] <...> cgroup.maint:cpu.max:'200000 100000',mem.max:655360 /path/to/foo args -- description
|
||||||
.Ed
|
.Ed
|
||||||
.Pp
|
.Pp
|
||||||
Notice the comma separation and the
|
Notice the comma separation and the
|
||||||
@@ -968,6 +992,97 @@ available in your Linux kernel, or the name is misspelled.
|
|||||||
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:
|
||||||
.Lk https://www.kernel.org/doc/html/latest/admin-guide/cgroup-v2.html
|
.Lk https://www.kernel.org/doc/html/latest/admin-guide/cgroup-v2.html
|
||||||
|
.Sh CONDITIONAL LOADING
|
||||||
|
Finit support conditional loading of stanzas. The following example is
|
||||||
|
take from the
|
||||||
|
.Pa system/hotplug.conf
|
||||||
|
file in the Finit distribution. Here we only show a simplified subset.
|
||||||
|
.Pp
|
||||||
|
Starting with the
|
||||||
|
.Cm nowarn
|
||||||
|
option.
|
||||||
|
.Bd -unfilled -offset indent
|
||||||
|
service nowarn name:udevd pid:udevd /lib/systemd/systemd-udevd
|
||||||
|
service nowarn name:udevd pid:udevd udevd
|
||||||
|
.Ed
|
||||||
|
.Pp
|
||||||
|
When loading the .conf file Finit looks for
|
||||||
|
.Pa /lib/systemd/systemd-udevd
|
||||||
|
if that is not found Finit automatically logs a warning. The
|
||||||
|
.Cm nowarn
|
||||||
|
option disables this warning so that the second line can be evaluated,
|
||||||
|
which also provides a service named
|
||||||
|
.Cm udevd .
|
||||||
|
.Bd -unfilled -offset indent
|
||||||
|
run nowarn if:udevd <pid/udevd> :1 udevadm settle -t 0
|
||||||
|
.Ed
|
||||||
|
.Pp
|
||||||
|
This line is only loaded if we know of a service named
|
||||||
|
.Cm udevd .
|
||||||
|
Again, we do not warn if
|
||||||
|
.Cm udevadm
|
||||||
|
is not found, execution will also stop here until the PID condition is
|
||||||
|
asserted, i.e., Finit detecting udevd has started.
|
||||||
|
.Bd -unfilled -offset indent
|
||||||
|
run nowarn conflict:udevd [S] mdev -s -- Populating device tree
|
||||||
|
.Ed
|
||||||
|
.Pp
|
||||||
|
If
|
||||||
|
.Cm udevd
|
||||||
|
is not available, we try to run
|
||||||
|
.Cm mdev ,
|
||||||
|
but if that is not found, again we do not warn.
|
||||||
|
.Pp
|
||||||
|
Conditional loading statements can also be negated, so the previous stanza
|
||||||
|
can also be written as:
|
||||||
|
.Bd -unfilled -offset indent
|
||||||
|
run nowarn if:!udevd [S] mdev -s -- Populating device tree
|
||||||
|
.Ed
|
||||||
|
.Pp
|
||||||
|
The reason for using
|
||||||
|
.Cm conflict
|
||||||
|
in this example is that a conflict can be resolved. Stanzas marked with
|
||||||
|
.C, conflict:foo
|
||||||
|
are rechecked at runtime.
|
||||||
|
.Sh CONDITIONAL EXECUTION
|
||||||
|
Similar to conditional loading of stanzas there is conditional runtime
|
||||||
|
execution. This can be confusing at first, since Finit already has a
|
||||||
|
condition subsystem, but this is more akin to the qualification to a
|
||||||
|
runlevel. E.g., a
|
||||||
|
.Cm task [123]
|
||||||
|
is qualified to run only in runlevel 1, 2, and 3. It is not considered
|
||||||
|
for other runlevels.
|
||||||
|
.Pp
|
||||||
|
Conditional execution qualify a run/task/service based on a condition.
|
||||||
|
Consider this (simplified) example from the Infix operating system:
|
||||||
|
.Bd -unfilled -offset indent
|
||||||
|
run [S] name:startup <pid/sysrepo> confd -b --load startup-config
|
||||||
|
run [S] if:<usr/fail-startup> name:failure <pid/sysrepo> confd --load failure-config
|
||||||
|
.Ed
|
||||||
|
.Pp
|
||||||
|
The two run statements reside in the same .conf file so Finit runs them
|
||||||
|
in true sequence. If loading the file
|
||||||
|
.Cm startup-config
|
||||||
|
fails
|
||||||
|
.Cm confd
|
||||||
|
sets the condition
|
||||||
|
.Cm usr/fail-startup ,
|
||||||
|
thus allowing the next run statement to load
|
||||||
|
.Cm failure-config .
|
||||||
|
.Pp
|
||||||
|
Notice the critical difference between the
|
||||||
|
.Cm <pid/sysrepo>
|
||||||
|
condition and
|
||||||
|
.Cm if:<usr/fail-startup> .
|
||||||
|
The former is a condition for starting and the latter is a condition to
|
||||||
|
check if a run/task/service is qualified to even be considered.
|
||||||
|
.Pp
|
||||||
|
Conditional execution statements can also be negated, so provided the
|
||||||
|
file loaded did the opposite, i.e., set a condition on success, the
|
||||||
|
previous stanza can also be written as:
|
||||||
|
.Bd -unfilled -offset indent
|
||||||
|
run [S] if:<!usr/startup-ok> name:failure <pid/sysrepo> confd ...
|
||||||
|
.Ed
|
||||||
.Sh LIMITATIONS
|
.Sh LIMITATIONS
|
||||||
As of Finit v4 there are no limitations to where
|
As of Finit v4 there are no limitations to where
|
||||||
.Cm .conf
|
.Cm .conf
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
.\" First parameter, NAME, should be all caps
|
.\" First parameter, NAME, should be all caps
|
||||||
.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection
|
.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection
|
||||||
.\" other parameters are allowed: see man(7), man(1)
|
.\" other parameters are allowed: see man(7), man(1)
|
||||||
.Dd June 6, 2021
|
.Dd July 10, 2025
|
||||||
.\" Please adjust this date whenever revising the manpage.
|
.\" Please adjust this date whenever revising the manpage.
|
||||||
.Dt INITCTL 8 SMM
|
.Dt INITCTL 8 SMM
|
||||||
.Os Linux
|
.Os Linux
|
||||||
@@ -24,39 +24,39 @@ This program follows the usual UNIX command line syntax, with long
|
|||||||
options starting with two dashes (`-'). The options are as follows:
|
options starting with two dashes (`-'). The options are as follows:
|
||||||
.Bl -tag -width Ds
|
.Bl -tag -width Ds
|
||||||
.It Fl b, -batch
|
.It Fl b, -batch
|
||||||
Batch mode, no screen size probing. Useful for scripting.
|
Batch mode, no screen size probing. Useful for scripting
|
||||||
.It Fl c, -create
|
.It Fl c, -create
|
||||||
Create missing paths (and files) as needed. Useful with the
|
Create missing paths (and files) as needed. Useful with the
|
||||||
.Cm edit
|
.Cm edit
|
||||||
command.
|
command
|
||||||
.It Fl f, -force
|
.It Fl f, -force
|
||||||
Ignore missing files and arguments, never prompt.
|
Ignore missing files and arguments, never prompt
|
||||||
.It Fl h, -help
|
.It Fl h, -help
|
||||||
Show built-in help text.
|
Show built-in help text
|
||||||
.It Fl j, -json
|
.It Fl j, -json
|
||||||
JSON output in
|
JSON output in
|
||||||
.Ar status
|
.Ar status
|
||||||
and
|
and
|
||||||
.Ar cond
|
.Ar cond
|
||||||
commands.
|
commands
|
||||||
.It Fl n, -noerr
|
.It Fl n, -noerr
|
||||||
When scripting
|
When scripting
|
||||||
.Nm
|
.Nm
|
||||||
to stop, start, restart, or signal a task or service, this option can be
|
to stop, start, restart, or signal a task or service, this option can be
|
||||||
used to ignore error 69 (no such task or service) and instead return 0
|
used to ignore error 69 (no such task or service) and instead return 0
|
||||||
(OK).
|
(OK)
|
||||||
.It Fl 1, -once
|
.It Fl 1, -once
|
||||||
Only one lap in commands like top.
|
Only one lap in commands like top
|
||||||
.It Fl p, -plain
|
.It Fl p, -plain
|
||||||
Use plain table headings, no ANSI control characters.
|
Use plain table headings, no ANSI control characters
|
||||||
.It Fl q, -quiet
|
.It Fl q, -quiet
|
||||||
Silent, only return status of command.
|
Silent, only return status of command
|
||||||
.It Fl t, -no-heading
|
.It Fl t, -no-heading
|
||||||
Skip table headings.
|
Skip table headings
|
||||||
.It Fl v, -verbose
|
.It Fl v, -verbose
|
||||||
Verbose output, where applicable.
|
Verbose output, where applicable
|
||||||
.It Fl V, -version
|
.It Fl V, -version
|
||||||
Show program version.
|
Show program version
|
||||||
.El
|
.El
|
||||||
.Sh COMMANDS
|
.Sh COMMANDS
|
||||||
.Bl -tag -width Ds
|
.Bl -tag -width Ds
|
||||||
@@ -66,9 +66,9 @@ Toggle
|
|||||||
(daemon) debug to
|
(daemon) debug to
|
||||||
.Pa /dev/console
|
.Pa /dev/console
|
||||||
.It Nm Ar help
|
.It Nm Ar help
|
||||||
Show built-in help text.
|
Show built-in help text
|
||||||
.It Nm Ar version
|
.It Nm Ar version
|
||||||
Show program version.
|
Show program version
|
||||||
.It Nm Ar ls | list
|
.It Nm Ar ls | list
|
||||||
List all
|
List all
|
||||||
.Cm *.conf
|
.Cm *.conf
|
||||||
@@ -112,9 +112,10 @@ like
|
|||||||
.Ar edit
|
.Ar edit
|
||||||
this tells
|
this tells
|
||||||
.Nm finit
|
.Nm finit
|
||||||
that a configuration has been changed and is a candidate to be restarted
|
that a configuration has been changed and is a candidate to be reloaded
|
||||||
(or SIGHUP'ed) on
|
(SIGHUP'ed or restarted) on
|
||||||
.Cm initctl reload
|
.Cm initctl reload
|
||||||
|
in dependency order
|
||||||
.It Nm Ar enable Ar CONF
|
.It Nm Ar enable Ar CONF
|
||||||
Enable
|
Enable
|
||||||
.Cm .conf
|
.Cm .conf
|
||||||
@@ -127,12 +128,12 @@ Disable
|
|||||||
.Cm .conf
|
.Cm .conf
|
||||||
in
|
in
|
||||||
.Pa /etc/finit.d/enabled ,
|
.Pa /etc/finit.d/enabled ,
|
||||||
i.e., removes symlink.
|
i.e., removes symlink
|
||||||
.It Nm Ar reload
|
.It Nm Ar reload
|
||||||
Reload
|
Reload all (touched)
|
||||||
.Cm *.conf in
|
.Cm *.conf in
|
||||||
.Pa /etc/finit.d ,
|
.Pa /etc/finit.d
|
||||||
i.e., activates changes.
|
and activate changes
|
||||||
.It Nm Ar cond set Ar COND Op COND ...
|
.It Nm Ar cond set Ar COND Op COND ...
|
||||||
Set (assert) user-defined condition,
|
Set (assert) user-defined condition,
|
||||||
.Cm +usr/COND
|
.Cm +usr/COND
|
||||||
@@ -148,7 +149,7 @@ The command is geared for scripting, check the exit code to get the
|
|||||||
status of the condition: 0 - on, 1 - off, 255 - flux. For a more
|
status of the condition: 0 - on, 1 - off, 255 - flux. For a more
|
||||||
verbose output, use the
|
verbose output, use the
|
||||||
.Fl v
|
.Fl v
|
||||||
option.
|
option
|
||||||
.It Nm Ar cond clr | clear Ar COND Op COND ...
|
.It Nm Ar cond clr | clear Ar COND Op COND ...
|
||||||
Clear (deassert) user-defined condition,
|
Clear (deassert) user-defined condition,
|
||||||
.Cm -usr/COND
|
.Cm -usr/COND
|
||||||
@@ -157,28 +158,28 @@ Show condition status, default
|
|||||||
.Cm cond
|
.Cm cond
|
||||||
command. Also supports the
|
command. Also supports the
|
||||||
.Fl j
|
.Fl j
|
||||||
option for detailed JSON output.
|
option for detailed JSON output
|
||||||
.It Nm Ar cond dump Op Cm TYPE
|
.It Nm Ar cond dump Op Cm TYPE
|
||||||
Dump all, or a given type of, conditions and their status. Also
|
Dump all, or a given type of, conditions and their status. Also
|
||||||
supports the
|
supports the
|
||||||
.Fl j
|
.Fl j
|
||||||
option for detailed JSON output.
|
option for detailed JSON output
|
||||||
.It Nm Ar ident Op Cm NAME
|
.It Nm Ar ident Op Cm NAME
|
||||||
Display indentities of all run/task/services, or only instances
|
Display indentities of all run/task/services, or only instances
|
||||||
matching
|
matching
|
||||||
.Cm NAME .
|
.Cm NAME .
|
||||||
A partial string, e.g.,
|
A partial string, e.g.,
|
||||||
.Cm NAM ,
|
.Cm NAM ,
|
||||||
will not match anything.
|
will not match anything
|
||||||
.It Nm Ar log Op Cm NAME
|
.It Nm Ar log Op Cm NAME
|
||||||
Show ten last Finit, or
|
Show ten last Finit, or
|
||||||
.Cm NAME ,
|
.Cm NAME ,
|
||||||
messages from syslog.
|
messages from syslog
|
||||||
.It Nm Ar start Cm NAME[:ID]
|
.It Nm Ar start Cm NAME[:ID]
|
||||||
Start service by name, with optional ID, e.g.,
|
Start service by name, with optional ID, e.g.,
|
||||||
.Cm initctl start tty:1
|
.Cm initctl start tty:1
|
||||||
.It Nm Ar stop Cm NAME[:ID]
|
.It Nm Ar stop Cm NAME[:ID]
|
||||||
Stop/Pause a running service by name.
|
Stop/Pause a running service by name
|
||||||
.It Nm Ar reload Cm NAME[:ID]
|
.It Nm Ar reload Cm NAME[:ID]
|
||||||
Reload service as if its configuration had changed. Internally,
|
Reload service as if its configuration had changed. Internally,
|
||||||
.Nm finit
|
.Nm finit
|
||||||
@@ -193,17 +194,19 @@ it is the same as calling
|
|||||||
Except for two things:
|
Except for two things:
|
||||||
.Bl -enum -offset indent -compact
|
.Bl -enum -offset indent -compact
|
||||||
.It
|
.It
|
||||||
if the service supports HUP, it's signaled instead of stop-started, and
|
if the service supports HUP (or has a
|
||||||
|
.Cm reload:script )
|
||||||
|
it is signaled instead of stop-started, and
|
||||||
.It
|
.It
|
||||||
it allows restarting run/task in the same runlevel -- which is otherwise
|
it allows restarting run/task in the same runlevel -- which is otherwise
|
||||||
restricted.
|
restricted
|
||||||
.El
|
.El
|
||||||
.It Nm Ar signal Cm NAME:[ID] S
|
.It Nm Ar <kill | signal> Cm NAME:[ID] S
|
||||||
Send signal S to service, by name.
|
Send signal S to service, by name.
|
||||||
.Cm S
|
.Cm S
|
||||||
may be a complete signal name such as SIGHUP, or short name such as HUP, or the signal number such as 1 (SIGHUP).
|
may be a complete signal name such as SIGHUP, or short name such as HUP, or the signal number such as 1 (SIGHUP)
|
||||||
.It Nm Ar restart Cm NAME[:ID]
|
.It Nm Ar restart Cm NAME[:ID]
|
||||||
Restart (stop/start) service by name.
|
Restart (stop/start) service by name
|
||||||
.It Nm Ar status Cm NAME[:ID]
|
.It Nm Ar status Cm NAME[:ID]
|
||||||
Show service status, by name. If only
|
Show service status, by name. If only
|
||||||
.Cm NAME
|
.Cm NAME
|
||||||
@@ -225,48 +228,48 @@ option for detailed JSON output suitable for machine parsing.
|
|||||||
.Pp
|
.Pp
|
||||||
.Sy Tip:
|
.Sy Tip:
|
||||||
.Xr jq 1
|
.Xr jq 1
|
||||||
is a useful scripting tool in combination with JSON output.
|
is a useful scripting tool in combination with JSON output
|
||||||
.It Nm Ar status
|
.It Nm Ar status
|
||||||
Show status of all services, default command. Also supports the
|
Show status of all services, default command. Also supports the
|
||||||
.Fl j
|
.Fl j
|
||||||
option for detailed JSON output.
|
option for detailed JSON output
|
||||||
.It Nm Ar cgroup
|
.It Nm Ar cgroup
|
||||||
List cgroup config overview.
|
List cgroup config overview
|
||||||
.It Nm Ar ps
|
.It Nm Ar ps
|
||||||
List processes based on cgroups.
|
List processes based on cgroups
|
||||||
.It Nm Ar top
|
.It Nm Ar top
|
||||||
Show top-like listing based on cgroups.
|
Show top-like listing based on cgroups
|
||||||
.It Nm Ar plugins
|
.It Nm Ar plugins
|
||||||
List installed plugins.
|
List installed plugins
|
||||||
.It Nm Ar runlevel Op Ar 0-9
|
.It Nm Ar runlevel Op Ar 0-9
|
||||||
Show or set runlevel: 0 halt, 6 reboot.
|
Show or set runlevel: 0 halt, 6 reboot.
|
||||||
.Pp
|
.Pp
|
||||||
If called at boot (runlevel S) to set the runlevel, Finit only schedules
|
If called at boot (runlevel S) to set the runlevel, Finit only schedules
|
||||||
the change, effectively overriding the configured runlevel from
|
the change, effectively overriding the configured runlevel from
|
||||||
.Pa /etc/finit.conf .
|
.Pa /etc/finit.conf .
|
||||||
Useful to trigger a fail-safe mode, or similar.
|
Useful to trigger a fail-safe mode, or similar
|
||||||
.It Nm Ar reboot
|
.It Nm Ar reboot
|
||||||
Reboot system, default if
|
Reboot system, default if
|
||||||
.Cm reboot
|
.Cm reboot
|
||||||
is symlinked to
|
is symlinked to
|
||||||
.Nm .
|
.Nm
|
||||||
.It Nm Ar halt
|
.It Nm Ar halt
|
||||||
Halt system, default if
|
Halt system, default if
|
||||||
.Cm halt
|
.Cm halt
|
||||||
is symlinked to
|
is symlinked to
|
||||||
.Nm .
|
.Nm
|
||||||
.It Nm Ar poweroff
|
.It Nm Ar poweroff
|
||||||
Power-off system, default if
|
Power-off system, default if
|
||||||
.Cm poweroff
|
.Cm poweroff
|
||||||
is symlinked to
|
is symlinked to
|
||||||
.Nm .
|
.Nm
|
||||||
.It Nm Ar suspend
|
.It Nm Ar suspend
|
||||||
Suspend system, default if
|
Suspend system, default if
|
||||||
.Cm suspend
|
.Cm suspend
|
||||||
is symlinked to
|
is symlinked to
|
||||||
.Nm .
|
.Nm
|
||||||
.It Nm Ar utmp show
|
.It Nm Ar utmp show
|
||||||
Raw dump of UTMP/WTMP db.
|
Raw dump of UTMP/WTMP db
|
||||||
.El
|
.El
|
||||||
.Sh SEE ALSO
|
.Sh SEE ALSO
|
||||||
.Xr finit.conf 5
|
.Xr finit.conf 5
|
||||||
|
|||||||
@@ -0,0 +1,112 @@
|
|||||||
|
site_name: doc/
|
||||||
|
site_description: Fast Init for Linux Systems
|
||||||
|
site_url: https://troglobit.github.io/finit/
|
||||||
|
repo_url: https://github.com/troglobit/finit
|
||||||
|
repo_name: troglobit/finit
|
||||||
|
copyright: Copyright © 2008-2025 Joachim Wiberg
|
||||||
|
docs_dir: doc/
|
||||||
|
edit_uri: edit/master/doc/
|
||||||
|
|
||||||
|
exclude_docs: |
|
||||||
|
TODO.md
|
||||||
|
|
||||||
|
theme:
|
||||||
|
logo: img/logo.png
|
||||||
|
name: material
|
||||||
|
features:
|
||||||
|
- toc.follow
|
||||||
|
- toc.integrate
|
||||||
|
- navigation.path
|
||||||
|
- navigation.instant
|
||||||
|
- navigation.instant.progress
|
||||||
|
- navigation.tracking
|
||||||
|
# - navigation.tabs
|
||||||
|
# - navigation.sections
|
||||||
|
# - navigation.expand
|
||||||
|
# - navigation.top
|
||||||
|
- navigation.footer
|
||||||
|
- search.highlight
|
||||||
|
- search.share
|
||||||
|
# - content.action.edit
|
||||||
|
- content.code.copy
|
||||||
|
- content.code.annotate
|
||||||
|
palette:
|
||||||
|
- media: "(prefers-color-scheme: light)"
|
||||||
|
scheme: default
|
||||||
|
primary: orange
|
||||||
|
accent: orange
|
||||||
|
toggle:
|
||||||
|
icon: material/weather-night
|
||||||
|
name: Switch to dark mode
|
||||||
|
- media: "(prefers-color-scheme: dark)"
|
||||||
|
scheme: slate
|
||||||
|
primary: black
|
||||||
|
accent: black
|
||||||
|
toggle:
|
||||||
|
icon: material/weather-sunny
|
||||||
|
name: Switch to light mode
|
||||||
|
|
||||||
|
nav:
|
||||||
|
- Introduction: index.md
|
||||||
|
- Example: example.md
|
||||||
|
- Features: features.md
|
||||||
|
- Commands & Status: initctl.md
|
||||||
|
- Rebooting & Halting: commands.md
|
||||||
|
- Runlevels: runlevels.md
|
||||||
|
- Runparts & /etc/rc.local: runparts.md
|
||||||
|
- Configuration:
|
||||||
|
- Overview: config/index.md
|
||||||
|
- Files & Layout: config/files.md
|
||||||
|
- Conditions: conditions.md
|
||||||
|
- Cgroups: config/cgroups.md
|
||||||
|
- Environment Variables: config/env.md
|
||||||
|
- One-shot Tasks: config/task-and-run.md
|
||||||
|
- Services:
|
||||||
|
- Syntax: config/services.md
|
||||||
|
- Options: config/service-opts.md
|
||||||
|
- Environment: config/service-env.md
|
||||||
|
- Synchronization: config/service-sync.md
|
||||||
|
- Wrapper Scripts: config/service-wrappers.md
|
||||||
|
- Run-parts Scripts: config/runparts.md
|
||||||
|
- Runlevels: config/runlevels.md
|
||||||
|
- TTY & Console: config/tty.md
|
||||||
|
- Templating: config/templating.md
|
||||||
|
- Logging: config/logging.md
|
||||||
|
- SysV Compatibility: config/sysv.md
|
||||||
|
- Rescue Mode: config/rescue.md
|
||||||
|
- Limitations: config/limitations.md
|
||||||
|
- Usage:
|
||||||
|
- Building: build.md
|
||||||
|
- Command Line: cmdline.md
|
||||||
|
- Plugins: plugins.md
|
||||||
|
- Services: service.md
|
||||||
|
- Signals: signals.md
|
||||||
|
- Reference:
|
||||||
|
- Distributions: distro.md
|
||||||
|
- keventd: keventd.md
|
||||||
|
- Watchdog: watchdog.md
|
||||||
|
- Service State Machine: state-machine.md
|
||||||
|
- Requirements: requirements.md
|
||||||
|
|
||||||
|
markdown_extensions:
|
||||||
|
- admonition
|
||||||
|
- attr_list
|
||||||
|
- pymdownx.details
|
||||||
|
- pymdownx.superfences
|
||||||
|
- pymdownx.highlight:
|
||||||
|
anchor_linenums: true
|
||||||
|
- pymdownx.inlinehilite
|
||||||
|
- pymdownx.snippets
|
||||||
|
- pymdownx.tabbed:
|
||||||
|
alternate_style: true
|
||||||
|
- tables
|
||||||
|
- toc:
|
||||||
|
permalink: true
|
||||||
|
|
||||||
|
plugins:
|
||||||
|
- search
|
||||||
|
- callouts
|
||||||
|
|
||||||
|
|
||||||
|
extra:
|
||||||
|
homepage: https://troglobit.com/projects/finit/
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
/* Save and restore ALSA sound settings using alsactl
|
/* Save and restore ALSA sound settings using alsactl
|
||||||
*
|
*
|
||||||
* Copyright (c) 2012-2024 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (c) 2012-2025 Joachim Wiberg <troglobit@gmail.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -30,6 +30,7 @@
|
|||||||
#include "finit.h"
|
#include "finit.h"
|
||||||
#include "helpers.h"
|
#include "helpers.h"
|
||||||
#include "plugin.h"
|
#include "plugin.h"
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
#define ALSACTL "alsactl"
|
#define ALSACTL "alsactl"
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/* Setup necessary system files for, e.g. UTMP (tracking logins)
|
/* Setup necessary system files for, e.g. UTMP (tracking logins)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2012-2024 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (c) 2012-2025 Joachim Wiberg <troglobit@gmail.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -40,6 +40,7 @@
|
|||||||
#include "plugin.h"
|
#include "plugin.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "utmp-api.h"
|
#include "utmp-api.h"
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
static int is_tmpfs(char *path)
|
static int is_tmpfs(char *path)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/* Setup and start system message bus, D-Bus
|
/* Setup and start system message bus, D-Bus
|
||||||
*
|
*
|
||||||
* Copyright (c) 2012-2024 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (c) 2012-2025 Joachim Wiberg <troglobit@gmail.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -33,7 +33,9 @@
|
|||||||
#include "helpers.h"
|
#include "helpers.h"
|
||||||
#include "plugin.h"
|
#include "plugin.h"
|
||||||
#include "service.h"
|
#include "service.h"
|
||||||
|
#include "util.h"
|
||||||
#include "conf.h"
|
#include "conf.h"
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
#define DBUS_DAEMON "dbus-daemon"
|
#define DBUS_DAEMON "dbus-daemon"
|
||||||
#define DBUS_ARGS "--nofork --system --syslog-only"
|
#define DBUS_ARGS "--nofork --system --syslog-only"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/* Coldplug modules using modalias magic
|
/* Coldplug modules using modalias magic
|
||||||
*
|
*
|
||||||
* Copyright (c) 2021-2024 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (c) 2021-2025 Joachim Wiberg <troglobit@gmail.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -50,6 +50,7 @@
|
|||||||
#include "finit.h"
|
#include "finit.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "plugin.h"
|
#include "plugin.h"
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
struct module {
|
struct module {
|
||||||
TAILQ_ENTRY(module) link;
|
TAILQ_ENTRY(module) link;
|
||||||
|
|||||||
@@ -58,6 +58,7 @@
|
|||||||
#include "plugin.h"
|
#include "plugin.h"
|
||||||
#include "service.h"
|
#include "service.h"
|
||||||
#include "conf.h"
|
#include "conf.h"
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
#ifndef MODULES_LOAD_PATH
|
#ifndef MODULES_LOAD_PATH
|
||||||
#define MODULES_LOAD_PATH "/etc/modules-load.d"
|
#define MODULES_LOAD_PATH "/etc/modules-load.d"
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
/* Netlink plugin for IFUP/IFDN and GW events
|
/* Netlink plugin for IFUP/IFDN and GW events
|
||||||
*
|
*
|
||||||
* Copyright (C) 2009-2011 Mårten Wikström <marten.wikstrom@keystream.se>
|
* Copyright (C) 2009-2011 Mårten Wikström <marten.wikstrom@keystream.se>
|
||||||
* Copyright (C) 2009-2024 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (C) 2009-2025 Joachim Wiberg <troglobit@gmail.com>
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and/or distribute this software for any
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/* Simple pidfile event monitor for the Finit condition engine
|
/* Simple pidfile event monitor for the Finit condition engine
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2016 Tobias Waldekranz <tobias@waldekranz.com>
|
* Copyright (c) 2015-2016 Tobias Waldekranz <tobias@waldekranz.com>
|
||||||
* Copyright (c) 2016-2024 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (c) 2016-2025 Joachim Wiberg <troglobit@gmail.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -34,6 +34,7 @@
|
|||||||
#include "plugin.h"
|
#include "plugin.h"
|
||||||
#include "service.h"
|
#include "service.h"
|
||||||
#include "iwatch.h"
|
#include "iwatch.h"
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
static struct iwatch iw_pidfile;
|
static struct iwatch iw_pidfile;
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/* Set kernel variables from /etc/sysctl.conf et al
|
/* Set kernel variables from /etc/sysctl.conf et al
|
||||||
*
|
*
|
||||||
* Copyright (c) 2016-2024 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (c) 2016-2025 Joachim Wiberg <troglobit@gmail.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/* Setup necessary files for resolvconf
|
/* Setup necessary files for resolvconf
|
||||||
*
|
*
|
||||||
* Copyright (c) 2012-2024 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (c) 2012-2025 Joachim Wiberg <troglobit@gmail.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -30,6 +30,7 @@
|
|||||||
#include "finit.h"
|
#include "finit.h"
|
||||||
#include "helpers.h"
|
#include "helpers.h"
|
||||||
#include "plugin.h"
|
#include "plugin.h"
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* No need to clean up files in /etc/resolvconf/run/interface/
|
* No need to clean up files in /etc/resolvconf/run/interface/
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/* Save and restore RTC using hwclock
|
/* Save and restore RTC using hwclock
|
||||||
*
|
*
|
||||||
* Copyright (c) 2012-2024 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (c) 2012-2025 Joachim Wiberg <troglobit@gmail.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/* System condition event monitor for the Finit condition engine
|
/* System condition event monitor for the Finit condition engine
|
||||||
*
|
*
|
||||||
* Copyright (c) 2021-2024 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (c) 2021-2025 Joachim Wiberg <troglobit@gmail.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -32,6 +32,7 @@
|
|||||||
#include "pid.h"
|
#include "pid.h"
|
||||||
#include "plugin.h"
|
#include "plugin.h"
|
||||||
#include "iwatch.h"
|
#include "iwatch.h"
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
static struct iwatch iw_sys;
|
static struct iwatch iw_sys;
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/* Optional TTY Watcher, used to catch new TTYs that are discovered, e.g., USB
|
/* Optional TTY Watcher, used to catch new TTYs that are discovered, e.g., USB
|
||||||
*
|
*
|
||||||
* Copyright (c) 2013 Mattias Walström <lazzer@gmail.com>
|
* Copyright (c) 2013 Mattias Walström <lazzer@gmail.com>
|
||||||
* Copyright (c) 2013-2024 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (c) 2013-2025 Joachim Wiberg <troglobit@gmail.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/* Setup and save random seed at boot/shutdown
|
/* Setup and save random seed at boot/shutdown
|
||||||
*
|
*
|
||||||
* Copyright (c) 2012-2024 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (c) 2012-2025 Joachim Wiberg <troglobit@gmail.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/* User-defined condition event monitor for the Finit condition engine
|
/* User-defined condition event monitor for the Finit condition engine
|
||||||
*
|
*
|
||||||
* Copyright (c) 2021-2024 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (c) 2021-2025 Joachim Wiberg <troglobit@gmail.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -31,6 +31,7 @@
|
|||||||
#include "pid.h"
|
#include "pid.h"
|
||||||
#include "plugin.h"
|
#include "plugin.h"
|
||||||
#include "iwatch.h"
|
#include "iwatch.h"
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
static struct iwatch iw_usr;
|
static struct iwatch iw_usr;
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/* Console setup (for X)
|
/* Console setup (for X)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2012-2024 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (c) 2012-2025 Joachim Wiberg <troglobit@gmail.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/* External client API, using UNIX domain socket.
|
/* External client API, using UNIX domain socket.
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2024 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (c) 2015-2025 Joachim Wiberg <troglobit@gmail.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/* Finit control group support functions
|
/* Finit control group support functions
|
||||||
*
|
*
|
||||||
* Copyright (c) 2019-2024 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (c) 2019-2025 Joachim Wiberg <troglobit@gmail.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/* Finit control group support functions
|
/* Finit control group support functions
|
||||||
*
|
*
|
||||||
* Copyright (c) 2019-2024 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (c) 2019-2025 Joachim Wiberg <troglobit@gmail.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/* New client tool, replaces old /dev/initctl API and telinit tool
|
/* New client tool, replaces old /dev/initctl API and telinit tool
|
||||||
*
|
*
|
||||||
* Copyright (c) 2019-2024 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (c) 2019-2025 Joachim Wiberg <troglobit@gmail.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/* Cgroup utility functions for initctl
|
/* Cgroup utility functions for initctl
|
||||||
*
|
*
|
||||||
* Copyright (c) 2019-2024 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (c) 2019-2025 Joachim Wiberg <troglobit@gmail.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/* External client API, using UNIX domain socket.
|
/* External client API, using UNIX domain socket.
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2024 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (c) 2015-2025 Joachim Wiberg <troglobit@gmail.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/* External client API, using UNIX domain socket.
|
/* External client API, using UNIX domain socket.
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2024 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (c) 2015-2025 Joachim Wiberg <troglobit@gmail.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/* Parser for /etc/finit.conf and /etc/finit.d/<SVC>.conf
|
/* Parser for /etc/finit.conf and /etc/finit.d/<SVC>.conf
|
||||||
*
|
*
|
||||||
* Copyright (c) 2012-2024 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (c) 2012-2025 Joachim Wiberg <troglobit@gmail.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/* Parser for /etc/finit.conf and /etc/finit.d/<SVC>.conf
|
/* Parser for /etc/finit.conf and /etc/finit.d/<SVC>.conf
|
||||||
*
|
*
|
||||||
* Copyright (c) 2012-2024 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (c) 2012-2025 Joachim Wiberg <troglobit@gmail.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/* Device node monitor for the Finit condition engine
|
/* Device node monitor for the Finit condition engine
|
||||||
*
|
*
|
||||||
* Copyright (c) 2022-2024 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (c) 2022-2025 Joachim Wiberg <troglobit@gmail.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/* Device node monitor for the Finit condition engine
|
/* Device node monitor for the Finit condition engine
|
||||||
*
|
*
|
||||||
* Copyright (c) 2022-2024 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (c) 2022-2025 Joachim Wiberg <troglobit@gmail.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/* Functions for exec'ing processes
|
/* Functions for exec'ing processes
|
||||||
*
|
*
|
||||||
* Copyright (c) 2008-2010 Claudio Matsuoka <cmatsuoka@gmail.com>
|
* Copyright (c) 2008-2010 Claudio Matsuoka <cmatsuoka@gmail.com>
|
||||||
* Copyright (c) 2008-2024 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (c) 2008-2025 Joachim Wiberg <troglobit@gmail.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/* Finit - Fast /sbin/init replacement w/ I/O, hook & service plugins
|
/* Finit - Fast /sbin/init replacement w/ I/O, hook & service plugins
|
||||||
*
|
*
|
||||||
* Copyright (c) 2008-2010 Claudio Matsuoka <cmatsuoka@gmail.com>
|
* Copyright (c) 2008-2010 Claudio Matsuoka <cmatsuoka@gmail.com>
|
||||||
* Copyright (c) 2008-2024 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (c) 2008-2025 Joachim Wiberg <troglobit@gmail.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -38,6 +38,7 @@
|
|||||||
#ifdef HAVE_SYS_SYSMACROS_H
|
#ifdef HAVE_SYS_SYSMACROS_H
|
||||||
#include <sys/sysmacros.h>
|
#include <sys/sysmacros.h>
|
||||||
#endif
|
#endif
|
||||||
|
#include <sys/prctl.h>
|
||||||
#ifdef _LIBITE_LITE
|
#ifdef _LIBITE_LITE
|
||||||
# include <libite/lite.h>
|
# include <libite/lite.h>
|
||||||
#else
|
#else
|
||||||
@@ -623,6 +624,13 @@ int main(int argc, char *argv[])
|
|||||||
*/
|
*/
|
||||||
conf_parse_cmdline(argc, argv);
|
conf_parse_cmdline(argc, argv);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Clear command line arguments for ps display, issue #442
|
||||||
|
*/
|
||||||
|
prctl(PR_SET_NAME, "init", 0, 0, 0);
|
||||||
|
for (int i = 1; i < argc; i++)
|
||||||
|
memset(argv[i], 0, strlen(argv[i]));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Figure out system console(s) and call log_init() to set
|
* Figure out system console(s) and call log_init() to set
|
||||||
* correct log level, possibly finit.debug enabled.
|
* correct log level, possibly finit.debug enabled.
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/* Finit - Fast /sbin/init replacement w/ I/O, hook & service plugins
|
/* Finit - Fast /sbin/init replacement w/ I/O, hook & service plugins
|
||||||
*
|
*
|
||||||
* Copyright (c) 2008-2010 Claudio Matsuoka <cmatsuoka@gmail.com>
|
* Copyright (c) 2008-2010 Claudio Matsuoka <cmatsuoka@gmail.com>
|
||||||
* Copyright (c) 2008-2024 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (c) 2008-2025 Joachim Wiberg <troglobit@gmail.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/* Initialize and serve a login terminal
|
/* Initialize and serve a login terminal
|
||||||
*
|
*
|
||||||
* Copyright (c) 2016-2024 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (c) 2016-2025 Joachim Wiberg <troglobit@gmail.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|||||||