mirror of
https://github.com/troglobit/finit.git
synced 2026-10-14 10:19:36 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
197c5767ea | ||
|
|
22072e477c | ||
|
|
bda2f94e8a | ||
|
|
abb4561516 | ||
|
|
309cc7f741 | ||
|
|
c23952cd9e | ||
|
|
13a8f56b46 | ||
|
|
927acdbd7e | ||
|
|
6f6267f3b3 | ||
|
|
dec89d4054 | ||
|
|
193e114596 | ||
|
|
1be67c434e | ||
|
|
4f8dab75b2 | ||
|
|
37d063fd3b | ||
|
|
97be3da126 | ||
|
|
e7f97f8264 | ||
|
|
6415aeebac | ||
|
|
e69200ea43 | ||
|
|
26d5018224 | ||
|
|
1b7699ca93 | ||
|
|
8eab099f09 | ||
|
|
c7c5426586 | ||
|
|
85484178e0 | ||
|
|
e958189e6a | ||
|
|
eb13309a34 | ||
|
|
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 | ||
|
|
ce7d4cebab | ||
|
|
d5a47e2d8b | ||
|
|
020eefe732 | ||
|
|
14336bd407 | ||
|
|
bb841383b8 | ||
|
|
e49763d834 | ||
|
|
57545e1ab0 | ||
|
|
7ad802b092 | ||
|
|
e319a606b8 | ||
|
|
7d434b1eaa | ||
|
|
58d48b54b3 | ||
|
|
7d4603e13b | ||
|
|
d0c5d7be5b | ||
|
|
db840bdc19 | ||
|
|
3df3c51dae | ||
|
|
d37d241647 | ||
|
|
b18b21830a | ||
|
|
06daf2e4a5 | ||
|
|
eb13ccc227 | ||
|
|
0861373d14 | ||
|
|
1b9e69414e | ||
|
|
39f4aa3f2c | ||
|
|
dedb56a9d0 | ||
|
|
a27903c745 | ||
|
|
f24f76fc80 | ||
|
|
d95fc5f790 | ||
|
|
10a1257e47 | ||
|
|
a7b8e1b94d | ||
|
|
da83462731 | ||
|
|
1396177706 | ||
|
|
7cf0a293fd | ||
|
|
d0d9b83b66 | ||
|
|
76f8a18816 | ||
|
|
dc497bcd57 | ||
|
|
0da6bbe4a8 | ||
|
|
91f7a75bee | ||
|
|
f217d493b4 | ||
|
|
77404a2ea0 | ||
|
|
d42a1d438b | ||
|
|
1275f05343 | ||
|
|
61a92aa0b6 | ||
|
|
b38ff0cc79 | ||
|
|
168f5bf1d8 | ||
|
|
ffd00f646c | ||
|
|
5e2e273cad | ||
|
|
33f6697cd5 | ||
|
|
6f0ba22a0f | ||
|
|
ecb690c9ec | ||
|
|
0459bb432a | ||
|
|
2760616c73 | ||
|
|
62ab990129 | ||
|
|
0c2836d747 | ||
|
|
8be7a462e0 | ||
|
|
5993b4bb5d | ||
|
|
2957246092 | ||
|
|
a5710125f6 | ||
|
|
ff95ebeb91 | ||
|
|
1921b3f2c5 | ||
|
|
051ef81e53 | ||
|
|
90993c237a | ||
|
|
b0b4f7b2ba | ||
|
|
4d79d84fb8 | ||
|
|
d318aa00c3 | ||
|
|
9684127eb7 | ||
|
|
8d2cfd69fa | ||
|
|
4f252858e4 | ||
|
|
1ccd1d6926 | ||
|
|
b87c51209d | ||
|
|
6b7478ff43 | ||
|
|
6c4c16cbdb | ||
|
|
e539dbfe37 | ||
|
|
90c6bcd365 | ||
|
|
c9c268f218 | ||
|
|
3feff37ba5 | ||
|
|
c67d15e272 | ||
|
|
8984c655f8 | ||
|
|
1a7b26bac3 | ||
|
|
1f47718012 | ||
|
|
fa13cddc28 | ||
|
|
185a72bd14 | ||
|
|
cd32c623cf | ||
|
|
ac4b9c2f93 | ||
|
|
5e9591d0a8 | ||
|
|
e3bcf9bf16 | ||
|
|
84fd3196b0 | ||
|
|
994e51e34f | ||
|
|
0a7814b391 | ||
|
|
73f72b39cf | ||
|
|
02e0aa7383 | ||
|
|
6528628b5c | ||
|
|
1480657982 | ||
|
|
33e378a345 | ||
|
|
b695b46a9d | ||
|
|
0e61ed727f | ||
|
|
e9d60a6c04 | ||
|
|
5e9edf9deb | ||
|
|
8ed2751ae1 | ||
|
|
7fec66dc09 | ||
|
|
75fa868a4b | ||
|
|
7b321de339 | ||
|
|
1691ebb292 | ||
|
|
c371c10455 | ||
|
|
a23e152f6b | ||
|
|
9210f2851e | ||
|
|
617609cbc5 | ||
|
|
b022916758 | ||
|
|
9a357b7aab | ||
|
|
ffd01b0276 | ||
|
|
2c95f091ee | ||
|
|
b75b107d6d | ||
|
|
1f2c1d2109 | ||
|
|
f328d24d01 | ||
|
|
211293a83d | ||
|
|
446f5bc8b8 | ||
|
|
0c6f748f2c | ||
|
|
a677b94ad9 | ||
|
|
6552cda605 | ||
|
|
3add682be3 | ||
|
|
abac31682d | ||
|
|
cfe915e6d5 | ||
|
|
ecf65ce44b | ||
|
|
0d742d6ae8 | ||
|
|
cf201a43df | ||
|
|
9245869e18 | ||
|
|
0f4a487328 | ||
|
|
f1b5b42919 | ||
|
|
f546129baf | ||
|
|
27451ac3f2 | ||
|
|
0a8f3a6250 | ||
|
|
70c4e7d774 | ||
|
|
5265eee25d | ||
|
|
4b06e1a49f | ||
|
|
6b9aa21509 | ||
|
|
990307fbc9 | ||
|
|
9d8a9b7fba | ||
|
|
bbc83eaa64 | ||
|
|
23d034f521 | ||
|
|
9a3148a49d | ||
|
|
8560103a24 | ||
|
|
7a75e34808 | ||
|
|
4d4fc10d57 | ||
|
|
003faae9e9 | ||
|
|
01a01d65c0 | ||
|
|
048302f06a | ||
|
|
74f0fcfccd | ||
|
|
3cfe0a33b8 | ||
|
|
465bc17ca4 | ||
|
|
d4889b435d | ||
|
|
49c0557ced | ||
|
|
6be16f2f6d | ||
|
|
bc8118d515 | ||
|
|
0c0e880f3f | ||
|
|
119e66a7e9 | ||
|
|
46ffa81f5c | ||
|
|
54701422a5 | ||
|
|
9d463e3823 | ||
|
|
56e558c960 | ||
|
|
dfaf351da1 | ||
|
|
a8433fcb7f | ||
|
|
2daa953bee | ||
|
|
3e3e9aadf5 | ||
|
|
dc873c6548 | ||
|
|
29bd7a504e | ||
|
|
a0685219cf | ||
|
|
13b107b7b1 | ||
|
|
409d68d05b | ||
|
|
ab62b5282b | ||
|
|
d02d65feeb | ||
|
|
9a0dea6aef | ||
|
|
7481505b1a | ||
|
|
8251f1a422 | ||
|
|
e269176a79 | ||
|
|
612f5a9385 | ||
|
|
4a2381eb6f | ||
|
|
0cae7d44dd | ||
|
|
340cae4afd | ||
|
|
6a89e60fc8 | ||
|
|
840d612fc2 | ||
|
|
60c676ab2d | ||
|
|
deada0fa89 | ||
|
|
7b501f255b | ||
|
|
052136cb99 | ||
|
|
742b8b72cc | ||
|
|
c37037c015 | ||
|
|
c32b5a749a | ||
|
|
7701718d7b | ||
|
|
eb4eca9607 | ||
|
|
cab94b81e8 | ||
|
|
5913217808 | ||
|
|
b49f55ab3d | ||
|
|
bf4a584e2e | ||
|
|
90a4df8d12 | ||
|
|
146bf55122 | ||
|
|
c1ed373398 | ||
|
|
5998342b3e | ||
|
|
9dc7b8a6b0 | ||
|
|
c221823654 | ||
|
|
248f7d3110 | ||
|
|
fe90ba5781 | ||
|
|
71c87734b7 | ||
|
|
cd060e8af3 | ||
|
|
33a7f123d7 |
No files matched your search
@@ -24,7 +24,8 @@ the maintainer(s) and make it easier for them to include your code.
|
||||
Coding Style
|
||||
------------
|
||||
|
||||
> **Tip:** Always submit code that follows the style of surrounding code!
|
||||
> [!TIP]
|
||||
> Always submit code that follows the style of surrounding code!
|
||||
|
||||
First of all, lines are allowed to be longer than 72 characters these
|
||||
days. In fact, there exist no enforced maximum, but keeping it around
|
||||
|
||||
@@ -8,20 +8,27 @@ on:
|
||||
- '**'
|
||||
- '!dev'
|
||||
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:
|
||||
build:
|
||||
# Verify we can build on latest Ubuntu with both gcc and clang
|
||||
name: ${{ matrix.compiler }}
|
||||
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:
|
||||
matrix:
|
||||
compiler: [gcc, clang]
|
||||
fail-fast: false
|
||||
env:
|
||||
MAKEFLAGS: -j3
|
||||
CC: ${{ matrix.compiler }}
|
||||
steps:
|
||||
- name: Install dependencies
|
||||
@@ -33,14 +40,15 @@ jobs:
|
||||
run: |
|
||||
./autogen.sh
|
||||
./configure --prefix= --enable-static
|
||||
make V=1
|
||||
make -j3 V=1
|
||||
- name: Regular Finit
|
||||
run: |
|
||||
./configure --prefix=/usr --exec-prefix= --sysconfdir=/etc --localstatedir=/var \
|
||||
--enable-x11-common-plugin --enable-testserv-plugin --with-watchdog \
|
||||
--with-keventd
|
||||
make clean
|
||||
make V=1
|
||||
--with-keventd --with-libsystemd \
|
||||
CFLAGS="-fsanitize=address -ggdb"
|
||||
make -j3 clean
|
||||
make -j3 V=1
|
||||
- name: Install to /tmp
|
||||
run: |
|
||||
DESTDIR=/tmp make install-strip
|
||||
@@ -57,6 +65,9 @@ jobs:
|
||||
run: |
|
||||
sudo /tmp/sbin/finit -h
|
||||
sudo /tmp/sbin/initctl -h
|
||||
- name: Enable unprivileged userns (unshare)
|
||||
run: |
|
||||
sudo sysctl kernel.apparmor_restrict_unprivileged_userns=0
|
||||
- name: Run Unit Tests
|
||||
run: |
|
||||
make check || (cat test/test-suite.log; false)
|
||||
|
||||
@@ -4,6 +4,10 @@ on:
|
||||
push:
|
||||
branches:
|
||||
- 'dev'
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
env:
|
||||
PROJECT_NAME: finit
|
||||
@@ -25,7 +29,7 @@ jobs:
|
||||
--post-data "token=$TOKEN&project=${COVERITY_PROJ}&md5=1" \
|
||||
-O coverity-latest.tar.gz.md5
|
||||
echo "md5=$(cat coverity-latest.tar.gz.md5)" | tee -a $GITHUB_OUTPUT
|
||||
- uses: actions/cache@v3
|
||||
- uses: actions/cache@v4
|
||||
id: cache
|
||||
with:
|
||||
path: coverity-latest.tar.gz
|
||||
@@ -62,7 +66,8 @@ jobs:
|
||||
- name: Configure
|
||||
run: |
|
||||
./autogen.sh
|
||||
./configure --prefix= --enable-x11-common-plugin --with-watchdog --with-keventd
|
||||
./configure --prefix= --enable-x11-common-plugin --with-watchdog \
|
||||
--with-keventd --with-libsystemd
|
||||
- name: Build
|
||||
run: |
|
||||
export PATH=`pwd`/coverity/bin:$PATH
|
||||
|
||||
@@ -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:
|
||||
- '[0-9]+.[0-9]+*'
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
jobs:
|
||||
release:
|
||||
name: Build and upload release tarball
|
||||
@@ -36,9 +39,13 @@ jobs:
|
||||
- name: Creating Makefiles ...
|
||||
run: |
|
||||
./autogen.sh
|
||||
./configure --prefix=/usr --exec-prefix= --sysconfdir=/etc --localstatedir=/var \
|
||||
--enable-x11-common-plugin --enable-testserv-plugin --with-watchdog \
|
||||
--with-keventd
|
||||
./configure --prefix=/usr --exec-prefix= --sysconfdir=/etc \
|
||||
--localstatedir=/var --enable-x11-common-plugin \
|
||||
--enable-testserv-plugin --with-watchdog \
|
||||
--with-keventd --with-libsystemd
|
||||
- name: Enable unprivileged userns (unshare)
|
||||
run: |
|
||||
sudo sysctl kernel.apparmor_restrict_unprivileged_userns=0
|
||||
- name: Build release ...
|
||||
run: |
|
||||
make release || (cat test/test-suite.log; false)
|
||||
@@ -47,7 +54,7 @@ jobs:
|
||||
mv ../*.tar.* artifacts/
|
||||
- name: Extract ChangeLog entry ...
|
||||
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
|
||||
cat release.md
|
||||
- uses: ncipollo/release-action@v1
|
||||
|
||||
@@ -7,6 +7,9 @@ on:
|
||||
- cron: '0 0 * * 0'
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
schedule:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -41,6 +44,9 @@ jobs:
|
||||
- name: Install to /tmp
|
||||
run: |
|
||||
DESTDIR=/tmp make install-strip
|
||||
- name: Enable unprivileged userns (unshare)
|
||||
run: |
|
||||
sudo sysctl kernel.apparmor_restrict_unprivileged_userns=0
|
||||
- name: Check dist tarball
|
||||
run: |
|
||||
ver=$(/tmp/sbin/initctl -V | awk '/Finit.*/ {print $2;}')
|
||||
|
||||
@@ -1,7 +1,15 @@
|
||||
# GNU Global .conf file, see /etc/gtags/gtags.conf for details.
|
||||
# This configuration is optimized for the Finit project structure.
|
||||
|
||||
default:\
|
||||
:tc=default@/etc/gtags/gtags.conf:\
|
||||
:tc=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-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
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
||||
+14
-8
@@ -1,7 +1,6 @@
|
||||
ACLOCAL_AMFLAGS = -I m4
|
||||
SUBDIRS = man plugins src system test tmpfiles.d
|
||||
doc_DATA = README.md LICENSE contrib/finit.conf
|
||||
EXTRA_DIST = README.md LICENSE ChangeLog.md contrib/finit.conf
|
||||
SUBDIRS = man plugins src system tmpfiles.d
|
||||
dist_doc_DATA = README.md LICENSE contrib/finit.conf
|
||||
|
||||
if CONTRIB
|
||||
SUBDIRS += contrib
|
||||
@@ -9,11 +8,18 @@ endif
|
||||
if DOC
|
||||
SUBDIRS += doc
|
||||
endif
|
||||
|
||||
if BASH
|
||||
bashdir = $(BASH_DIR)
|
||||
dist_bash_DATA = initctl
|
||||
if LIBSYSTEMD
|
||||
SUBDIRS += libsystemd
|
||||
endif
|
||||
|
||||
if LIBSYSTEMD
|
||||
SUBDIRS += test
|
||||
# Explicit dependency to ensure libsystemd is built before test
|
||||
test: libsystemd
|
||||
else
|
||||
SUBDIRS += test
|
||||
endif
|
||||
|
||||
# Compat hook
|
||||
install-dev:
|
||||
@make -C src install-pkgincludeHEADERS
|
||||
@@ -37,4 +43,4 @@ release: distcheck
|
||||
DISTCHECK_CONFIGURE_FLAGS = --prefix=/usr --sysconfdir=/etc --localstatedir=/var \
|
||||
--enable-testserv-plugin --enable-x11-common-plugin \
|
||||
--with-watchdog --with-keventd --with-fstab=/etc/fstab \
|
||||
--with-bash-completion-dir=no
|
||||
--with-libsystemd --with-bash-completion-dir=no
|
||||
@@ -1,719 +1,46 @@
|
||||
[![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)
|
||||
* [Features](#features)
|
||||
* [Runlevels](#runlevels)
|
||||
* [Syntax](doc/config.md#syntax)
|
||||
* [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)
|
||||
Finit is an alternative to [SysV init](https://en.wikipedia.org/wiki/Init)
|
||||
and [systemd](https://www.freedesktop.org/wiki/Software/systemd/), focused
|
||||
on small and embedded Linux systems, although fully usable on server and
|
||||
[desktop systems][finix].
|
||||
|
||||
> 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
|
||||
fastinit][] by [Claudio Matsuoka][] — "gaps filled with frog DNA …"
|
||||
<div align="center">
|
||||
<img src="doc/img/alpine-screenshot2.png" alt="Alpine screenshot"><br/>
|
||||
</div>
|
||||
|
||||

|
||||
*Figure 1: Screenshot of Finit booting [Alpine Linux (HowTo)](https://github.com/troglobit/finit/tree/master/contrib/alpine).*
|
||||
For working examples, see the :rocket: [contrib/](contrib/) section or these
|
||||
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/),
|
||||
* :mountain: [Alpine Linux](contrib/alpine/), and
|
||||
* :milky_way: [Void Linux](contrib/void/)
|
||||
|
||||
* Runlevels, 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](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`
|
||||
> [!NOTE]
|
||||
> Support for various Linux distributions does not mean Finit installs
|
||||
> easily on all architectures. Bundled install scripts are examples for
|
||||
> standard installations, tested on amd64 (x86_64) systems. Custom
|
||||
> setups, e.g., for embedded systems, can be found in the following
|
||||
> [Buildroot][] based examples: [myLinux][], [Infix][], or the plain
|
||||
> [br2-finit-demo](https://github.com/troglobit/br2-finit-demo).
|
||||
|
||||
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:** support for various Linux distributions does not mean Finit
|
||||
> installs easily on all architectures. The bundled install scripts are
|
||||
> examples for standard installations, tested on amd64 (x86_64) systems.
|
||||
> Custom setups, e.g., for embedded systems, can be found in any of the
|
||||
> following [Buildroot][] based examples: [myLinux][], [Infix][], or the
|
||||
> plain [br2-finit-demo](https://github.com/troglobit/br2-finit-demo).
|
||||
|
||||
|
||||
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][].
|
||||
|
||||
> **Note:** as of Finit v4.4, .conf lines can be broken up using the
|
||||
> standard UNIX continuation character (`\`), also trailing comments are
|
||||
> now 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
|
||||
`intictl` 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
|
||||
```
|
||||
|
||||
> 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:
|
||||
are:
|
||||
|
||||
- `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
|
||||
[finix]: https://github.com/aanderse/finix
|
||||
[Buildroot]: https://buildroot.org
|
||||
[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 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 Status]: https://github.com/troglobit/finit/actions/workflows/build.yml/badge.svg
|
||||
[Coverity Scan]: https://scan.coverity.com/projects/3545
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
#!/bin/sh
|
||||
# Run test suite with the correct configure params
|
||||
|
||||
make distclean
|
||||
./configure --prefix=/usr --exec-prefix= --sysconfdir=/etc --localstatedir=/var \
|
||||
--enable-x11-common-plugin --with-watchdog --with-keventd
|
||||
make -j17 clean check
|
||||
+59
-20
@@ -1,7 +1,7 @@
|
||||
AC_INIT([Finit], [4.7], [https://github.com/troglobit/finit/issues],
|
||||
AC_INIT([Finit], [4.14], [https://github.com/troglobit/finit/issues],
|
||||
[finit], [https://troglobit.com/projects/finit/])
|
||||
AC_CONFIG_AUX_DIR(aux)
|
||||
AM_INIT_AUTOMAKE([1.11 foreign dist-xz subdir-objects])
|
||||
AM_INIT_AUTOMAKE([1.11 foreign subdir-objects])
|
||||
AM_SILENT_RULES([yes])
|
||||
|
||||
AC_CONFIG_SRCDIR([src/finit.c])
|
||||
@@ -11,7 +11,8 @@ AC_CONFIG_FILES([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/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
|
||||
man/Makefile
|
||||
plugins/Makefile
|
||||
src/Makefile
|
||||
@@ -67,10 +68,18 @@ AC_ARG_ENABLE(fsckfix,
|
||||
AS_HELP_STRING([--enable-fsckfix], [Run fsck fix mode (options: -yf) on filesystems listed in /etc/fstab]),,[
|
||||
enable_fsckfix=no])
|
||||
|
||||
AC_ARG_ENABLE(cgroup,
|
||||
AS_HELP_STRING([--disable-cgroup], [Disable cgroup v2 support, default: autodetect from /sys/fs/cgroup]),,[
|
||||
enable_cgroup=yes])
|
||||
|
||||
AC_ARG_ENABLE(redirect,
|
||||
AS_HELP_STRING([--disable-redirect], [Disable redirection of service output to /dev/null]),,[
|
||||
enable_redirect=yes])
|
||||
|
||||
AC_ARG_ENABLE(kernel_logging,
|
||||
AS_HELP_STRING([--disable-kernel-logging], [Disable kernel logging to console (use 'quiet' instead!]),,[
|
||||
enable_kernel_logging=yes])
|
||||
|
||||
AC_ARG_ENABLE(logrotate,
|
||||
AS_HELP_STRING([--disable-logrotate], [Disable built-in rotation of /var/log/wtmp]),,[
|
||||
enable_logrotate=yes])
|
||||
@@ -160,6 +169,10 @@ AC_ARG_WITH(watchdog,
|
||||
AS_HELP_STRING([--with-watchdog@<:@=DEV@:>@], [Enable built-in watchdog, default: /dev/watchdog]),
|
||||
[watchdog=$withval], [with_watchdog=no watchdog=])
|
||||
|
||||
AC_ARG_WITH(libsystemd,
|
||||
AS_HELP_STRING([--with-libsystemd], [Build replacement libsystemd library, default: yes]),
|
||||
[with_libsystemd=$withval], [with_libsystemd=no])
|
||||
|
||||
AC_ARG_WITH(hook-scripts-path,
|
||||
AS_HELP_STRING([--with-hook-scripts-path=DIR], [Base directory for hook scripts, default $libexecdir/finit/hook]),
|
||||
[hook_scripts_path=$withval], [hook_scripts_path=yes])
|
||||
@@ -169,9 +182,13 @@ AC_ARG_WITH(plugin-path,
|
||||
[plugin_path=$withval], [plugin_path=yes])
|
||||
|
||||
AC_ARG_WITH(rtc-date,
|
||||
AS_HELP_STRING([--with-rtc-date=DATE], [If RTC date/time is too old, restore to DATE, format "YYYY-MM-DD HH:MM", default "2000-01-01 00:00"]),
|
||||
AS_HELP_STRING([--with-rtc-date=DATE], [If RTC date/time is too old, restore to DATE, format "YYYY-MM-DD HH:MM:SS", default "2000-01-01 00:00:00"]),
|
||||
[rtc_date=$withval], [rtc_date=no])
|
||||
|
||||
AC_ARG_WITH(rtc-file,
|
||||
AS_HELP_STRING([--with-rtc-file=FILE], [If RTC is missing, save and restore system clock from this file, default: no]),
|
||||
[rtc_file=$withval], [rtc_file=no])
|
||||
|
||||
### Enable features ###########################################################################
|
||||
|
||||
# Create config.h from selected features and fallback defaults
|
||||
@@ -181,6 +198,12 @@ AS_IF([test "x$enable_auto_reload" = "xyes"], [
|
||||
AS_IF([test "x$enable_kernel_cmdline" = "xyes"], [
|
||||
AC_DEFINE(KERNEL_CMDLINE, 1, [Dumpster diving after init args from /proc/cmdline])])
|
||||
|
||||
AS_IF([test "x$enable_kernel_logging" = "xyes"], [
|
||||
AC_DEFINE(KERNEL_LOGGING, 1, [Keep kernel warn/err logs to console])])
|
||||
|
||||
AS_IF([test "x$enable_cgroup" = "xyes"], [
|
||||
AC_DEFINE(CGROUP2_ENABLED, 1, [Autodetect cgroup v2 support from /sys/fs/cgroup])])
|
||||
|
||||
AS_IF([test "x$enable_fastboot" = "xyes"], [
|
||||
AC_DEFINE(FAST_BOOT, 1, [Skip fsck check on filesystems listed in /etc/fstab])])
|
||||
|
||||
@@ -227,10 +250,9 @@ AC_DEFINE_UNQUOTED(FINIT_RCSD, "$rcsd_path", [Finit rcS.d/, default /etc/finit.d
|
||||
AC_SUBST(FINIT_RCSD, "$rcsd_path")
|
||||
|
||||
AS_IF([test "x$with_rc_local" != "xno"], [
|
||||
AS_IF([test "x$rclocal" = "xyes"], [
|
||||
rclocal=$sysconfdir/rc.local])])
|
||||
AC_EXPAND_DIR(rclocal_path, "$rclocal")
|
||||
AC_DEFINE_UNQUOTED(FINIT_RC_LOCAL, "$rclocal_path", [Compat SysV /etc/rc.local file to run last at boot.])
|
||||
AS_IF([test "x$rclocal" = "xyes"], [rclocal=$sysconfdir/rc.local])
|
||||
AC_EXPAND_DIR(rclocal_path, "$rclocal")
|
||||
AC_DEFINE_UNQUOTED(FINIT_RC_LOCAL, "$rclocal_path", [Compat SysV /etc/rc.local file to run last at boot.])])
|
||||
|
||||
AS_IF([test "x$with_sysconfig" != "xno"], [
|
||||
AS_IF([test "x$sysconfig" != "xdefault"], [
|
||||
@@ -265,9 +287,16 @@ AS_IF([test "x$with_random_seed" != "xno"], [
|
||||
AC_DEFINE_UNQUOTED(RANDOMSEED, "$random_path", [Improve random at boot by seeding it with sth from before.])])
|
||||
|
||||
AS_IF([test "x$rtc_date" != "xno"], [
|
||||
AC_DEFINE(RTC_TIMESTAMP_CUSTOM, "$rtc_date", [Custom RTC restore date, default: 2000-01-01 00:00])], [
|
||||
AC_DEFINE_UNQUOTED(RTC_TIMESTAMP_CUSTOM, "$rtc_date", [Custom RTC restore date, default: 2000-01-01 00:00])], [
|
||||
rtc_date=""])
|
||||
|
||||
AS_IF([test "x$rtc_file" != "xno"], [
|
||||
AS_IF([test "x$rtc_file" = "xyes"], [
|
||||
rtc_file=/var/lib/misc/rtc])
|
||||
AC_EXPAND_DIR(rtcfile_path, "$rtc_file")
|
||||
AC_DEFINE_UNQUOTED(RTC_FILE, "$rtcfile_path", [Save and restore system time from this file if /dev/rtc is missing.])],[
|
||||
AC_DEFINE_UNQUOTED(RTC_FILE, NULL)])
|
||||
|
||||
AS_IF([test "x$with_keventd" != "xno"], [with_keventd=yes])
|
||||
|
||||
AS_IF([test "x$with_sulogin" != "xno"], [
|
||||
@@ -284,6 +313,9 @@ AS_IF([test "x$with_watchdog" != "xno"], [
|
||||
AC_DEFINE_UNQUOTED(WDT_DEVNODE, "$watchdog", [Built-in watchdog device node])], [
|
||||
watchdog=])
|
||||
|
||||
AS_IF([test "x$with_libsystemd" != "xno"], [
|
||||
AC_DEFINE(HAVE_LIBSYSTEMD, 1, [Build replacement libsystemd library support])])
|
||||
|
||||
AS_IF([test "x$enable_hook_scripts_plugin" != "xno"], [
|
||||
AS_IF([test "x$hook_scripts_path" = "xyes"], [hook_scripts_path=$libexecdir/finit/hook])
|
||||
AC_EXPAND_DIR(hook_scripts_path, "$hook_scripts_path")
|
||||
@@ -295,14 +327,15 @@ AS_IF([test "x$with_plugin_path" != "xno"], [
|
||||
AC_DEFINE_UNQUOTED(EXTERNAL_PLUGIN_PATH, "$plugin_path", [Built-in default: /usr/lib/finit/plugins:/usr/local/lib/finit/plugins])])
|
||||
|
||||
# Control build with automake flags
|
||||
AM_CONDITIONAL(BASH, [test "x$bash_dir" != "xno"])
|
||||
AM_CONDITIONAL(STATIC, [test "x$enable_static" = "xyes"])
|
||||
AM_CONDITIONAL(KEVENTD, [test "x$with_keventd" != "xno"])
|
||||
AM_CONDITIONAL(SULOGIN, [test "x$with_sulogin" != "xno"])
|
||||
AM_CONDITIONAL(WATCHDOGD, [test "x$with_watchdog" != "xno"])
|
||||
AM_CONDITIONAL(DOC, [test "x$enable_doc" = "xyes"])
|
||||
AM_CONDITIONAL(CONTRIB, [test "x$enable_contrib" = "xyes"])
|
||||
AM_CONDITIONAL(TESTSERV, [test "x$enable_testserv_plugin" = "xyes"])
|
||||
AM_CONDITIONAL(BASH, [test "x$bash_dir" != "xno"])
|
||||
AM_CONDITIONAL(STATIC, [test "x$enable_static" = "xyes"])
|
||||
AM_CONDITIONAL(KEVENTD, [test "x$with_keventd" != "xno"])
|
||||
AM_CONDITIONAL(SULOGIN, [test "x$with_sulogin" != "xno"])
|
||||
AM_CONDITIONAL(WATCHDOGD, [test "x$with_watchdog" != "xno"])
|
||||
AM_CONDITIONAL(LIBSYSTEMD, [test "x$with_libsystemd" != "xno"])
|
||||
AM_CONDITIONAL(DOC, [test "x$enable_doc" = "xyes"])
|
||||
AM_CONDITIONAL(CONTRIB, [test "x$enable_contrib" = "xyes"])
|
||||
AM_CONDITIONAL(TESTSERV, [test "x$enable_testserv_plugin" = "xyes"])
|
||||
|
||||
# Workaround for as-of-yet unreleased runstatedir support, planned for
|
||||
# autoconf 2.70, which some major distros have backported.
|
||||
@@ -355,15 +388,16 @@ cat <<EOF
|
||||
|
||||
------------------ Summary ------------------
|
||||
$PACKAGE_NAME version $PACKAGE_VERSION
|
||||
Prefix................: $prefix
|
||||
Exec prefix...........: $eprefix
|
||||
Prefix................: $(eval echo $prefix)
|
||||
Exec prefix...........: $(eval echo $exec_prefix)
|
||||
Libdir................: $(eval echo $libdir)
|
||||
Sysconfdir............: `eval echo $sysconfdir`
|
||||
Localstatedir.........: `eval echo $localstatedir`
|
||||
Default fstab.........: `eval echo $fstab`
|
||||
Finit config file.....: $conf_path
|
||||
Finit config.d path...: $rcsd_path
|
||||
Finit plugin path.....: $plugin_path
|
||||
Compat rc.local path..: $rclocal_path
|
||||
Compat rc.local path..: `eval echo $rclocal`
|
||||
System environment....: ${sysconfig_path:-${sysconfig}}
|
||||
Random seed path......: $random_path
|
||||
C Compiler............: $CC $CFLAGS $CPPFLAGS $LDFLAGS $LIBS
|
||||
@@ -373,6 +407,7 @@ Behavior:
|
||||
Boot heading..........: $heading
|
||||
Plugins...............: $plugins
|
||||
RTC restore date......: $RTC_DATE
|
||||
RTC fallback file.....: $rtc_file
|
||||
|
||||
Optional features:
|
||||
Install doc/..........: $enable_doc
|
||||
@@ -382,6 +417,10 @@ Optional features:
|
||||
Built-in sulogin......: $with_sulogin $sulogin
|
||||
Built-in watchdogd....: $with_watchdog $watchdog
|
||||
Built-in logrotate....: $enable_logrotate
|
||||
Replacement libsystemd: $with_libsystemd
|
||||
Use cgroup v2.........: $enable_cgroup
|
||||
Parse kernel cmdline..: $enable_kernel_cmdline
|
||||
Keep kernel logging...: $enable_kernel_logging
|
||||
Skip fsck check.......: $enable_fastboot
|
||||
Run fsck fix mode.....: $enable_fsckfix
|
||||
Redirect output.......: $enable_redirect
|
||||
|
||||
@@ -3,3 +3,8 @@ bin_SCRIPT = service
|
||||
docsdir := @docdir@/contrib
|
||||
docs_DATA = README.md finit.conf procmon.sh
|
||||
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/)
|
||||
* [Debian](debian/)
|
||||
* [Void](void/)
|
||||
|
||||
If you have ideas on how to simplify, extend, or even add new example
|
||||
configurations for other distributions you are most welcome! :)
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
HowTo: Finit on Alpine Linux 3.4...3.19
|
||||
=======================================
|
||||
|
||||
> [!TIP]
|
||||
> https://troglobit.com/post/2021-02-12-alpine-linux-with-finit/
|
||||
|
||||
HowTo use Finit to boot an [Alpine Linux][] system. It is assumed that
|
||||
the user has already installed make, a compiler, C library header files,
|
||||
and other tools needed to build a GNU configure based project.
|
||||
|
||||
@@ -20,8 +20,9 @@ tools pre-systemd work as intended.
|
||||
|
||||
root@debian:~# apt install initscripts console-setup
|
||||
|
||||
> **Note:** as of Debian 11 (Bullseye), libuev and libite are part of
|
||||
> the main section of Debian. So just install the -dev packages :)
|
||||
> [!TIP]
|
||||
> As of Debian 11 (Bullseye), libuev and libite are part of the main
|
||||
> section of Debian. So just install the -dev packages :)
|
||||
|
||||
The following script can then be used to configure, build, install and
|
||||
set up your system to run Finit:
|
||||
@@ -47,7 +48,8 @@ comands to `initctl`, followed by `reload` to activate your changes.
|
||||
You can also use a standard [/etc/rc.local](rc.local) for one-shot tasks
|
||||
and initialization like keyboard language etc.
|
||||
|
||||
> **NOTE:** X Window system, you may need to `sudo apt install elogind`
|
||||
> [!NOTE]
|
||||
> For the X Window system, you may need to `sudo apt install elogind`
|
||||
> (Bullseye and later), followed by `initctl reload` to activate it (it
|
||||
> is enabled by default), and logout/login again. The elogind daemon
|
||||
> ensures a regular non-root user can start and interact with an X
|
||||
|
||||
File renamed without changes.
File renamed without changes.
+239
-36
@@ -4,6 +4,202 @@ Change Log
|
||||
All relevant changes are documented in this file.
|
||||
|
||||
|
||||
|
||||
[4.14][] - 2025-08-29
|
||||
---------------------
|
||||
|
||||
Minor bug fix release.
|
||||
|
||||
### Changes
|
||||
- Add exit status/signal info when a process dies, by Mattias Berthel
|
||||
- Extend `service kill:SEC` to support up to 300 sec.
|
||||
- Extend `norespawn` debug to cover `service_retry()`
|
||||
- Build *without* libsystemd replacement by default
|
||||
|
||||
### Fixes
|
||||
- Fix #449: ALSA plugin fail-to-build-from-source
|
||||
- Fix `sysv` stop command process environment, should be same as start
|
||||
- Fix state machine ordering issue: enter new config generation *after*
|
||||
services disabled in previous generation have been stopped
|
||||
|
||||
|
||||
[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
|
||||
- `initctl signal` command has been renamed to `initctl kill`
|
||||
- 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
|
||||
---------------------
|
||||
|
||||
### Changes
|
||||
- Improve notify:s6 readiness compatibility, by Aaron Andersen
|
||||
- Update `runparts` usage text
|
||||
|
||||
### Fixes
|
||||
- Fix variable overloading in urandom plugin
|
||||
- Fix buffer overwrite in urandom plugin, reported by Aaron Andersen
|
||||
|
||||
|
||||
[4.11][] - 2025-03-27
|
||||
---------------------
|
||||
|
||||
### Changes
|
||||
- Update documentation regarding transition from runlevel S to 2, how
|
||||
run/tasks must "complete" before Finit can move to the next runlevel
|
||||
- Improve argument handling in bundled getty when launching login
|
||||
|
||||
### Fixes
|
||||
- Fix #432: allow services in `setup` state to be stopped. This fixes
|
||||
a serious blocker introduced in 4.10 that prevented systems from
|
||||
being rebooted when any service was in this state
|
||||
- Fix fallback `SIGKILL` when stopping a service with `SIGTERM` does
|
||||
not work. This fixes a serious issue with services not responding to
|
||||
the default `SIGTERM`
|
||||
- Fix pre/post/ready/cleanup script execution if service has an
|
||||
optional `env:file` (leading `-`)
|
||||
- Fix blocked signals for pre/post/ready/cleanup scripts preventing
|
||||
normal shutdown when a service/sysv is stopped in its setup state
|
||||
- Fix issue where a pre:script creates a PID file in `/run` cause the
|
||||
service to move from setup state to running. Any `svc_t` in setup,
|
||||
teardown, or cleanup state should be ignored in the pidfile plugin
|
||||
|
||||
|
||||
[4.10][] - 2025-03-03
|
||||
---------------------
|
||||
|
||||
### Changes
|
||||
- Add support for `cleanup:[0-3600,]script`, runs before service is
|
||||
removed, unlike `post:script` that runs when service is stopped
|
||||
- Improved entropy gathering in tertiary fallback of urandom plugin
|
||||
- Reclassify `sysv` from run/task class to `service`
|
||||
|
||||
### Fixes
|
||||
- Fix #427: using an external getty with custom login program cause
|
||||
Finit to use login program as the getty command
|
||||
- Fix #428: allow `sysctl` path to be set at build time
|
||||
- Fix #429: regression in v4.9 causing Finit to segfault at shutdown
|
||||
- Fix possible memory leak when sourcing a service `env:file`
|
||||
- Finit now waits until all `post:scripts` have run before returning
|
||||
OK to `initctl <reload|runlevel>`. This also applies to the new
|
||||
`cleanup:scripts` introduced in this release
|
||||
- RFC3154 conformance formatting fix for `/dev/kmsg` fallback logging
|
||||
|
||||
|
||||
[4.9][] - 2025-02-15
|
||||
--------------------
|
||||
|
||||
> [!CAUTION]
|
||||
> This release changes how Finit reacts to the exit status of `pre:`
|
||||
> scripts. Finit will now no longer start the main process if its
|
||||
> `pre:` script fails for any reason. So, if you have pre scripts that,
|
||||
> e.g., create directories, make sure they are idempotent.
|
||||
|
||||
### Changes
|
||||
- Add individual timeout (optional) support for pre/post/ready scripts
|
||||
- Add support for systems with broken RTC, i.e., those that at power-on
|
||||
may reset the RTC to a random date instead of zero, issue #418
|
||||
- Add support for detecting "in-container" when in `systemd-nspawn`
|
||||
- Check exit status of `pre:` scripts, on failure drive service/sysv to
|
||||
`crashed` state. (The exit code of `post:` scripts remain ignored)
|
||||
- All pre/post/ready scripts are now also searched for in `$PATH`
|
||||
- Reset color attributes and clear screen when starting up. This is
|
||||
for boot loaders like GRUB, which leave background color artifacts
|
||||
|
||||
### Fixes
|
||||
- Fix #415: only mark reverse-dependencies "dirty" if the main service
|
||||
does not support SIGHUP. This helps avoid unnecessary restarts of
|
||||
services that depend on a service that supports SIGHUP
|
||||
- Fix #417: leaking inotify watchers in the cgroup subsystem
|
||||
- Fix #421: add support for `nofail` mount option in `/etc/fstab`
|
||||
- Fix #425: ordering bug in detecting .conf file changes to services
|
||||
and `initctl reload`, or runlevel changes
|
||||
- Fix `initctl touch` of template services, previously marking a
|
||||
service created from a template as "dirty" did not take
|
||||
- Fix unintended restart of template "siblings". I.e., `initctl touch`
|
||||
of instantiated template service A affected B from same template
|
||||
- Fix buggy `--with-rtc-date=DATE` configure option
|
||||
- Fix kill on timeout of pre/post/ready scripts
|
||||
|
||||
|
||||
[4.8][] - 2024-10-13
|
||||
--------------------
|
||||
|
||||
### Changes
|
||||
- Avoid remounting already mounted `/run` and `/tmp` directories. This
|
||||
extends the existing support for detecting mounted directories to
|
||||
include complex mount hierarchies are in use, overlayfs and tmpfs
|
||||
mounts. Feature by Mathias Thore, Atlas Copco
|
||||
- getty: trigger /etc/issue compat mode for Alpine Linux
|
||||
- tmpfiles.d: skip `x11.conf` unless X11 common plugin is enabled
|
||||
- tmpfiles.d: ignore x/X command, nos support for cleanup at runtime
|
||||
- Drop debug mode `-D` from `udevd` in `hotplug.conf.in`, allow the
|
||||
user to set this in `/etc/default/udevd` instead
|
||||
- Certain initctl APIs at bootstrap are not supported, update warning
|
||||
log to include command (number) for troubleshooting, issue #398
|
||||
- Add support for hwrng to urandom plugin and check for empty seed
|
||||
- Add `runparts -b` (batch mode) support, disables escape sequences
|
||||
- New configure `--without-rc-local`, disables `/etc/rc.local` support
|
||||
- New configure `--disable-cgroup` option, disables cgroup v2 detection
|
||||
- `initctl show template@foo.conf` now shows how an enabled template
|
||||
service has been evaluated by Finit, issue #411
|
||||
- Extend `initctl` timeout connecting and waiting for Finit reply. The
|
||||
previous 2 + 2 second poll timeout has proved to be too short on more
|
||||
complex systems. Now a 15 + 15 second timeout is applied which should
|
||||
be more resistant to temporary overload scenarios, issue #407
|
||||
|
||||
### Fixes
|
||||
- Fix #397: system shutdown/reboot can block on console input if action
|
||||
is started remotely (ssh). Caused by legacy TTY screen size probing,
|
||||
removed from both bootstrap and shutdown/reboot
|
||||
- Fix #400: both `HOOK_MOUNT_ERROR` and `sulogin()` fail to trigger on
|
||||
either mount or `fsck` errors. Problem caused by unresolved status
|
||||
from pipe, calling `pclose()` without extracting exit status
|
||||
- Fix #402: `initctl touch` does not respect `-n` (no error) flag
|
||||
- Fix #403: `initctl touch` does not support template services
|
||||
- Fix #404: possible undefined behavior when `--with-fstab=no` is set
|
||||
- Fix #405: `@console` getty does not work with `tty0 ttyS0`
|
||||
- Fix #409: prevent tmpfiles from following symlinks for `L+` and `R`,
|
||||
otherwise symlink targets would also be removed. Found and fixed by
|
||||
Mathias Thore and Ming Liu, Atlas Copco
|
||||
- Fix #414: Frr Zebra immediately restarts on `initctl stop zebra`.
|
||||
The fix likely works for all Frr/Quagga services due to the way they
|
||||
create and delete their pid file
|
||||
- Cosmetic issue with `[ OK ]` messages being printed out of order at
|
||||
shutdown/reboot. Caused by nested calls to `service_stop()`
|
||||
- Cosmetic issue with duplicate "Restoring RTC" message at bootstrap
|
||||
|
||||
|
||||
[4.7][] - 2024-01-07
|
||||
--------------------
|
||||
|
||||
@@ -24,6 +220,7 @@ All relevant changes are documented in this file.
|
||||
Found and fixed by Ryan Rorison
|
||||
- Fix #389: must libc requires `libgen.h` for `basename()` function.
|
||||
Reported and worked around with new `basenm()` function by Stargirl
|
||||
- Fix #392: `service/foo/ready` condition reasserted on pidfile removal
|
||||
|
||||
|
||||
[4.6][] - 2023-11-13
|
||||
@@ -241,7 +438,7 @@ All relevant changes are documented in this file.
|
||||
`/etc/finit.conf`.
|
||||
|
||||
For the complete experience a new top-level configuration file directive
|
||||
`rcsd PATH` has aslo been added. It in turn can be used by `factory.conf`
|
||||
`rcsd PATH` has also been added. It in turn can be used by `factory.conf`
|
||||
as follows to override `/etc/finit.d`:
|
||||
|
||||
rcsd /etc/factory.d
|
||||
@@ -824,7 +1021,7 @@ make sure to read the whole change log when upgrading.
|
||||
previously hard-coded in Finit, e.g., starting the bundled watchdogd,
|
||||
various distro packed udevd and other hotplugging tools
|
||||
* A proper rescue mode has been added. It is started extremely early
|
||||
and is protected with a bundled `suslogin`. Exiting rescue mode now
|
||||
and is protected with a bundled `sulogin`. Exiting rescue mode now
|
||||
brings up the system as a normal boot, as one expects
|
||||
* Support for `sysv` start/stop scripts as well as monitoring forking
|
||||
services, stared using `sysv` or `service` stanza
|
||||
@@ -1655,42 +1852,48 @@ Major bug fix release.
|
||||
|
||||
* Initial release
|
||||
|
||||
[UNRELEASED]: https://github.com/troglobit/finit/compare/4.7...HEAD
|
||||
[4.7]: https://github.com/troglobit/finit/compare/4.6...4.7
|
||||
[4.6]: https://github.com/troglobit/finit/compare/4.5...4.6
|
||||
[4.5]: https://github.com/troglobit/finit/compare/4.4...4.5
|
||||
[4.4]: https://github.com/troglobit/finit/compare/4.3...4.4
|
||||
[4.3]: https://github.com/troglobit/finit/compare/4.2...4.3
|
||||
[4.2]: https://github.com/troglobit/finit/compare/4.1...4.2
|
||||
[4.1]: https://github.com/troglobit/finit/compare/4.0...4.1
|
||||
[4.0]: https://github.com/troglobit/finit/compare/3.1...4.0
|
||||
[3.1]: https://github.com/troglobit/finit/compare/3.0...3.1
|
||||
[3.0]: https://github.com/troglobit/finit/compare/2.4...3.0
|
||||
[2.4]: https://github.com/troglobit/finit/compare/2.3...2.4
|
||||
[2.3]: https://github.com/troglobit/finit/compare/2.2...2.3
|
||||
[2.2]: https://github.com/troglobit/finit/compare/2.1...2.2
|
||||
[2.1]: https://github.com/troglobit/finit/compare/2.0...2.1
|
||||
[2.0]: https://github.com/troglobit/finit/compare/1.12...2.0
|
||||
[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.11]: https://github.com/troglobit/finit/compare/4.10...4.11
|
||||
[4.10]: https://github.com/troglobit/finit/compare/4.9...4.10
|
||||
[4.9]: https://github.com/troglobit/finit/compare/4.8...4.9
|
||||
[4.8]: https://github.com/troglobit/finit/compare/4.7...4.8
|
||||
[4.7]: https://github.com/troglobit/finit/compare/4.6...4.7
|
||||
[4.6]: https://github.com/troglobit/finit/compare/4.5...4.6
|
||||
[4.5]: https://github.com/troglobit/finit/compare/4.4...4.5
|
||||
[4.4]: https://github.com/troglobit/finit/compare/4.3...4.4
|
||||
[4.3]: https://github.com/troglobit/finit/compare/4.2...4.3
|
||||
[4.2]: https://github.com/troglobit/finit/compare/4.1...4.2
|
||||
[4.1]: https://github.com/troglobit/finit/compare/4.0...4.1
|
||||
[4.0]: https://github.com/troglobit/finit/compare/3.1...4.0
|
||||
[3.1]: https://github.com/troglobit/finit/compare/3.0...3.1
|
||||
[3.0]: https://github.com/troglobit/finit/compare/2.4...3.0
|
||||
[2.4]: https://github.com/troglobit/finit/compare/2.3...2.4
|
||||
[2.3]: https://github.com/troglobit/finit/compare/2.2...2.3
|
||||
[2.2]: https://github.com/troglobit/finit/compare/2.1...2.2
|
||||
[2.1]: https://github.com/troglobit/finit/compare/2.0...2.1
|
||||
[2.0]: https://github.com/troglobit/finit/compare/1.12...2.0
|
||||
[1.12]: https://github.com/troglobit/finit/compare/1.11...1.12
|
||||
[1.11]: https://github.com/troglobit/finit/compare/1.10...1.11
|
||||
[1.10]: https://github.com/troglobit/finit/compare/1.9...1.10
|
||||
[1.9]: https://github.com/troglobit/finit/compare/1.8...1.9
|
||||
[1.8]: https://github.com/troglobit/finit/compare/1.7...1.8
|
||||
[1.7]: https://github.com/troglobit/finit/compare/1.6...1.7
|
||||
[1.6]: https://github.com/troglobit/finit/compare/1.5...1.6
|
||||
[1.5]: https://github.com/troglobit/finit/compare/1.4...1.5
|
||||
[1.4]: https://github.com/troglobit/finit/compare/1.3...1.4
|
||||
[1.3]: https://github.com/troglobit/finit/compare/1.2...1.3
|
||||
[1.2]: https://github.com/troglobit/finit/compare/1.1...1.2
|
||||
[1.1]: https://github.com/troglobit/finit/compare/1.0...1.1
|
||||
[1.0]: https://github.com/troglobit/finit/compare/0.9...1.0
|
||||
[0.9]: https://github.com/troglobit/finit/compare/0.8...0.9
|
||||
[0.8]: https://github.com/troglobit/finit/compare/0.7...0.8
|
||||
[0.7]: https://github.com/troglobit/finit/compare/0.6...0.7
|
||||
[0.6]: https://github.com/troglobit/finit/compare/0.5...0.6
|
||||
[0.5]: https://github.com/troglobit/finit/compare/0.4...0.5
|
||||
[0.4]: https://github.com/troglobit/finit/compare/0.3...0.4
|
||||
[0.3]: https://github.com/troglobit/finit/compare/0.2...0.3
|
||||
[0.2]: https://github.com/troglobit/finit/compare/0.1...0.2
|
||||
[1.9]: https://github.com/troglobit/finit/compare/1.8...1.9
|
||||
[1.8]: https://github.com/troglobit/finit/compare/1.7...1.8
|
||||
[1.7]: https://github.com/troglobit/finit/compare/1.6...1.7
|
||||
[1.6]: https://github.com/troglobit/finit/compare/1.5...1.6
|
||||
[1.5]: https://github.com/troglobit/finit/compare/1.4...1.5
|
||||
[1.4]: https://github.com/troglobit/finit/compare/1.3...1.4
|
||||
[1.3]: https://github.com/troglobit/finit/compare/1.2...1.3
|
||||
[1.2]: https://github.com/troglobit/finit/compare/1.1...1.2
|
||||
[1.1]: https://github.com/troglobit/finit/compare/1.0...1.1
|
||||
[1.0]: https://github.com/troglobit/finit/compare/0.9...1.0
|
||||
[0.9]: https://github.com/troglobit/finit/compare/0.8...0.9
|
||||
[0.8]: https://github.com/troglobit/finit/compare/0.7...0.8
|
||||
[0.7]: https://github.com/troglobit/finit/compare/0.6...0.7
|
||||
[0.6]: https://github.com/troglobit/finit/compare/0.5...0.6
|
||||
[0.5]: https://github.com/troglobit/finit/compare/0.4...0.5
|
||||
[0.4]: https://github.com/troglobit/finit/compare/0.3...0.4
|
||||
[0.3]: https://github.com/troglobit/finit/compare/0.2...0.3
|
||||
[0.2]: https://github.com/troglobit/finit/compare/0.1...0.2
|
||||
[libuEv]: https://github.com/troglobit/libuev
|
||||
[dea3ae8]: https://github.com/troglobit/finit/commit/dea3ae8
|
||||
+11
-4
@@ -1,4 +1,11 @@
|
||||
docsdir := @docdir@/doc
|
||||
docs_DATA = config.md conditions.md distro.md plugins.md \
|
||||
service.md signals.md svc-machine.png cmdline.md
|
||||
EXTRA_DIST = $(docs_DATA)
|
||||
SUBDIRS = config
|
||||
EXTRA_DIST = AUTHORS ChangeLog.md
|
||||
|
||||
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
-1
@@ -1 +1 @@
|
||||
config.md
|
||||
index.md
|
||||
+30
-34
@@ -1,15 +1,5 @@
|
||||
Building
|
||||
========
|
||||
|
||||
* [Introduction](#introduction)
|
||||
* [Configure](#configure)
|
||||
* [Example](#example)
|
||||
* [Running](#running)
|
||||
* [Debugging](#debugging)
|
||||
|
||||
|
||||
Introduction
|
||||
------------
|
||||
Building Finit
|
||||
==============
|
||||
|
||||
Finit comes with a traditional configure script to control features and
|
||||
optional plugins to enable. It depends on two external libraries:
|
||||
@@ -17,14 +7,15 @@ optional plugins to enable. It depends on two external libraries:
|
||||
- [libuEv][], the event loop
|
||||
- [libite][] (-lite), much needed frog DNA
|
||||
|
||||
**NOTE:** Most free/open source software that uses `configure` default
|
||||
to install to `/usr/local`. However, some Linux distributions do no
|
||||
longer search that path for installed software, e.g. Fedora and Alpine
|
||||
Linux. To get finit's configure script to find its dependencies you
|
||||
have to help the `pkg-config` tool a bit if you do not change the
|
||||
default prefix path:
|
||||
|
||||
PKG_CONFIG_LIBDIR=/usr/local/lib/pkgconfig ./configure
|
||||
> [!IMPORTANT]
|
||||
> Most free/open source software packages that use `configure` default
|
||||
> to install to `/usr/local`. However, some Linux distributions do no
|
||||
> longer search that path for installed software, e.g. Fedora and Alpine
|
||||
> Linux. To get finit's configure script to find its dependencies you
|
||||
> have to help the `pkg-config` tool a bit if you do not change the
|
||||
> default prefix path:
|
||||
>
|
||||
> PKG_CONFIG_LIBDIR=/usr/local/lib/pkgconfig ./configure
|
||||
|
||||
The configure script checks for all dependencies, including the correct
|
||||
version of the above mentioned libraries. Currently required versions:
|
||||
@@ -71,12 +62,13 @@ Below are a few of the main switches to configure:
|
||||
|
||||
For more configure flags, see <kbd>./configure --help</kbd>
|
||||
|
||||
> **Note:** the configure script is not available in the GIT sources. It is
|
||||
> however included in (officially supported) released tarballs. The
|
||||
> idea is that you should not need GNU autotools to build, only the
|
||||
> above mentioned dependencies, a POSIX shell, a C compiler and make.
|
||||
> Any contributing to Finit can generate it from `configure.ac` using
|
||||
> the `autogen.sh` script.
|
||||
> [!NOTE]
|
||||
> The configure script is not available in the GIT sources. It is
|
||||
> however included in (officially supported) released tarballs. The
|
||||
> idea is that you should not need GNU autotools to build, only the
|
||||
> above mentioned dependencies, a POSIX shell, a C compiler and make.
|
||||
> Any contributing to Finit can generate it from `configure.ac` using
|
||||
> the `autogen.sh` script.
|
||||
|
||||
|
||||
Example
|
||||
@@ -115,10 +107,11 @@ Linux config to:
|
||||
|
||||
CONFIG_UEVENT_HELPER_PATH="/sbin/mdev"
|
||||
|
||||
**Note:** If you run into problems starting Finit, take a look at
|
||||
`finit.c`. One of the most common problems is a custom Linux kernel
|
||||
build that lack `CONFIG_DEVTMPFS`. Another is too much cruft in the
|
||||
system `/etc/fstab`.
|
||||
> [!TIP]
|
||||
> If you run into problems starting Finit, take a look at `finit.c`.
|
||||
> One of the most common problems is a custom Linux kernel build that
|
||||
> lack `CONFIG_DEVTMPFS`. Another is too much cruft in the system
|
||||
> `/etc/fstab`.
|
||||
|
||||
|
||||
Running
|
||||
@@ -157,8 +150,10 @@ enabled. The default Finit rescue mode configuration is installed into
|
||||
|
||||
By default the a root shell, without login, is started.
|
||||
|
||||
> **Note:** in this mode `initctl` will not work. Use the `-f` flag to
|
||||
> force `reboot`, `shutdown`, or `poweroff`.
|
||||
> [!IMPORTANT]
|
||||
> In rescue mode `initctl` will not work, the same goes for `reboot`,
|
||||
> `shutdown`, and `poweroff` commands, provided they are the Finit
|
||||
> versions of these commands. Use the `-f` flag to force the action.
|
||||
|
||||
|
||||
Debugging
|
||||
@@ -187,8 +182,9 @@ kernel usually reboots: `configure --enable-emergency-shell`. However,
|
||||
the behavior of Finit is severely limited when this is enabled, so use
|
||||
it only for debugging start up issues when Finit crashes.
|
||||
|
||||
**NOTE:** Neither of these options should be enabled on production
|
||||
systems since they can potentially give a user root access.
|
||||
> [!CAUTION]
|
||||
> None of these options should be enabled on production systems since
|
||||
> they can potentially give a user root access.
|
||||
|
||||
|
||||
[1]: ftp://troglobit.com/finit/finit-4.3.tar.gz
|
||||
|
||||
+17
-16
@@ -4,10 +4,11 @@ Tips & Tricks with the kernel cmdline
|
||||
This document summarizes the different boot parameters that can be
|
||||
passed on the Linux kernel command line. Not limited to Finit.
|
||||
|
||||
The `bool` setting is one of `on, off, true false, 1, 0`.
|
||||
> [!IMPORTANT]
|
||||
> Remember to use `--` to separate kernel parameters from parameters to
|
||||
> init. E.g., `init=/sbin/finit -- finit.debug rescue`
|
||||
|
||||
> **NOTE:** remember to use `--` to separate kernel parameters from
|
||||
> parameters to init. E.g., `init=/sbin/finit -- finit.debug rescue`
|
||||
The `bool` setting is one of `on, off, true false, 1, 0`.
|
||||
|
||||
* `debug`: Enable kernel debug. Debug messages are printed to the
|
||||
console until Finit starts up, unless `loglevel=7` (below) is used.
|
||||
@@ -28,19 +29,20 @@ The `bool` setting is one of `on, off, true false, 1, 0`.
|
||||
system bootstrap.
|
||||
|
||||
Very useful for selecting different boot modes, e.g. manufacturing test,
|
||||
firmware upgrade, or rescue mode.
|
||||
firmware upgrade, or [rescue mode][rescue].
|
||||
|
||||
> Note: `<boot/...>` conditions cannot be cleared with `initctl`!
|
||||
> [!NOTE]
|
||||
> `<boot/...>` conditions cannot be cleared with `initctl`!
|
||||
|
||||
* `finit.config=/path/to/alternative/finit.conf`: override the
|
||||
compile-time bootstrap config file, default:
|
||||
|
||||
./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
|
||||
directive `rcsd /path/to/finit.d` to override the default
|
||||
rcS.d directory.
|
||||
directive `rcsd /path/to/finit.d` to override the default rcS.d
|
||||
directory.
|
||||
|
||||
* `finit.debug[=bool]`: Enable finit debug. This is operated
|
||||
independently of the kernel `debug` setting. New as of Finit v4.
|
||||
@@ -73,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
|
||||
shell. Note, this shell is very limited and does not support
|
||||
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
|
||||
than `debug`. Also, when `loglevel=7`, Finit will *not disable*
|
||||
@@ -88,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
|
||||
errors. Also, see `loglevel` and `quiet` above.
|
||||
|
||||
* `rescue`: Start rescue/maintenance mode. If your system comes with
|
||||
the bundled `sulogin` program (Finit, or from util-linux/Busybox),
|
||||
you will be given a root login to a maintenance shell. However, if
|
||||
`sulogin` is missing, the file `/lib/finit/rescue.conf` is read and
|
||||
the system booted in a limited fallback mode. See [config.md][]
|
||||
for more information.
|
||||
* `rescue`: Start [rescue/maintenance mode][rescue]. If your system
|
||||
comes with the bundled `sulogin` program (Finit, or from util-linux,
|
||||
or Busybox), you will be given a root login to a maintenance shell.
|
||||
However, if `sulogin` is missing, the file `/lib/finit/rescue.conf`
|
||||
is read and the system booted in a limited fallback mode.
|
||||
|
||||
This option can be disabled with `configure --without-rescue`
|
||||
|
||||
@@ -114,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)][].
|
||||
|
||||
[config.md]: config.md#rescue-mode
|
||||
[rescue]: config/rescue.md
|
||||
[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.
|
||||
+27
-29
@@ -1,21 +1,8 @@
|
||||
Finit Conditions
|
||||
================
|
||||
Conditions
|
||||
==========
|
||||
|
||||

|
||||
|
||||
* [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:
|
||||
Conditions were added to Finit 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 basic network access to be available"*
|
||||
@@ -47,9 +34,10 @@ both the `pid/setupd` *and* `pid/zebra` conditions are satisfied. A
|
||||
`pid/` condition is satisfied by the corresponding service's PID file
|
||||
being created, i.e., the service's default readiness notification.
|
||||
|
||||
**NOTE:** Conditions also stop services when a condition is no longer
|
||||
asserted. I.e., if the Zebra process above stops or restarts, netd
|
||||
will also stop or restart.
|
||||
> [!IMPORTANT]
|
||||
> Conditions also stop services when a condition is no longer asserted.
|
||||
> I.e., if the `zebra` process above stops or restarts, `netd` will also
|
||||
> stop or restart.
|
||||
|
||||
Another example is `dropbear`, it does not support `SIGHUP`, but we can
|
||||
also see optional sourcing of arguments from an environment file:
|
||||
@@ -88,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
|
||||
services, or run/task jobs, on external site-dependent stimuli.
|
||||
Example:
|
||||
|
||||
**Example:**
|
||||
|
||||
service [2345] <usr/foo> alarm --arg foo -- Foo alarm
|
||||
|
||||
@@ -106,11 +95,16 @@ on this, see [Internals](#internals).) Thus, after a reconfiguration it
|
||||
is up to the "owner" of the condition to convey the new (or possibly
|
||||
unchanged) state of it.
|
||||
|
||||
> **Note:** For `pid/` conditions it is expected that services "touch"
|
||||
> or recreate their PID file on `SIGHUP`.
|
||||
|
||||
Static (one-shot) conditions, like `usr/`, never enter the `flux` state.
|
||||
|
||||
> [!IMPORTANT]
|
||||
> For `pid/` conditions it is expected that the service reassert, i.e.,
|
||||
> "touch" or recreate, their PID file on `SIGHUP`. This can be done by
|
||||
> calling `utimensat()` on the PID file. Provided, of course, that the
|
||||
> service supports reloading on `SIGHUP`, otherwise it will be restarted
|
||||
> by Finit when they instead exit on the signal. For such services, use
|
||||
> `<!>` to tell Finit the service does not support `SIGHUP`.
|
||||
|
||||
|
||||
Built-in Conditions
|
||||
-------------------
|
||||
@@ -171,9 +165,10 @@ Built-in conditions:
|
||||
- `boot/arg`
|
||||
- `dev/node` and `dev/dir/node`
|
||||
|
||||
**Note:** `up` means administratively up, the interface flag `IFF_UP`.
|
||||
`running` is the `IFF_RUNNING` flag, meaning operatively up. The
|
||||
difference is that `running` tells if the NIC has link.
|
||||
> [!NOTE]
|
||||
> Here, `up` means administratively up, the interface flag `IFF_UP`.
|
||||
> `running` is the `IFF_RUNNING` flag, meaning operatively up. The
|
||||
> difference is that `running` tells if the NIC has link.
|
||||
|
||||
|
||||
Composition
|
||||
@@ -205,8 +200,9 @@ the service stanza for the daemon. It is far from optimal since any
|
||||
synchronization of depending services may fail due to the daemon not
|
||||
having reinitialized/created their IPC sockets, or similar.
|
||||
|
||||
> **Note:** in versions of Finit prior to v4, the PID conditions were
|
||||
> called 'svc' conditions, and they were far more complex.
|
||||
> [!NOTE]
|
||||
> In versions of Finit prior to v4, the PID conditions were called 'svc'
|
||||
> conditions, and they were far more complex.
|
||||
|
||||
|
||||
Debugging
|
||||
@@ -269,6 +265,8 @@ A condition is always in one of three states:
|
||||
All conditions that have not explicitly been set are interpreted as
|
||||
being in the `off` state.
|
||||
|
||||

|
||||
|
||||
When a reconfiguration is requested, Finit transitions all conditions to
|
||||
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
|
||||
|
||||
-1409
File diff suppressed because it is too large.
Load diff
@@ -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
|
||||
Symlink
+1
@@ -0,0 +1 @@
|
||||
index.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,63 @@
|
||||
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
|
||||
|
||||
Output Buffering
|
||||
----------------
|
||||
|
||||
When using the `log` directive, Finit redirects the service's stdout and
|
||||
stderr to a pipe connected to a logger process. Programs detect this as
|
||||
non-interactive output (i.e., `isatty()` returns false) and typically
|
||||
switch from line-buffered to fully-buffered mode.
|
||||
|
||||
Most well-behaved daemons explicitly flush their output or use syslog
|
||||
directly, so this is rarely an issue. However, if a service's log
|
||||
messages appear delayed or batched, you can force line-buffered output
|
||||
by wrapping the command with `stdbuf`:
|
||||
|
||||
service log /usr/bin/stdbuf -oL /path/to/command -- My service
|
||||
|
||||
The `-oL` option forces line-buffered output, and `-o0` forces unbuffered
|
||||
output. See `stdbuf(1)` for details.
|
||||
|
||||
> [!NOTE]
|
||||
> Using `stdbuf` is rarely necessary. Only use it if you observe actual
|
||||
> buffering issues with a specific service.
|
||||
@@ -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,186 @@
|
||||
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.
|
||||
|
||||
**Syntax:** `reboot-watchdog <on|off|true|false|1|0>`
|
||||
|
||||
Controls whether the system should reboot via the watchdog timer (WDT)
|
||||
or directly via the SoC/kernel. When enabled, Finit will:
|
||||
|
||||
1. Send `SIGPWR` to the registered watchdog daemon before shutdown
|
||||
2. Send `SIGTERM` to the watchdog daemon and wait up to 10 seconds
|
||||
for the watchdog to trigger a hardware reset
|
||||
|
||||
When disabled (default), Finit skips the watchdog reboot logic and
|
||||
calls the kernel's `reboot(2)` syscall directly for a clean SoC reboot.
|
||||
|
||||
*Default:* off (reboot via SoC)
|
||||
|
||||
> [!NOTE]
|
||||
> This setting only affects reboots. The watchdog daemon will still
|
||||
> run and monitor the system during normal operation.
|
||||
@@ -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
|
||||
+3
-2
@@ -34,8 +34,9 @@ build time:
|
||||
./configure --with-rcsd=/etc/init.d --with-config=/etc/init.d/init.conf
|
||||
```
|
||||
|
||||
> **Note:** remember `--prefix` et al as well, the default is likely
|
||||
> *not* what you want. See the [build docs][1] for details.
|
||||
> [!IMPORTANT]
|
||||
> Remember `--prefix` et al as well, the default is likely *not* what
|
||||
> you want. See the [build docs][1] for details.
|
||||
|
||||
The resulting directory structure is depicted below. Please notice how
|
||||
`/etc/finit.conf` now resides in the same sub-directory as a non-symlink
|
||||
|
||||
+137
@@ -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,11 @@
|
||||
.md-header__topic:first-child {
|
||||
font-weight: 500;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.md-header__title {
|
||||
font-size: 1.1rem;
|
||||
font-style: italic;
|
||||
font-weight: 500;
|
||||
line-height: 2.6rem;
|
||||
}
|
||||
+178
@@ -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
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Binary file not shown.
|
After Width: | Height: | Size: 5.8 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 320 KiB |
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Do not edit this file with editors other than draw.io -->
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" style="background: transparent; background-color: transparent; color-scheme: light dark;" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="732px" height="1006px" viewBox="-0.5 -0.5 732 1006" content="<mxfile host="app.diagrams.net" agent="Mozilla/5.0 (X11; Linux x86_64; rv:135.0) Gecko/20100101 Firefox/135.0" version="26.0.15" scale="1" border="0">
 <diagram name="Page-1" id="FNw5HM3Bq2xN372-o7V3">
 <mxGraphModel dx="2049" dy="1094" grid="0" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0">
 <root>
 <mxCell id="0" />
 <mxCell id="1" parent="0" />
 <mxCell id="2" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;sketch=1;orthogonalLoop=1;jettySize=auto;html=1;fontFamily=Architects Daughter;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchitects%2BDaughter;fontSize=14;" edge="1" source="4" target="7" parent="1">
 <mxGeometry relative="1" as="geometry" />
 </mxCell>
 <mxCell id="3" style="edgeStyle=orthogonalEdgeStyle;rounded=1;sketch=1;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=0;entryDx=0;entryDy=0;fontFamily=Architects Daughter;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchitects%2BDaughter;fontSize=14;" edge="1" source="4" target="19" parent="1">
 <mxGeometry relative="1" as="geometry">
 <Array as="points">
 <mxPoint x="421" y="328" />
 <mxPoint x="265" y="328" />
 <mxPoint x="183" y="329" />
 </Array>
 </mxGeometry>
 </mxCell>
 <mxCell id="4" value="&lt;font style=&quot;font-size: 16px&quot;&gt;&lt;b&gt;&lt;font data-font-src=&quot;https://fonts.googleapis.com/css?family=Architects+Daughter&quot; style=&quot;font-size: 16px&quot; face=&quot;Architects Daughter&quot;&gt;STOPPING&lt;/font&gt;&lt;/b&gt;&lt;/font&gt;" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f8cecc;strokeColor=#b85450;sketch=1;" vertex="1" parent="1">
 <mxGeometry x="360.89" y="226" width="120" height="60" as="geometry" />
 </mxCell>
 <mxCell id="5" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;sketch=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.25;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" edge="1" source="10" target="21" parent="1">
 <mxGeometry relative="1" as="geometry">
 <Array as="points">
 <mxPoint x="390.89" y="729" />
 <mxPoint x="264.89" y="729" />
 </Array>
 </mxGeometry>
 </mxCell>
 <mxCell id="6" style="edgeStyle=orthogonalEdgeStyle;rounded=0;sketch=1;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.25;entryY=0;entryDx=0;entryDy=0;fontFamily=Architects Daughter;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchitects%2BDaughter;fontSize=14;exitX=0.25;exitY=1;exitDx=0;exitDy=0;" edge="1" source="7" target="10" parent="1">
 <mxGeometry relative="1" as="geometry" />
 </mxCell>
 <mxCell id="7" value="&lt;font style=&quot;font-size: 16px&quot;&gt;&lt;b&gt;&lt;font data-font-src=&quot;https://fonts.googleapis.com/css?family=Architects+Daughter&quot; style=&quot;font-size: 16px&quot; face=&quot;Architects Daughter&quot;&gt;HALTED&lt;/font&gt;&lt;/b&gt;&lt;/font&gt;" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f8cecc;strokeColor=#b85450;sketch=1;" vertex="1" parent="1">
 <mxGeometry x="360.89" y="526" width="120" height="Line truncated
|
||||
|
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/
|
||||
+145
@@ -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
|
||||
kill <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.
|
||||
+22
-23
@@ -1,12 +1,6 @@
|
||||
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
|
||||
monitors, or hook plugins. It is even possible to run scripts at these
|
||||
hook points, see below.
|
||||
@@ -35,9 +29,10 @@ For your convenience a set of *optional* plugins are available:
|
||||
files distributed with Finit. It is read first but can be overridden
|
||||
by any of the standard tmpfiles.d directories, e.g. `/etc/tmpfiles.d`.
|
||||
|
||||
> **Note:** On an embedded system both `/var` and `/run` can be `tmpfs`
|
||||
> RAM disks and `/dev` is usually a `devtmpfs`. This must be defined
|
||||
> in the `/etc/fstab` file and in the Linux kernel config.
|
||||
> [!NOTE]
|
||||
> On an embedded system both `/var` and `/run` can be `tmpfs` RAM
|
||||
> disks and `/dev` is usually a `devtmpfs`. This must be defined in
|
||||
> the `/etc/fstab` file and in the Linux kernel config.
|
||||
|
||||
* *dbus.so*: Setup and start system message bus, D-Bus, at boot.
|
||||
_Optional plugin._
|
||||
@@ -63,8 +58,9 @@ For your convenience a set of *optional* plugins are available:
|
||||
|
||||
Enabled by default.
|
||||
|
||||
> See the [Services](config.md#services) section in the configuration
|
||||
> guide for an example how to run `mdevd`, alternative to plain mdev.
|
||||
> [!TIP]
|
||||
> See the [Services](config/services.md) section in the configuration
|
||||
> guide for an example how to run `mdevd`, alternative to plain mdev.
|
||||
|
||||
* *rtc.so*: Restore and save system clock from/to RTC on boot/halt.
|
||||
Enabled by default.
|
||||
@@ -89,16 +85,17 @@ For your convenience a set of *optional* plugins are available:
|
||||
|
||||
set index 1234
|
||||
|
||||
**Note:** unlike the traditional .conf `module` directive, which load
|
||||
any listed module immediately, this plugin creates a background `task`
|
||||
which load the module(s) in the background. The program is modprobe,
|
||||
`/sbin/modprobe`, which you can override per .conf file:
|
||||
Since these tasks run in the background, they return `[ OK ]` at boot,
|
||||
unless the modprobe tool does not exist. Check syslog for warnings
|
||||
and the actual status of the operation using `initctl`.
|
||||
|
||||
set modprobe /path/to/maybe-a-modprobe-wrapper
|
||||
|
||||
Since these tasks run in the background, they usually return `[ OK ]`
|
||||
at boot, unless the modprobe tool does not exist. Check syslog for
|
||||
warnings and the actual status of the operation using `initctl`.
|
||||
> [!IMPORTANT]
|
||||
> Unlike the traditional .conf `module` directive, which load any listed
|
||||
> module immediately, this plugin creates a background `task` which load
|
||||
> the module(s) in the background. The program is modprobe,
|
||||
> `/sbin/modprobe`, which you can override per .conf file:
|
||||
>
|
||||
> set modprobe /path/to/maybe-a-modprobe-wrapper
|
||||
|
||||
* *netlink.so*: Listens to Linux kernel Netlink events for gateway and
|
||||
interfaces. These events are then sent to the Finit service monitor
|
||||
@@ -132,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
|
||||
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.
|
||||
|
||||
All hook scripts are called with at least one environment variable set,
|
||||
@@ -158,8 +155,10 @@ hook points:
|
||||
EOF
|
||||
$ chmod +x /libexec/finit/hook/sys/down/foo.sh
|
||||
|
||||
> **Note:** to use hook scripts, even for pre-bootstrap and pre-shutdown
|
||||
> tasks, you must build with `configure --enable-hook-scripts-plugin`.
|
||||
> [!IMPORTANT]
|
||||
> To use hook scripts, even for pre-bootstrap and pre-shutdown tasks,
|
||||
> you must build with `configure --enable-hook-scripts-plugin`.
|
||||
|
||||
|
||||
### Bootstrap Hooks
|
||||
|
||||
|
||||
@@ -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
|
||||
+13
-43
@@ -1,15 +1,13 @@
|
||||
Finit Services
|
||||
==============
|
||||
|
||||
Starting & Monitoring
|
||||
---------------------
|
||||
=====================
|
||||
|
||||
Finit can start and monitor the following types of daemons:
|
||||
|
||||
* Forks to background, creates a PID file
|
||||
* Runs in foreground:
|
||||
- creates a PID file
|
||||
* Runs in foreground and signals ready by:
|
||||
- creating a PID file
|
||||
- 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:
|
||||
|
||||
@@ -22,10 +20,12 @@ Finit can *not* start and monitor a daemon that:
|
||||
| ✔ | No | No | Yes, optionally |
|
||||
| ✘ | Yes | No | No |
|
||||
|
||||
> **Note:** PID files is one mechanism used to assert conditions to
|
||||
> synchronize the start and stop of other, dependent, services.
|
||||
> [!NOTE]
|
||||
> PID files is one mechanism used to assert conditions to synchronize
|
||||
> 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
|
||||
traditional one used also for `sysv` start/stop scripts, and the latter
|
||||
@@ -39,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
|
||||
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
|
||||
|
||||
### 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
|
||||
need it to synchronize start/stop of a dependent service.
|
||||
|
||||
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
|
||||
|
||||
|
||||
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.
|
||||
[1]: config/service-sync.md
|
||||
@@ -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.
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 230 KiB |
@@ -1,4 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Do not edit this file with editors other than diagrams.net -->
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" style="background-color: rgb(255, 255, 255);" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="732px" height="888px" viewBox="-0.5 -0.5 732 888" content="<mxfile host="app.diagrams.net" modified="2022-08-23T13:29:07.417Z" agent="5.0 (X11)" version="20.2.4" etag="2-w-AmAkF4Yj3b3JyTHu" type="google"><diagram id="2QNQ_rVyMpIu31uE8ppT">7V1Zc6O4Gv01rpl+iEuA2B6dpXu6KpNJJenq248EZJvbGPkCznIf5rePxGaEZAwYMOnBU5M2QggkHc63Sp4pV5u3L4G1Xf+JHeTNZOC8zZTrmSzLQDXIP7TkPSmRgAmTklXgOkkZ2Bc8uv9HWcW0dOc6KEzLkqIIYy9yt2yhjX0f2RFTZgUBfmWrLbHnMAVba4W4gkfb8vjS764TrZNSQ9b35X8gd7XO7ixpZnJmY2WV056Ea8vBr4Ui5WamXAUYR8m3zdsV8ujosePy+cDZ/MEC5Ed1LpCTC14sb5f2LX2u6D3rLHJI39NDHERrvMK+5d3sSy8DvPMdRFsE5Cj8iSKb9lIiB/sLbjHepoX/RVH0ns6qtYswKVpHGy89u8R+9NnauB5FxyKw125E5jAkD0UqkzFFQVrpEe8Cm7axjiIy8bKqLMgf0lX6h1YI5yuMVx6ytm44t/EmPmGHcdXPy+QW5CtzE1W+LN8meVAJkuNkcOiIMOMdZk9CDlMkR1awQukU6PysSPlck7cE4Q2KAvIsIECeFbkvbOtWitZVXm8/oeRLOqfi+VVOmk6pg+kkXQ7e/0OxMVezwx8pVOKD6zfm6D09+vVgIJnd4yC+dBEE1nuhwha7Pu1E3vI9LSAVUgaGMpgb6cOkFCwbGssTpUtkDR65hHxJnmOPy7xDtaAKBVSkeVE6/AyItf/tcHbiIownhsw5kLTt2/4k+bZK/41beS4XpM06VmRdJC0FNtN8AijaNAHTASjFQMphxIJoD6HCQzXvBlhaNnuB+HXgev749Nf9/de7L1mH006Ux4EUc2PDVS2xCMsRr/RpHrfJY74SoV9idNfzrrCHg/haZWnYyLYptUQB/okKZ54NFaqcDElxgYIIvR0UcwdepPQCReMQL5kJfMHrXoJLmVheF6S3Bk6nYbVbMdsJL7+5UULLspoe/iic2rMyPchIuS2Z1yDMTLcrMmaDie6XMRWTw4+mmk0Zs3TJyYypnV1XK+BB/mWke6s3owbCdYFKAM6nGuqTvO1Y3v6xuH26uZ6krUDaQmVAaWuM0KhlJ8VRkeFA0aQY8rOiaQwLjVY8K30ZNAKLRSojSjcNtpXkydILS2BpJlfN8eGnMLM6M7XSkandw0gv4ghU4qg5hbRE0Bk9I9njTPKvM/n3ffH1aYTmpkr/E6FXiz/lt5M+SKFS8ulNMKoaHE4wShI3smczO4tklIu4ruhoT5eMGNxLxRMEocLTGBxKDkoCAAGtlhxsavKSO5nQLHyYu5qaXmy84dWZ6dqVISyNMIyRAV1igK5XI/0QbvVjwG2uX7aEunROka1MIrtjkX2/+PY4OpPVsZCxFBK8ZhvoedmDySqpHLGaij6gZIajIawmBmdbElHOSCIj9MW3UHDyyTJNVsJABVZOGT24R4FLBo56P2tPYw+8f8DWN8iraBxTHbpWd6AhNVJwdF07qX6lCiR4Oi6YIAFosiORTFcXDhBJG68+xRoOck19KneTFC9roE8dl0gN3qHRUOHhEIDjvhzQhSYVq6GK9fDt7q4jr0hezExPl5rXcbuh+2AB59odVvMyzi/+P0QwtFut0OSp8JyWpcjlP9HeKbR3dXuzuPt2PzLTcrlcymLV2tGeNbUPgpMBp7spmcNqCILLU41H4PRtQCKjJsVC2gtRogqq5QWYAyAfUS7joxY2WJ7rPkQMtqkBJch30nW50iZSDKODSwygl16HKktKdE9TZ8eiu0hyNsqTXOkuqfXmaZIqQqmiGQPm2GQegQKytziM4skujSzpZMQOHztMPvZRaUzTIstzVz45tMmgxERMh8y1LW+Rnti4jhPLK9F8VfgfxixcugAHn64qazw4oAAbchfY4OM0f19NsBgjLEyF10R7gwW/wuNigsX5YWGW/O0lhEDeGdMbQkSxmcsJI+fHiIg6jAGpgw9IXNxMsDg7LKBKnbdg/4EMRFQoDQcRUTCDcgewfId2KqCWSGgH7jaakHN25BB9dG6qrP2iGAL7Re4JLvwiAcoogMytDCa1ZAQIUaHO5hCW1BKVA4vWF7WIogOTWjICjIjWhejD6auKaA1B2dfuOwu65QidXc8KQ9eefZzgX8s0aoGzi3Nst4v8FSZVFUxqVnZqmjVgTSJDZyAGtVIO0oHMG65dlc8yVI16+UwtnM8K73wOSeuT9nN+3pKAVJUfDyG/KKQ3DuMduUS4TcbV+UGiQJNjiwENKuVwtn2cfgSyed3HaDy0jPiIDVWrL8j/N7717JGZPJDG1Kbpq7TpK+w7buRi//fwU5ft36ft338lVQHBNoqFi+W85wG44Fh6Vpv7PqT3fSC3cn1Egdjn7RLbOL0nObjIzOQOb5EFh5J7kKPSTY737CghVXBP/FD/DubxrGfkXeLAQUFpMELSP9dfkQK4P3qKczjAvuA2Hqq4ZJvlKDzmVwKO+GdEDY4/3bCeZlR5o2XhPgLGPFsEt2a23dM7YMFpW6oD3Wgdwb/+6+5mbAH88awRVmWpwu2hSLwC0FuMX1F5a3ZKjRVYx8122+gppVaw42BGXmdPDoOSUfb2ymr1joOiS45sUqgaVa9O5X6F/O2VwykUTc3+eEVT6T3O3Jc9mP18rCzY+eSqyAp/Tmbd2c06aHI+yyGTc7K1FROpD7neQRGw82ArKmWdz0A35ZZcJnFOCZh1rgcu46N0G8vfWaT+4h1RxMTB3bIF6fpuZEe0od8D9Glyeo6E+HS5LNEVQbAm8Y32RH6H1/lMKx473Hd48dDVRlD/kiWP2SKGQew6WCds+UtukFhHUgtWJg64+QFvdmhl8VpbVCs8zMouse5ENeSjjWzKFXCo+JzE8LnFsKwRMSwzsNCzuDnLPkKvahdiGLbhm1/Z6rB3wUsuv/ryD/Ww08SB9IlS5pbBos2E9eyFpk4mSWeVSxNUu4ukLKu4bf20H539AAYfcN0bMmRKsCUwdfiSx69f6A8/0Ld5nQQsl+5qF9DwjQzwjnbIXVIcBNiOI4sgXOOdR9oGz7S261Ppt3bpGYJun9ZdIR8FFg2w1iDwHrma8z6M+aXuNUxm6FUJJLpoKaCu8GwugdIuyq3onI+RtQFunh+QZmw/3Cyuf1BUxph9tdwowfAyztG1ZvHveyVh/5lMMwHQfDWPr8bRmtolGcTnE2jHAdrqlF6oKkOCll9rlCR2TIsERqOqKrpZ9hhJQJM5lBhqT3pqx/ugDWYbMyDpYO/4Bj+E4ljhOu9sDbVUuCnaYPa2YkIeYVlKZGODm4buy41J9X6moPkvEgnupVbvQUhXax255nQltuaecjTF7Wh2WV5kbSgR+s/hNn6DZvTlvrw/rFQ0Th2bmLxnJjeVuWKWXw0+y1kVMXnJXGzF5G12eZs8Did6HPram4hnNk1hPQ5lRq+XbdF4j3xY8gjIRxJUsn2/WtbPO9IZW/PxsO9rRB0AIQpeXJv6A0JCbJZHUftbrCD/Rt9YeoKwnhe7CgpJ0SD39iY2XJS0hjZulFfN+Tym6vDFzgtSto7tusSsA+SdIn8Cd7WKLbrMsitmtHxOnzWswfOTmTeEmacStb3CNyEy82Se940OrDy1RqiLpcIjy/U+4Hz3GCzLPD+jWbmnmlUeBq2sStTW7E25Qr6oZikxsCPxUt2Z7K6HFxvK9a8+WZKofPjv7tvtbdFJF6frBFQCEHGCy2fm8zO76T6USv7BF3lACMrmgJbFJItiIQuJMEzRfL9fchhgmqKyBzeZ/fWf2EG0xj8=</diagram></mxfile>"><defs><style type="text/css">@font-face { font-family: "Architects Daughter"; src: url("data:application/x-font-ttf;charset=utf-8;base64,AAEAAAAMAIAAAwBAT1MvMoWwV7IAAGWAAAAAYGNtYXDPBugkAABl4AAAARxnYXNwAAAAEAAAkvgAAAAIZ2x5Zv2v7C0AAADMAABb/GhlYWQC0dksAABfqAAAADZoaGVhCEMEFgAAZVwAAAAkaG10eN2yH1kAAF/gAAAFfGxvY2GKxKMcAABc6AAAAsBtYXhwAa4AzAAAXMgAAAAgbmFtZUarZSoAAGcEAAAlEHBvc3QANIw5AACMFAAABuNwcmVwaAaMhQAAZvwAAAAHAAIAFv/5AHwDhQAKABMAADcyFhUGBwYiJicmEwYQByM0NxI1PyoTCyUGDhUFC1sGD0MIDkMQCSgIAQgKGQNhGv2rLWebAS1pAAIANgHqANcC+wALABcAABM3JzQ3FxUXDgEjIic3JzQ3FxUXDgEjIpIBASQREAMZBSRcAQEkEBEEGAUkAlIcKVMREMciAw1XHSpTERDHIgQNAAACADgAxgKdApgAQwBQAAATNDMyFjM1Ii4BJyY0Nz4BNzYzNTQ2MzIWHQE3NTMXMxQjIiYjFTI2MxUUBw4BBw4BBwYjNSYiDgEeAQYHIyInJicuASQmIgYHBh0BMjc2NTRWKhIlAwLine truncated
|
||||
|
Before Width: | Height: | Size: 164 KiB |
@@ -0,0 +1,38 @@
|
||||
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.
|
||||
|
||||
> [!NOTE]
|
||||
> The watchdog reboot delegation can be enabled with the `reboot-watchdog`
|
||||
> configuration option in `/etc/finit.conf`. By default this is disabled
|
||||
> and the system reboots directly via the SoC using the kernel's `reboot(2)`
|
||||
> syscall. See [Runlevels](config/runlevels.md) for details.
|
||||
|
||||
The delegation is performed at the very last steps of system shutdown,
|
||||
if reboot has been selected, `reboot-watchdog` is enabled, 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.
|
||||
@@ -0,0 +1,7 @@
|
||||
.deps/*
|
||||
.libs/*
|
||||
.dirstamp
|
||||
*.lo
|
||||
libsystemd.*
|
||||
Makefile
|
||||
Makefile.in
|
||||
@@ -0,0 +1,14 @@
|
||||
# libsystemd replacement library
|
||||
lib_LTLIBRARIES = libsystemd.la
|
||||
libsystemd_la_SOURCES = sd-daemon.c sd-daemon.h
|
||||
libsystemd_la_LDFLAGS = -version-info 0:0:0
|
||||
libsystemd_la_CFLAGS = $(lite_CFLAGS)
|
||||
libsystemd_la_LIBADD = $(lite_LIBS)
|
||||
|
||||
# pkg-config support
|
||||
pkgconfigdir = $(libdir)/pkgconfig
|
||||
pkgconfig_DATA = libsystemd.pc
|
||||
|
||||
# Install header to systemd/ subdirectory
|
||||
systemddir = $(includedir)/systemd
|
||||
systemd_HEADERS = sd-daemon.h
|
||||
@@ -0,0 +1,10 @@
|
||||
prefix=@prefix@
|
||||
exec_prefix=@exec_prefix@
|
||||
libdir=@libdir@
|
||||
includedir=@includedir@
|
||||
|
||||
Name: libsystemd
|
||||
Description: Finit replacement for systemd notification library
|
||||
Version: @PACKAGE_VERSION@
|
||||
Libs: -L${libdir} -lsystemd
|
||||
Cflags: -I${includedir}
|
||||
@@ -0,0 +1,221 @@
|
||||
/* SPDX-License-Identifier: MIT-0 */
|
||||
|
||||
/*
|
||||
* systemd notify protocol, supporting readiness notification on startup
|
||||
* and reloading, according to the protocol defined at:
|
||||
* https://www.freedesktop.org/software/systemd/man/latest/sd_notify.html
|
||||
*
|
||||
* This protocol is guaranteed to be stable as per:
|
||||
* https://systemd.io/PORTABILITY_AND_STABILITY/
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE 1
|
||||
#include <errno.h>
|
||||
#include <inttypes.h>
|
||||
#include <signal.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdarg.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#ifdef _LIBITE_LITE
|
||||
# include <libite/lite.h>
|
||||
#else
|
||||
# include <lite/lite.h>
|
||||
#endif
|
||||
|
||||
#include "sd-daemon.h"
|
||||
|
||||
/*
|
||||
* NOTE: As per spec., this function does not return POSIX OK(0) but
|
||||
* rather "a positive value", i.e., 1.
|
||||
*/
|
||||
int sd_notify(int unset_environment, const char *state)
|
||||
{
|
||||
struct sockaddr_un sun = {
|
||||
.sun_family = AF_UNIX,
|
||||
};
|
||||
size_t len, sun_len;
|
||||
const char *path;
|
||||
ssize_t written;
|
||||
int sd;
|
||||
|
||||
if (!state)
|
||||
return -EINVAL;
|
||||
|
||||
len = strlen(state);
|
||||
if (len == 0)
|
||||
return -EINVAL;
|
||||
|
||||
/* If the variable is not set, the protocol is a noop */
|
||||
path = getenv("NOTIFY_SOCKET");
|
||||
if (!path)
|
||||
return 0; /* Not set? Nothing to do */
|
||||
|
||||
/* Only AF_UNIX is supported, with path or abstract sockets */
|
||||
if (path[0] != '/' && path[0] != '@')
|
||||
return -EAFNOSUPPORT;
|
||||
|
||||
/* Ensure there is room for NUL byte */
|
||||
sun_len = strlen(path);
|
||||
if (sun_len >= sizeof(sun.sun_path))
|
||||
return -E2BIG;
|
||||
|
||||
strlcpy(sun.sun_path, path, sizeof(sun.sun_path));
|
||||
if (sun.sun_path[0] == '@')
|
||||
sun.sun_path[0] = 0;
|
||||
|
||||
sd = socket(AF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC, 0);
|
||||
if (sd == -1)
|
||||
return -errno;
|
||||
|
||||
if (connect(sd, (struct sockaddr *)&sun, offsetof(struct sockaddr_un, sun_path) + sun_len) == -1) {
|
||||
close(sd);
|
||||
return -errno;
|
||||
}
|
||||
|
||||
if (unset_environment)
|
||||
unsetenv("NOTIFY_SOCKET");
|
||||
|
||||
written = write(sd, state, len);
|
||||
close(sd);
|
||||
if (written != (ssize_t) len)
|
||||
return written < 0 ? -errno : -EPROTO;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Printf-style notification function
|
||||
*/
|
||||
int sd_notifyf(int unset_environment, const char *format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
char *state;
|
||||
int ret;
|
||||
|
||||
if (!format)
|
||||
return -EINVAL;
|
||||
|
||||
va_start(ap, format);
|
||||
ret = vasprintf(&state, format, ap);
|
||||
va_end(ap);
|
||||
|
||||
if (ret < 0)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = sd_notify(unset_environment, state);
|
||||
free(state);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* PID-specific notification function
|
||||
*/
|
||||
int sd_pid_notify(pid_t pid, int unset_environment, const char *state)
|
||||
{
|
||||
char path[256], *env;
|
||||
size_t len;
|
||||
int ret;
|
||||
|
||||
if (!state)
|
||||
return -EINVAL;
|
||||
|
||||
len = strlen(state);
|
||||
if (len == 0)
|
||||
return -EINVAL;
|
||||
|
||||
if (pid == 0)
|
||||
pid = getpid();
|
||||
|
||||
env = getenv("NOTIFY_SOCKET");
|
||||
if (env) {
|
||||
env = strdup(env);
|
||||
if (!env)
|
||||
return -errno;
|
||||
}
|
||||
|
||||
snprintf(path, sizeof(path), "@run/finit/notify/%d", pid);
|
||||
setenv("NOTIFY_SOCKET", path, 1);
|
||||
|
||||
ret = sd_notify(unset_environment, state);
|
||||
|
||||
if (env) {
|
||||
setenv("NOTIFY_SOCKET", env, 1);
|
||||
free(env);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* PID-specific printf-style notification function
|
||||
*/
|
||||
int sd_pid_notifyf(pid_t pid, int unset_environment, const char *format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
char *state;
|
||||
int ret;
|
||||
|
||||
if (!format)
|
||||
return -EINVAL;
|
||||
|
||||
va_start(ap, format);
|
||||
ret = vasprintf(&state, format, ap);
|
||||
va_end(ap);
|
||||
|
||||
if (ret < 0)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = sd_pid_notify(pid, unset_environment, state);
|
||||
free(state);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Socket activation stub - Finit doesn't support socket activation yet
|
||||
* Returns 0 (no file descriptors passed)
|
||||
*/
|
||||
int sd_listen_fds(int unset_environment)
|
||||
{
|
||||
if (unset_environment) {
|
||||
unsetenv("LISTEN_PID");
|
||||
unsetenv("LISTEN_FDS");
|
||||
unsetenv("LISTEN_FDNAMES");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Watchdog stub - Finit doesn't support watchdog yet
|
||||
* Returns 0 (no watchdog enabled)
|
||||
*/
|
||||
int sd_watchdog_enabled(int unset_environment, uint64_t *usec)
|
||||
{
|
||||
if (unset_environment) {
|
||||
unsetenv("WATCHDOG_PID");
|
||||
unsetenv("WATCHDOG_USEC");
|
||||
}
|
||||
|
||||
if (usec)
|
||||
*usec = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* System detection function
|
||||
* Returns 1 to indicate systemd compatibility (trick applications)
|
||||
*/
|
||||
int sd_booted(void)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
#ifndef SD_DAEMON_H_
|
||||
#define SD_DAEMON_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#define SD_LISTEN_FDS_START 3
|
||||
|
||||
/* systemd logging defines for stderr parsing by Finit */
|
||||
#define SD_EMERG "<0>" /* system is unusable */
|
||||
#define SD_ALERT "<1>" /* action must be taken immediately */
|
||||
#define SD_CRIT "<2>" /* critical conditions */
|
||||
#define SD_ERR "<3>" /* error conditions */
|
||||
#define SD_WARNING "<4>" /* warning conditions */
|
||||
#define SD_NOTICE "<5>" /* normal but significant condition */
|
||||
#define SD_INFO "<6>" /* informational */
|
||||
#define SD_DEBUG "<7>" /* debug-level messages */
|
||||
|
||||
/* Basic notification function */
|
||||
int sd_notify(int unset_environment, const char *state);
|
||||
|
||||
/* Printf-style notification functions */
|
||||
int sd_notifyf(int unset_environment, const char *format, ...);
|
||||
|
||||
/* PID-specific notification functions */
|
||||
int sd_pid_notify(pid_t pid, int unset_environment, const char *state);
|
||||
int sd_pid_notifyf(pid_t pid, int unset_environment, const char *format, ...);
|
||||
|
||||
/* Socket activation stubs */
|
||||
int sd_listen_fds(int unset_environment);
|
||||
|
||||
/* Watchdog stub */
|
||||
int sd_watchdog_enabled(int unset_environment, uint64_t *usec);
|
||||
|
||||
/* System detection */
|
||||
int sd_booted(void);
|
||||
|
||||
#endif /* SD_DAEMON_H_ */
|
||||
+70
-13
@@ -2,7 +2,7 @@
|
||||
.\" First parameter, NAME, should be all caps
|
||||
.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection
|
||||
.\" 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.
|
||||
.Dt FINIT 8 SMM
|
||||
.Os Linux
|
||||
@@ -10,30 +10,66 @@
|
||||
.Nm finit
|
||||
.Nd Fast init for Linux systems
|
||||
.Sh SYNOPSIS
|
||||
.Nm /sbin/finit
|
||||
.Op --
|
||||
.Nm /sbin/finit --
|
||||
.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 rescue | recover
|
||||
.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
|
||||
.Op Fl hv
|
||||
.Op q | Q | 0-9
|
||||
.Op q | Q | s | S | 0-9
|
||||
.Sh DESCRIPTION
|
||||
Fast init for Linux systems. Reverse engineered from the EeePC
|
||||
fastinit, 10+ years ago by Claudio Matsuoka, "gaps filled with frog
|
||||
DNA ...". Focus is on small and embedded systems, although Finit is
|
||||
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
|
||||
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
|
||||
.It
|
||||
Runlevels, defined per service
|
||||
@@ -93,6 +129,27 @@ Enable kernel debug. Debug messages are printed to the console until
|
||||
Finit starts up, unless
|
||||
.Cm loglevel=7
|
||||
(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]]
|
||||
set
|
||||
.Cm <boot/foo>
|
||||
|
||||
+167
-38
@@ -2,7 +2,7 @@
|
||||
.\" First parameter, NAME, should be all caps
|
||||
.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection
|
||||
.\" other parameters are allowed: see man(7), man(1)
|
||||
.Dd July 11, 2023
|
||||
.Dd July 10, 2025
|
||||
.Dt FINIT.CONF 5 SMM
|
||||
.Os Linux
|
||||
.Sh NAME
|
||||
@@ -175,13 +175,13 @@ task [s] echo "foo" | cat >/tmp/bar
|
||||
.Ed
|
||||
.It Cm sysv Oo LVLS Oc Ao COND Ac Ar /path/to/script ARGS Op -- Optional description
|
||||
Similar to
|
||||
.Cm task
|
||||
.Cm service
|
||||
is the
|
||||
.Cm sysv
|
||||
stanza, which can be used to call SysV style start/stop scripts. The
|
||||
primary intention for this command is to be able to re-use much of
|
||||
existing setup and init scripts in Linux distributions.
|
||||
.Pp
|
||||
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
|
||||
SysV init scripts in Linux distributions.
|
||||
.Pp
|
||||
When entering an allowed runlevel, Finit calls
|
||||
.Cm init-script start ,
|
||||
when entering a disallowed runlevel, Finit calls
|
||||
@@ -194,7 +194,7 @@ on
|
||||
.Cm initctl reload .
|
||||
Similar to how
|
||||
.Cm service
|
||||
stanzas work.
|
||||
directives work.
|
||||
.Pp
|
||||
Forking services started with
|
||||
.Cm sysv
|
||||
@@ -416,7 +416,30 @@ The post:script is called with the same environment variables
|
||||
for the
|
||||
.Cm EXIT_CODE
|
||||
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
|
||||
.Pp
|
||||
When stopping a service (run/task/sysv/service), either manually or when
|
||||
@@ -434,30 +457,42 @@ e.g.,
|
||||
.Cm kill:10
|
||||
to wait 10 seconds before sending SIGKILL.
|
||||
.Pp
|
||||
Services support the
|
||||
.Cm pre:script
|
||||
and
|
||||
.Cm post:script
|
||||
command actions as well. These run as the same
|
||||
Services, including the
|
||||
.Cm sysv
|
||||
variant, support pre/post/ready and cleanup scripts:
|
||||
.Bl -tag -width 1n
|
||||
.It Cm pre:[0-3600,]script
|
||||
called before the sysv/service is stated
|
||||
.It Cm post:[0-3600,]script
|
||||
called after the sysv/service has stopped
|
||||
.It Cm ready:[0-3600,]script
|
||||
called when the sysv/service is ready
|
||||
.It Cm cleanup:[0-3600,]script
|
||||
called when run/task/sysv/service is removed
|
||||
.El
|
||||
.Pp
|
||||
The optional number (0-3600) is the timeout before Finit kills the
|
||||
script, it defaults to the kill delay value and can be disabled by
|
||||
setting it to zero. These scripts run as the same
|
||||
.Cm @USER:GROUP
|
||||
as the service itself, with any
|
||||
.Cm env:file
|
||||
sourced. The scripts must use an absolute path, but are executed from
|
||||
the
|
||||
.Cm $HOME
|
||||
of the given user. The scripts are not called with any argument
|
||||
(currently), but both get the
|
||||
.Cm SERVICE_IDENT=foo
|
||||
environment variable set. Here
|
||||
.Cm foo
|
||||
denotes the identity of the service, which if there are multiple
|
||||
services named
|
||||
.Cm foo ,
|
||||
may be
|
||||
.Cm foo:1 ,
|
||||
or any unique identifier specified in the .conf file. The
|
||||
of the given user. The scripts are not called with any argument, but
|
||||
both get a set of environment variables:
|
||||
.Pp
|
||||
.Bl -tag -width 1n -compact
|
||||
.It Cm SERVICE_IDENT=foo:1
|
||||
.It Cm SERVICE_NAME=foo
|
||||
.It Cm SERVICE_ID=1
|
||||
.El
|
||||
.Pp
|
||||
The
|
||||
.Cm post:script
|
||||
is called with an additional set of environment variables:
|
||||
is called with an additional set of environment variables, and yes the
|
||||
naming looks like it should be swapped:
|
||||
.Bl -tag -offset indent -width 1n
|
||||
.It Cm EXIT_CODE=[exited,signal,crashed]
|
||||
set to one of
|
||||
@@ -471,10 +506,12 @@ set to one of exit status code from the program, if it exited normally,
|
||||
or the signal name (HUP, TERM, etc.) if it exited due to signal
|
||||
.El
|
||||
.Pp
|
||||
The scripts have a default execution time of 3 seconds before they are
|
||||
SIGKILLed, this can be adjusted using the
|
||||
.Cm kill:SEC
|
||||
modifier syntax.
|
||||
When a run/task/sys/service is removed (disable + reload) it is first
|
||||
stopped and then removed from the runlevel. The
|
||||
.Cm post:script
|
||||
always runs when the process has stopped, and the
|
||||
.Cm cleanup:script
|
||||
runs when the the stanza has been removed from the runlevel.
|
||||
.It Cm runparts Aq DIR
|
||||
Call
|
||||
.Xr run-parts 8
|
||||
@@ -521,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
|
||||
This form of the
|
||||
.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 ,
|
||||
in the given runlevels.
|
||||
.Ar DEV may be the special keyword
|
||||
@@ -531,8 +568,8 @@ useful on embedded systems.
|
||||
.Pp
|
||||
The default baud rate is 0, i.e., keep kernel default.
|
||||
.Pp
|
||||
The `tty` stanza inherits runlevel, condition (and other feature)
|
||||
parsing from the `service` stanza. So TTYs can run in one or many
|
||||
The `tty` directive inherits runlevel, condition (and other feature)
|
||||
parsing from the `service` directive. 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.
|
||||
.Bd -unfilled -offset indent
|
||||
@@ -541,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
|
||||
This form of the
|
||||
.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
|
||||
By default, these first two syntax variants
|
||||
.Em clear
|
||||
@@ -611,7 +648,7 @@ board bringup and system debugging it can come in handy.
|
||||
.Pp
|
||||
One can also use the
|
||||
.Cm service
|
||||
stanza to start a stand-alone shell:
|
||||
directive to start a stand-alone shell:
|
||||
.Bd -unfilled -offset indent
|
||||
service [12345] /bin/sh -l
|
||||
.Ed
|
||||
@@ -636,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.
|
||||
.El
|
||||
.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.
|
||||
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
|
||||
.It Cm @user:group
|
||||
Every
|
||||
@@ -932,9 +969,10 @@ or
|
||||
service [...] <...> cgroup.maint /path/to/foo args -- description
|
||||
.Ed
|
||||
.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
|
||||
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
|
||||
.Pp
|
||||
Notice the comma separation and the
|
||||
@@ -954,6 +992,97 @@ available in your Linux kernel, or the name is misspelled.
|
||||
Linux cgroups and details surrounding values are not explained in the
|
||||
Finit documentation. The Linux admin-guide cover this well:
|
||||
.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
|
||||
As of Finit v4 there are no limitations to where
|
||||
.Cm .conf
|
||||
|
||||
+47
-44
@@ -2,7 +2,7 @@
|
||||
.\" First parameter, NAME, should be all caps
|
||||
.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection
|
||||
.\" 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.
|
||||
.Dt INITCTL 8 SMM
|
||||
.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:
|
||||
.Bl -tag -width Ds
|
||||
.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
|
||||
Create missing paths (and files) as needed. Useful with the
|
||||
.Cm edit
|
||||
command.
|
||||
command
|
||||
.It Fl f, -force
|
||||
Ignore missing files and arguments, never prompt.
|
||||
Ignore missing files and arguments, never prompt
|
||||
.It Fl h, -help
|
||||
Show built-in help text.
|
||||
Show built-in help text
|
||||
.It Fl j, -json
|
||||
JSON output in
|
||||
.Ar status
|
||||
and
|
||||
.Ar cond
|
||||
commands.
|
||||
commands
|
||||
.It Fl n, -noerr
|
||||
When scripting
|
||||
.Nm
|
||||
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
|
||||
(OK).
|
||||
(OK)
|
||||
.It Fl 1, -once
|
||||
Only one lap in commands like top.
|
||||
Only one lap in commands like top
|
||||
.It Fl p, -plain
|
||||
Use plain table headings, no ANSI control characters.
|
||||
Use plain table headings, no ANSI control characters
|
||||
.It Fl q, -quiet
|
||||
Silent, only return status of command.
|
||||
Silent, only return status of command
|
||||
.It Fl t, -no-heading
|
||||
Skip table headings.
|
||||
Skip table headings
|
||||
.It Fl v, -verbose
|
||||
Verbose output, where applicable.
|
||||
Verbose output, where applicable
|
||||
.It Fl V, -version
|
||||
Show program version.
|
||||
Show program version
|
||||
.El
|
||||
.Sh COMMANDS
|
||||
.Bl -tag -width Ds
|
||||
@@ -66,9 +66,9 @@ Toggle
|
||||
(daemon) debug to
|
||||
.Pa /dev/console
|
||||
.It Nm Ar help
|
||||
Show built-in help text.
|
||||
Show built-in help text
|
||||
.It Nm Ar version
|
||||
Show program version.
|
||||
Show program version
|
||||
.It Nm Ar ls | list
|
||||
List all
|
||||
.Cm *.conf
|
||||
@@ -112,9 +112,10 @@ like
|
||||
.Ar edit
|
||||
this tells
|
||||
.Nm finit
|
||||
that a configuration has been changed and is a candidate to be restarted
|
||||
(or SIGHUP'ed) on
|
||||
that a configuration has been changed and is a candidate to be reloaded
|
||||
(SIGHUP'ed or restarted) on
|
||||
.Cm initctl reload
|
||||
in dependency order
|
||||
.It Nm Ar enable Ar CONF
|
||||
Enable
|
||||
.Cm .conf
|
||||
@@ -127,12 +128,12 @@ Disable
|
||||
.Cm .conf
|
||||
in
|
||||
.Pa /etc/finit.d/enabled ,
|
||||
i.e., removes symlink.
|
||||
i.e., removes symlink
|
||||
.It Nm Ar reload
|
||||
Reload
|
||||
Reload all (touched)
|
||||
.Cm *.conf in
|
||||
.Pa /etc/finit.d ,
|
||||
i.e., activates changes.
|
||||
.Pa /etc/finit.d
|
||||
and activate changes
|
||||
.It Nm Ar cond set Ar COND Op COND ...
|
||||
Set (assert) user-defined condition,
|
||||
.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
|
||||
verbose output, use the
|
||||
.Fl v
|
||||
option.
|
||||
option
|
||||
.It Nm Ar cond clr | clear Ar COND Op COND ...
|
||||
Clear (deassert) user-defined condition,
|
||||
.Cm -usr/COND
|
||||
@@ -157,28 +158,28 @@ Show condition status, default
|
||||
.Cm cond
|
||||
command. Also supports the
|
||||
.Fl j
|
||||
option for detailed JSON output.
|
||||
option for detailed JSON output
|
||||
.It Nm Ar cond dump Op Cm TYPE
|
||||
Dump all, or a given type of, conditions and their status. Also
|
||||
supports the
|
||||
.Fl j
|
||||
option for detailed JSON output.
|
||||
option for detailed JSON output
|
||||
.It Nm Ar ident Op Cm NAME
|
||||
Display indentities of all run/task/services, or only instances
|
||||
matching
|
||||
.Cm NAME .
|
||||
A partial string, e.g.,
|
||||
.Cm NAM ,
|
||||
will not match anything.
|
||||
will not match anything
|
||||
.It Nm Ar log Op Cm NAME
|
||||
Show ten last Finit, or
|
||||
.Cm NAME ,
|
||||
messages from syslog.
|
||||
messages from syslog
|
||||
.It Nm Ar start Cm NAME[:ID]
|
||||
Start service by name, with optional ID, e.g.,
|
||||
.Cm initctl start tty:1
|
||||
.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]
|
||||
Reload service as if its configuration had changed. Internally,
|
||||
.Nm finit
|
||||
@@ -193,17 +194,19 @@ it is the same as calling
|
||||
Except for two things:
|
||||
.Bl -enum -offset indent -compact
|
||||
.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 allows restarting run/task in the same runlevel -- which is otherwise
|
||||
restricted.
|
||||
restricted
|
||||
.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.
|
||||
.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]
|
||||
Restart (stop/start) service by name.
|
||||
Restart (stop/start) service by name
|
||||
.It Nm Ar status Cm NAME[:ID]
|
||||
Show service status, by name. If only
|
||||
.Cm NAME
|
||||
@@ -225,48 +228,48 @@ option for detailed JSON output suitable for machine parsing.
|
||||
.Pp
|
||||
.Sy Tip:
|
||||
.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
|
||||
Show status of all services, default command. Also supports the
|
||||
.Fl j
|
||||
option for detailed JSON output.
|
||||
option for detailed JSON output
|
||||
.It Nm Ar cgroup
|
||||
List cgroup config overview.
|
||||
List cgroup config overview
|
||||
.It Nm Ar ps
|
||||
List processes based on cgroups.
|
||||
List processes based on cgroups
|
||||
.It Nm Ar top
|
||||
Show top-like listing based on cgroups.
|
||||
Show top-like listing based on cgroups
|
||||
.It Nm Ar plugins
|
||||
List installed plugins.
|
||||
List installed plugins
|
||||
.It Nm Ar runlevel Op Ar 0-9
|
||||
Show or set runlevel: 0 halt, 6 reboot.
|
||||
.Pp
|
||||
If called at boot (runlevel S) to set the runlevel, Finit only schedules
|
||||
the change, effectively overriding the configured runlevel from
|
||||
.Pa /etc/finit.conf .
|
||||
Useful to trigger a fail-safe mode, or similar.
|
||||
Useful to trigger a fail-safe mode, or similar
|
||||
.It Nm Ar reboot
|
||||
Reboot system, default if
|
||||
.Cm reboot
|
||||
is symlinked to
|
||||
.Nm .
|
||||
.Nm
|
||||
.It Nm Ar halt
|
||||
Halt system, default if
|
||||
.Cm halt
|
||||
is symlinked to
|
||||
.Nm .
|
||||
.Nm
|
||||
.It Nm Ar poweroff
|
||||
Power-off system, default if
|
||||
.Cm poweroff
|
||||
is symlinked to
|
||||
.Nm .
|
||||
.Nm
|
||||
.It Nm Ar suspend
|
||||
Suspend system, default if
|
||||
.Cm suspend
|
||||
is symlinked to
|
||||
.Nm .
|
||||
.Nm
|
||||
.It Nm Ar utmp show
|
||||
Raw dump of UTMP/WTMP db.
|
||||
Raw dump of UTMP/WTMP db
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr finit.conf 5
|
||||
|
||||
+114
@@ -0,0 +1,114 @@
|
||||
site_name: Documentation
|
||||
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/
|
||||
extra_css:
|
||||
- extra.css
|
||||
|
||||
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
|
||||
*
|
||||
* 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
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -27,9 +27,11 @@
|
||||
# include <lite/lite.h>
|
||||
#endif
|
||||
|
||||
#include "conf.h"
|
||||
#include "finit.h"
|
||||
#include "helpers.h"
|
||||
#include "plugin.h"
|
||||
#include "log.h"
|
||||
|
||||
#define ALSACTL "alsactl"
|
||||
|
||||
@@ -65,12 +67,12 @@ static plugin_t plugin = {
|
||||
.hook[HOOK_SHUTDOWN] = { .cb = save }
|
||||
};
|
||||
|
||||
PLUGIN_INIT(plugin_init)
|
||||
PLUGIN_INIT(__init)
|
||||
{
|
||||
plugin_register(&plugin);
|
||||
}
|
||||
|
||||
PLUGIN_EXIT(plugin_exit)
|
||||
PLUGIN_EXIT(__exit)
|
||||
{
|
||||
plugin_unregister(&plugin);
|
||||
}
|
||||
|
||||
+5
-5
@@ -1,6 +1,6 @@
|
||||
/* 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
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -38,9 +38,9 @@
|
||||
#include "finit.h"
|
||||
#include "helpers.h"
|
||||
#include "plugin.h"
|
||||
#include "tmpfiles.h"
|
||||
#include "util.h"
|
||||
#include "utmp-api.h"
|
||||
#include "log.h"
|
||||
|
||||
static int is_tmpfs(char *path)
|
||||
{
|
||||
@@ -163,7 +163,7 @@ static void setup(void *arg)
|
||||
kernel_links();
|
||||
|
||||
/* Create all system tmpfiles.d(5) */
|
||||
tmpfilesd();
|
||||
run_interactive(_PATH_TMPFILES " --create", "Creating required directories and files");
|
||||
|
||||
/* Set BOOT_TIME UTMP entry */
|
||||
utmp_set_boot();
|
||||
@@ -178,12 +178,12 @@ static plugin_t plugin = {
|
||||
.depends = { "pidfile" },
|
||||
};
|
||||
|
||||
PLUGIN_INIT(plugin_init)
|
||||
PLUGIN_INIT(__init)
|
||||
{
|
||||
plugin_register(&plugin);
|
||||
}
|
||||
|
||||
PLUGIN_EXIT(plugin_exit)
|
||||
PLUGIN_EXIT(__exit)
|
||||
{
|
||||
plugin_unregister(&plugin);
|
||||
}
|
||||
|
||||
+5
-3
@@ -1,6 +1,6 @@
|
||||
/* 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
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -33,7 +33,9 @@
|
||||
#include "helpers.h"
|
||||
#include "plugin.h"
|
||||
#include "service.h"
|
||||
#include "util.h"
|
||||
#include "conf.h"
|
||||
#include "log.h"
|
||||
|
||||
#define DBUS_DAEMON "dbus-daemon"
|
||||
#define DBUS_ARGS "--nofork --system --syslog-only"
|
||||
@@ -166,12 +168,12 @@ static plugin_t plugin = {
|
||||
.hook[HOOK_SVC_PLUGIN] = { .cb = setup },
|
||||
};
|
||||
|
||||
PLUGIN_INIT(plugin_init)
|
||||
PLUGIN_INIT(__init)
|
||||
{
|
||||
plugin_register(&plugin);
|
||||
}
|
||||
|
||||
PLUGIN_EXIT(plugin_exit)
|
||||
PLUGIN_EXIT(__exit)
|
||||
{
|
||||
plugin_unregister(&plugin);
|
||||
}
|
||||
|
||||
@@ -99,12 +99,12 @@ static plugin_t plugin = {
|
||||
*/
|
||||
};
|
||||
|
||||
PLUGIN_INIT(plugin_init)
|
||||
PLUGIN_INIT(__init)
|
||||
{
|
||||
plugin_register(&plugin);
|
||||
}
|
||||
|
||||
PLUGIN_EXIT(plugin_exit)
|
||||
PLUGIN_EXIT(__exit)
|
||||
{
|
||||
plugin_unregister(&plugin);
|
||||
}
|
||||
|
||||
+4
-3
@@ -1,6 +1,6 @@
|
||||
/* 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
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -50,6 +50,7 @@
|
||||
#include "finit.h"
|
||||
#include "util.h"
|
||||
#include "plugin.h"
|
||||
#include "log.h"
|
||||
|
||||
struct module {
|
||||
TAILQ_ENTRY(module) link;
|
||||
@@ -232,12 +233,12 @@ static plugin_t plugin = {
|
||||
.depends = { "bootmisc", }
|
||||
};
|
||||
|
||||
PLUGIN_INIT(plugin_init)
|
||||
PLUGIN_INIT(__init)
|
||||
{
|
||||
plugin_register(&plugin);
|
||||
}
|
||||
|
||||
PLUGIN_EXIT(plugin_exit)
|
||||
PLUGIN_EXIT(__exit)
|
||||
{
|
||||
plugin_unregister(&plugin);
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
*
|
||||
* Please note, the :ID is there for your benefit, it ensures that tasks
|
||||
* in Finit are unique. If you have two tasks with the same name and ID
|
||||
* (or no ID), the last one read replaces any preceeding one!
|
||||
* (or no ID), the last one read replaces any preceding one!
|
||||
*/
|
||||
|
||||
#include <unistd.h>
|
||||
@@ -58,6 +58,7 @@
|
||||
#include "plugin.h"
|
||||
#include "service.h"
|
||||
#include "conf.h"
|
||||
#include "log.h"
|
||||
|
||||
#ifndef MODULES_LOAD_PATH
|
||||
#define MODULES_LOAD_PATH "/etc/modules-load.d"
|
||||
@@ -216,12 +217,12 @@ static plugin_t plugin = {
|
||||
.hook[HOOK_SVC_PLUGIN] = { .cb = load },
|
||||
};
|
||||
|
||||
PLUGIN_INIT(plugin_init)
|
||||
PLUGIN_INIT(__init)
|
||||
{
|
||||
plugin_register(&plugin);
|
||||
}
|
||||
|
||||
PLUGIN_EXIT(plugin_exit)
|
||||
PLUGIN_EXIT(__exit)
|
||||
{
|
||||
plugin_unregister(&plugin);
|
||||
}
|
||||
|
||||
+4
-3
@@ -2,7 +2,7 @@
|
||||
/* Netlink plugin for IFUP/IFDN and GW events
|
||||
*
|
||||
* 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
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
@@ -29,6 +29,7 @@
|
||||
|
||||
#include "finit.h"
|
||||
#include "cond.h"
|
||||
#include "log.h"
|
||||
#include "helpers.h"
|
||||
#include "plugin.h"
|
||||
#include "service.h"
|
||||
@@ -414,7 +415,7 @@ static plugin_t plugin = {
|
||||
},
|
||||
};
|
||||
|
||||
PLUGIN_INIT(plugin_init)
|
||||
PLUGIN_INIT(__init)
|
||||
{
|
||||
struct sockaddr_nl sa;
|
||||
int sd;
|
||||
@@ -447,7 +448,7 @@ PLUGIN_INIT(plugin_init)
|
||||
plugin_register(&plugin);
|
||||
}
|
||||
|
||||
PLUGIN_EXIT(plugin_exit)
|
||||
PLUGIN_EXIT(__exit)
|
||||
{
|
||||
plugin_unregister(&plugin);
|
||||
close(plugin.io.fd);
|
||||
|
||||
+32
-5
@@ -1,7 +1,7 @@
|
||||
/* Simple pidfile event monitor for the Finit condition engine
|
||||
*
|
||||
* 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
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -34,6 +34,7 @@
|
||||
#include "plugin.h"
|
||||
#include "service.h"
|
||||
#include "iwatch.h"
|
||||
#include "log.h"
|
||||
|
||||
static struct iwatch iw_pidfile;
|
||||
|
||||
@@ -52,7 +53,7 @@ static int pidfile_add_path(struct iwatch *iw, char *path)
|
||||
ptr = slash++;
|
||||
slash = strchr(ptr, '/');
|
||||
if (slash) {
|
||||
dbg("Path too deep, skipping.");
|
||||
dbg("Path too deep, skipping %s", path);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@@ -66,6 +67,7 @@ static void pidfile_update_conds(char *dir, char *name, uint32_t mask)
|
||||
char cond[MAX_COND_LEN];
|
||||
char fn[PATH_MAX];
|
||||
svc_t *svc;
|
||||
char *nm;
|
||||
|
||||
paste(fn, sizeof(fn), dir, name);
|
||||
if (fnmatch("*\\.pid", fn, 0) && fnmatch("*/pid", fn, 0))
|
||||
@@ -79,9 +81,33 @@ static void pidfile_update_conds(char *dir, char *name, uint32_t mask)
|
||||
return;
|
||||
}
|
||||
|
||||
dbg("Found svc %s for %s with pid %d", svc_ident(svc, NULL, 0), fn, svc->pid);
|
||||
switch (svc->state) {
|
||||
case SVC_TEARDOWN_STATE:
|
||||
case SVC_CLEANUP_STATE:
|
||||
case SVC_SETUP_STATE:
|
||||
/*
|
||||
* E.g., a setup script for a container may run in lieu
|
||||
* of crun, trying to fetch a container image from the
|
||||
* network. This script may want to advertise its PID
|
||||
* to the system for clean and swift reboots.
|
||||
*/
|
||||
dbg("%s[%d]: ignoring any PID file changes in CLEANUP/TEARDOWN/SETUP",
|
||||
svc_ident(svc, NULL, 0), svc->pid);
|
||||
return;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* Service condistion to set/clear */
|
||||
mkcond(svc, cond, sizeof(cond));
|
||||
|
||||
nm = svc_ident(svc, NULL, 0);
|
||||
dbg("Found svc %s for %s with pid %d", nm, fn, svc->pid);
|
||||
if (svc_is_stopping(svc)) {
|
||||
dbg("Ignoring pidfile death rattles while service %s is %s", nm, svc_status(svc));
|
||||
goto sneaky_zebra;
|
||||
}
|
||||
|
||||
if (mask & (IN_CLOSE_WRITE | IN_ATTRIB | IN_MODIFY | IN_MOVED_TO)) {
|
||||
/*
|
||||
* only mark native services as started, the s6 and
|
||||
@@ -125,6 +151,7 @@ static void pidfile_update_conds(char *dir, char *name, uint32_t mask)
|
||||
if (svc->notify == SVC_NOTIFY_PID || svc->notify == SVC_NOTIFY_NONE)
|
||||
service_ready(svc, 1);
|
||||
} else if (mask & IN_DELETE) {
|
||||
sneaky_zebra:
|
||||
cond_clear(cond);
|
||||
if (svc->notify == SVC_NOTIFY_PID)
|
||||
service_ready(svc, 0);
|
||||
@@ -312,7 +339,7 @@ static plugin_t plugin = {
|
||||
.depends = { "netlink" }, /* bootmisc depends on us */
|
||||
};
|
||||
|
||||
PLUGIN_INIT(plugin_init)
|
||||
PLUGIN_INIT(__init)
|
||||
{
|
||||
int fd;
|
||||
|
||||
@@ -327,7 +354,7 @@ PLUGIN_INIT(plugin_init)
|
||||
plugin_register(&plugin);
|
||||
}
|
||||
|
||||
PLUGIN_EXIT(plugin_exit)
|
||||
PLUGIN_EXIT(__exit)
|
||||
{
|
||||
plugin_unregister(&plugin);
|
||||
iwatch_exit(&iw_pidfile);
|
||||
|
||||
+10
-4
@@ -1,6 +1,6 @@
|
||||
/* 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
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -31,6 +31,12 @@
|
||||
#include "finit.h"
|
||||
#include "helpers.h"
|
||||
#include "plugin.h"
|
||||
#include "conf.h"
|
||||
#include "log.h"
|
||||
|
||||
#ifndef SYSCTL_PATH
|
||||
#define SYSCTL_PATH "/sbin/sysctl"
|
||||
#endif
|
||||
|
||||
static void setup(void *arg)
|
||||
{
|
||||
@@ -54,7 +60,7 @@ static void setup(void *arg)
|
||||
for (i = 0; i < gl.gl_pathc; i++) {
|
||||
char cmd[160];
|
||||
|
||||
snprintf(cmd, sizeof(cmd), "/sbin/sysctl -e -p %s >/dev/null", gl.gl_pathv[i]);
|
||||
snprintf(cmd, sizeof(cmd), "%s -e -p %s >/dev/null", SYSCTL_PATH, gl.gl_pathv[i]);
|
||||
run(cmd, "sysctl");
|
||||
}
|
||||
globfree(&gl);
|
||||
@@ -70,12 +76,12 @@ static plugin_t plugin = {
|
||||
.depends = { "bootmisc", },
|
||||
};
|
||||
|
||||
PLUGIN_INIT(plugin_init)
|
||||
PLUGIN_INIT(__init)
|
||||
{
|
||||
plugin_register(&plugin);
|
||||
}
|
||||
|
||||
PLUGIN_EXIT(plugin_exit)
|
||||
PLUGIN_EXIT(__exit)
|
||||
{
|
||||
plugin_unregister(&plugin);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* 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
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -30,6 +30,7 @@
|
||||
#include "finit.h"
|
||||
#include "helpers.h"
|
||||
#include "plugin.h"
|
||||
#include "log.h"
|
||||
|
||||
/*
|
||||
* No need to clean up files in /etc/resolvconf/run/interface/
|
||||
@@ -57,12 +58,12 @@ static plugin_t plugin = {
|
||||
.depends = { "bootmisc", },
|
||||
};
|
||||
|
||||
PLUGIN_INIT(plugin_init)
|
||||
PLUGIN_INIT(__init)
|
||||
{
|
||||
plugin_register(&plugin);
|
||||
}
|
||||
|
||||
PLUGIN_EXIT(plugin_exit)
|
||||
PLUGIN_EXIT(__exit)
|
||||
{
|
||||
plugin_unregister(&plugin);
|
||||
}
|
||||
|
||||
+192
-63
@@ -1,6 +1,6 @@
|
||||
/* 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
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -35,9 +35,19 @@
|
||||
#include "finit.h"
|
||||
#include "helpers.h"
|
||||
#include "plugin.h"
|
||||
#include "private.h"
|
||||
#include "conf.h"
|
||||
#include "log.h"
|
||||
|
||||
/* Kernel RTC driver validates against this date for sanity check */
|
||||
/*
|
||||
* Kernel RTC driver validates against this date for sanity check. The
|
||||
* on NTP sync the driver can also update the RTC every 11 mins. We use
|
||||
* the same update interval to handle manual time set and file save.
|
||||
*/
|
||||
#define RTC_TIMESTAMP_BEGIN_2000 "2000-01-01 00:00:00"
|
||||
#define RTC_FMT "%Y-%m-%d %H:%M:%S"
|
||||
#define RTC_PERIOD (11 * 60 * 1000)
|
||||
|
||||
#ifdef RTC_TIMESTAMP_CUSTOM
|
||||
static char *rtc_timestamp = RTC_TIMESTAMP_CUSTOM;
|
||||
#else
|
||||
@@ -45,6 +55,10 @@ static char *rtc_timestamp = RTC_TIMESTAMP_BEGIN_2000;
|
||||
#endif
|
||||
static time_t rtc_date_fallback = 946684800LL;
|
||||
|
||||
static char *rtc_file = RTC_FILE;
|
||||
static uev_t rtc_timer;
|
||||
|
||||
|
||||
static void tz_set(char *tz, size_t len)
|
||||
{
|
||||
char *ptr;
|
||||
@@ -68,6 +82,134 @@ static void tz_restore(char *tz)
|
||||
tzset();
|
||||
}
|
||||
|
||||
static int time_set(struct tm *tm)
|
||||
{
|
||||
struct tm fallback = { 0 };
|
||||
struct timeval tv = { 0 };
|
||||
char tz[128];
|
||||
int rc = 0;
|
||||
|
||||
tz_set(tz, sizeof(tz));
|
||||
|
||||
if (!tm) {
|
||||
logit(LOG_NOTICE, "Resetting system clock to kernel default, %s.", rtc_timestamp);
|
||||
tm = &fallback;
|
||||
|
||||
/* Attempt to set RTC to a sane value ... */
|
||||
tv.tv_sec = rtc_date_fallback;
|
||||
if (!gmtime_r(&tv.tv_sec, tm)) {
|
||||
rc = 1;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
tm->tm_isdst = -1; /* Use tzdata to figure it out, please. */
|
||||
tv.tv_sec = mktime(tm);
|
||||
if (tv.tv_sec == (time_t)-1 || tv.tv_sec < rtc_date_fallback) {
|
||||
errno = EINVAL;
|
||||
rc = 2;
|
||||
} else {
|
||||
if (settimeofday(&tv, NULL) == -1)
|
||||
rc = 1;
|
||||
}
|
||||
out:
|
||||
tz_restore(tz);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int time_get(struct tm *tm)
|
||||
{
|
||||
struct timeval tv = { 0 };
|
||||
char tz[128];
|
||||
int rc = 0;
|
||||
|
||||
tz_set(tz, sizeof(tz));
|
||||
|
||||
rc = gettimeofday(&tv, NULL);
|
||||
if (rc < 0 || tv.tv_sec < rtc_date_fallback)
|
||||
rc = 2;
|
||||
else
|
||||
gmtime_r(&tv.tv_sec, tm);
|
||||
|
||||
tz_restore(tz);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void file_save(void *arg)
|
||||
{
|
||||
struct tm tm = { 0 };
|
||||
int rc = 0;
|
||||
FILE *fp;
|
||||
|
||||
if (!rtc_file)
|
||||
return;
|
||||
|
||||
fp = fopen(rtc_file, "w");
|
||||
if (!fp) {
|
||||
logit(LOG_WARNING, "Failed saving system clock to %s, code %d: %s",
|
||||
rtc_file, errno, strerror(errno));
|
||||
return;
|
||||
}
|
||||
|
||||
if ((rc = time_get(&tm))) {
|
||||
logit(LOG_WARNING, "System clock invalid, before %s, not saving", rtc_timestamp);
|
||||
print_desc(NULL, "System clock invalid, skipping");
|
||||
} else {
|
||||
char buf[32] = { 0 };
|
||||
|
||||
print_desc(NULL, "Saving system clock to file");
|
||||
strftime(buf, sizeof(buf), RTC_FMT, &tm);
|
||||
fprintf(fp, "%s\n", buf);
|
||||
}
|
||||
|
||||
print(rc, NULL);
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
static void file_restore(void *arg)
|
||||
{
|
||||
struct tm tm = { 0 };
|
||||
int rc = 0;
|
||||
FILE *fp;
|
||||
char msg[120];
|
||||
|
||||
if (!rtc_file) {
|
||||
snprintf(msg, sizeof(msg), "Resetting system clock to kernel default, %s.", rtc_timestamp);
|
||||
print_desc(NULL, msg);
|
||||
rc = time_set(NULL);
|
||||
print(rc, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
fp = fopen(rtc_file, "r");
|
||||
if (fp) {
|
||||
char buf[32];
|
||||
|
||||
if (fgets(buf, sizeof(buf), fp)) {
|
||||
chomp(buf);
|
||||
strptime(buf, RTC_FMT, &tm);
|
||||
if (!strptime(buf, RTC_FMT, &tm))
|
||||
rc = 1;
|
||||
}
|
||||
fclose(fp);
|
||||
}
|
||||
rc = 1;
|
||||
|
||||
if (rc) {
|
||||
print_desc(NULL, "Failed to restore system clock from restore file");
|
||||
print(2, NULL);
|
||||
snprintf(msg, sizeof(msg), "Resetting system clock to kernel default, %s.", rtc_timestamp);
|
||||
print_desc(NULL, msg);
|
||||
rc = time_set(NULL);
|
||||
print(rc, NULL);
|
||||
} else {
|
||||
print_desc(NULL, "Restoring system clock from restore file");
|
||||
rc = time_set(&tm);
|
||||
print(rc, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static int rtc_open(void)
|
||||
{
|
||||
char *alt[] = {
|
||||
@@ -91,10 +233,8 @@ static int rtc_open(void)
|
||||
|
||||
static void rtc_save(void *arg)
|
||||
{
|
||||
struct timeval tv = { 0 };
|
||||
struct tm tm = { 0 };
|
||||
int fd, rc = 0;
|
||||
char tz[128];
|
||||
|
||||
if (rescue) {
|
||||
dbg("Skipping %s plugin in rescue mode.", __FILE__);
|
||||
@@ -105,38 +245,26 @@ static void rtc_save(void *arg)
|
||||
if (fd < 0)
|
||||
return;
|
||||
|
||||
tz_set(tz, sizeof(tz));
|
||||
rc = gettimeofday(&tv, NULL);
|
||||
if (rc < 0 || tv.tv_sec < rtc_date_fallback) {
|
||||
if ((rc = time_get(&tm))) {
|
||||
print_desc(NULL, "System clock invalid, not saving to RTC");
|
||||
invalid:
|
||||
logit(LOG_ERR, "System clock invalid, before %s, not saving to RTC", rtc_timestamp);
|
||||
} else {
|
||||
print_desc(NULL, "Saving system clock (UTC) to RTC");
|
||||
rc = ioctl(fd, RTC_SET_TIME, &tm);
|
||||
}
|
||||
|
||||
if (rc && errno == EINVAL) {
|
||||
logit(LOG_WARNING, "System clock invalid, before %s, not saving to RTC", rtc_timestamp);
|
||||
rc = 2;
|
||||
goto out;
|
||||
}
|
||||
|
||||
print_desc(NULL, "Saving system time (UTC) to RTC");
|
||||
|
||||
gmtime_r(&tv.tv_sec, &tm);
|
||||
if (ioctl(fd, RTC_SET_TIME, &tm) < 0) {
|
||||
if (EINVAL == errno)
|
||||
goto invalid;
|
||||
rc = 1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
tz_restore(tz);
|
||||
print(rc, NULL);
|
||||
close(fd);
|
||||
}
|
||||
|
||||
static void rtc_restore(void *arg)
|
||||
{
|
||||
struct timeval tv = { 0 };
|
||||
struct tm tm = { 0 };
|
||||
int fd, rc = 0;
|
||||
char tz[128];
|
||||
|
||||
if (rescue) {
|
||||
dbg("Skipping %s plugin in rescue mode.", __FILE__);
|
||||
@@ -145,82 +273,83 @@ static void rtc_restore(void *arg)
|
||||
|
||||
fd = rtc_open();
|
||||
if (fd < 0) {
|
||||
logit(LOG_NOTICE, "System has no RTC (missing driver?), skipping restore.");
|
||||
file_restore(arg);
|
||||
return;
|
||||
}
|
||||
|
||||
tz_set(tz, sizeof(tz));
|
||||
if (ioctl(fd, RTC_RD_TIME, &tm) < 0) {
|
||||
if ((rc = ioctl(fd, RTC_RD_TIME, &tm)) < 0) {
|
||||
char msg[120];
|
||||
|
||||
snprintf(msg, sizeof(msg), "Failed restoring system clock, %s",
|
||||
EINVAL == errno ? "RTC time is too old" :
|
||||
ENOENT == errno ? "RTC has no saved time" : "see log for details");
|
||||
print_desc(NULL, msg);
|
||||
} else {
|
||||
print_desc(NULL, "Restoring system clock (UTC) from RTC");
|
||||
rc = time_set(&tm);
|
||||
}
|
||||
|
||||
invalid:
|
||||
logit(LOG_ERR, "Failed restoring system clock from RTC.");
|
||||
if (rc) {
|
||||
logit(LOG_WARNING, "Failed restoring system clock from RTC.");
|
||||
if (EINVAL == errno)
|
||||
logit(LOG_ERR, "RTC time is too old (before %s)", rtc_timestamp);
|
||||
logit(LOG_WARNING, "RTC time is too old (before %s)", rtc_timestamp);
|
||||
else if (ENOENT == errno)
|
||||
logit(LOG_ERR, "RTC has no previously saved (valid) time.");
|
||||
logit(LOG_WARNING, "RTC has no previously saved (valid) time.");
|
||||
else
|
||||
logit(LOG_ERR, "RTC error code %d: %s", errno, strerror(errno));
|
||||
logit(LOG_WARNING, "RTC error code %d: %s", errno, strerror(errno));
|
||||
|
||||
/* Been here already? */
|
||||
if (rc)
|
||||
goto out;
|
||||
print(2, NULL);
|
||||
|
||||
/* Attempt to set RTC to a sane value ... */
|
||||
tv.tv_sec = rtc_date_fallback;
|
||||
if (!gmtime_r(&tv.tv_sec, &tm))
|
||||
goto out;
|
||||
/* Try restoring from last save game */
|
||||
file_restore(arg);
|
||||
} else
|
||||
print(0, NULL);
|
||||
|
||||
logit(LOG_NOTICE, "Resetting RTC to kernel default, %s.", rtc_timestamp);
|
||||
rc = 2;
|
||||
}
|
||||
|
||||
print_desc(NULL, "Restoring system clock (UTC) from RTC");
|
||||
tm.tm_isdst = -1; /* Use tzdata to figure it out, please. */
|
||||
tv.tv_sec = mktime(&tm);
|
||||
if (tv.tv_sec == (time_t)-1 || tv.tv_sec < rtc_date_fallback) {
|
||||
errno = EINVAL;
|
||||
goto invalid;
|
||||
}
|
||||
|
||||
if (settimeofday(&tv, NULL) == -1)
|
||||
rc = 1;
|
||||
|
||||
out:
|
||||
tz_restore(tz);
|
||||
print(rc, NULL);
|
||||
close(fd);
|
||||
}
|
||||
|
||||
|
||||
static void save(void *arg)
|
||||
{
|
||||
rtc_save(arg);
|
||||
file_save(arg);
|
||||
}
|
||||
|
||||
static void update(uev_t *w, void *arg, int events)
|
||||
{
|
||||
save(arg);
|
||||
}
|
||||
|
||||
|
||||
static plugin_t plugin = {
|
||||
.name = __FILE__,
|
||||
.hook[HOOK_BASEFS_UP] = {
|
||||
.cb = rtc_restore
|
||||
},
|
||||
.hook[HOOK_SHUTDOWN] = {
|
||||
.cb = rtc_save
|
||||
.cb = save
|
||||
}
|
||||
};
|
||||
|
||||
PLUGIN_INIT(plugin_init)
|
||||
PLUGIN_INIT(__init)
|
||||
{
|
||||
struct tm tm = { 0 };
|
||||
|
||||
if (!strptime(rtc_timestamp, "%Y-%m-%d %H:%M", &tm))
|
||||
rtc_date_fallback = mktime(&tm);
|
||||
else
|
||||
if (!strptime(rtc_timestamp, RTC_FMT, &tm)) {
|
||||
logit(LOG_WARNING, "Invalid restore date '%s', reverting to '%s'",
|
||||
rtc_timestamp, RTC_TIMESTAMP_BEGIN_2000);
|
||||
rtc_timestamp = RTC_TIMESTAMP_BEGIN_2000;
|
||||
} else
|
||||
rtc_date_fallback = mktime(&tm);
|
||||
|
||||
uev_timer_init(ctx, &rtc_timer, update, NULL, RTC_PERIOD, RTC_PERIOD);
|
||||
|
||||
plugin_register(&plugin);
|
||||
}
|
||||
|
||||
PLUGIN_EXIT(plugin_exit)
|
||||
PLUGIN_EXIT(__exit)
|
||||
{
|
||||
uev_timer_stop(&rtc_timer);
|
||||
plugin_unregister(&plugin);
|
||||
}
|
||||
|
||||
|
||||
+4
-3
@@ -1,6 +1,6 @@
|
||||
/* 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
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -32,6 +32,7 @@
|
||||
#include "pid.h"
|
||||
#include "plugin.h"
|
||||
#include "iwatch.h"
|
||||
#include "log.h"
|
||||
|
||||
static struct iwatch iw_sys;
|
||||
|
||||
@@ -184,7 +185,7 @@ static plugin_t plugin = {
|
||||
.depends = { "bootmisc", },
|
||||
};
|
||||
|
||||
PLUGIN_INIT(plugin_init)
|
||||
PLUGIN_INIT(__init)
|
||||
{
|
||||
int fd;
|
||||
|
||||
@@ -199,7 +200,7 @@ PLUGIN_INIT(plugin_init)
|
||||
plugin_register(&plugin);
|
||||
}
|
||||
|
||||
PLUGIN_EXIT(plugin_exit)
|
||||
PLUGIN_EXIT(__exit)
|
||||
{
|
||||
plugin_unregister(&plugin);
|
||||
iwatch_exit(&iw_sys);
|
||||
|
||||
+4
-3
@@ -1,7 +1,7 @@
|
||||
/* 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-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
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -38,6 +38,7 @@
|
||||
#include "plugin.h"
|
||||
#include "service.h"
|
||||
#include "tty.h"
|
||||
#include "log.h"
|
||||
|
||||
static void tty_watcher(void *arg, int fd, int events);
|
||||
|
||||
@@ -108,13 +109,13 @@ static void tty_watcher(void *arg, int fd, int events)
|
||||
}
|
||||
}
|
||||
|
||||
PLUGIN_INIT(plugin_init)
|
||||
PLUGIN_INIT(__init)
|
||||
{
|
||||
setup();
|
||||
plugin_register(&plugin);
|
||||
}
|
||||
|
||||
PLUGIN_EXIT(plugin_exit)
|
||||
PLUGIN_EXIT(__exit)
|
||||
{
|
||||
plugin_unregister(&plugin);
|
||||
if (plugin.io.fd)
|
||||
|
||||
+58
-14
@@ -1,6 +1,6 @@
|
||||
/* 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
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -26,6 +26,7 @@
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h> /* gettimeofday() */
|
||||
#include <sys/types.h>
|
||||
#include <sys/resource.h> /* getrusage() */
|
||||
#ifdef _LIBITE_LITE
|
||||
# include <libite/lite.h>
|
||||
#else
|
||||
@@ -37,16 +38,51 @@
|
||||
#include "finit.h"
|
||||
#include "helpers.h"
|
||||
#include "plugin.h"
|
||||
#include "conf.h"
|
||||
#include "log.h"
|
||||
|
||||
#ifndef RANDOM_BYTES
|
||||
#define RANDOM_BYTES (32*1024)
|
||||
#endif
|
||||
|
||||
#ifdef RANDOMSEED
|
||||
/*
|
||||
* This is the fallback seed function, please make sure you have drivers
|
||||
* enabling /dev/hwrng instead.
|
||||
*/
|
||||
static void fallback(FILE *fp)
|
||||
{
|
||||
unsigned long seed;
|
||||
struct timeval tv;
|
||||
struct rusage ru;
|
||||
int iter = 128;
|
||||
|
||||
gettimeofday(&tv, NULL);
|
||||
getrusage(RUSAGE_SELF, &ru);
|
||||
|
||||
/* Mix multiple sources of "randomness" */
|
||||
seed = tv.tv_sec ^ (tv.tv_usec << 16);
|
||||
seed ^= ru.ru_utime.tv_sec ^ (ru.ru_utime.tv_usec << 16);
|
||||
seed ^= ru.ru_stime.tv_sec ^ (ru.ru_stime.tv_usec << 16);
|
||||
seed ^= getpid() << 8;
|
||||
|
||||
srandom(seed);
|
||||
while (iter--) {
|
||||
uint32_t i, prng = random();
|
||||
|
||||
for (i = 0; i < sizeof(prng); i++)
|
||||
fputc((prng >> (i * CHAR_BIT)) & UCHAR_MAX, fp);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static void setup(void *arg)
|
||||
{
|
||||
#ifdef RANDOMSEED
|
||||
struct rand_pool_info *rpi;
|
||||
unsigned char *rpi_buf;
|
||||
ssize_t len = 0;
|
||||
struct stat st;
|
||||
int rc = -1;
|
||||
int fd, err;
|
||||
|
||||
@@ -55,7 +91,7 @@ static void setup(void *arg)
|
||||
return;
|
||||
}
|
||||
|
||||
if (!fexist(RANDOMSEED)) {
|
||||
if (stat(RANDOMSEED, &st) || st.st_size < 512) {
|
||||
int ret = 1;
|
||||
mode_t prev;
|
||||
FILE *fp;
|
||||
@@ -64,16 +100,23 @@ static void setup(void *arg)
|
||||
prev = umask(077);
|
||||
fp = fopen(RANDOMSEED, "w");
|
||||
if (fp) {
|
||||
int iter = 128;
|
||||
struct timeval tv;
|
||||
const char *hwrng = "/dev/hwrng";
|
||||
FILE *hw;
|
||||
|
||||
gettimeofday(&tv, NULL);
|
||||
srandom(tv.tv_sec % 3600);
|
||||
while (iter--) {
|
||||
uint32_t i, prng = random();
|
||||
hw = fopen(hwrng, "r");
|
||||
if (hw) {
|
||||
char buf[512];
|
||||
size_t num;
|
||||
|
||||
for (i = 0; i < sizeof(prng); i++)
|
||||
fputc((prng >> (i * CHAR_BIT)) & UCHAR_MAX, fp);
|
||||
num = fread(buf, sizeof(buf[0]), sizeof(buf), hw);
|
||||
if (num == 0)
|
||||
fallback(fp);
|
||||
else
|
||||
fwrite(buf, sizeof(buf[0]), num, fp);
|
||||
|
||||
fclose(hw);
|
||||
} else {
|
||||
fallback(fp);
|
||||
}
|
||||
ret = fclose(fp);
|
||||
}
|
||||
@@ -98,10 +141,11 @@ static void setup(void *arg)
|
||||
goto fallback;
|
||||
}
|
||||
|
||||
rpi_buf = (unsigned char *)rpi->buf;
|
||||
do {
|
||||
ssize_t num;
|
||||
|
||||
num = read(fd, &rpi->buf[len], RANDOM_BYTES - len);
|
||||
num = read(fd, &rpi_buf[len], RANDOM_BYTES - len);
|
||||
if (num <= 0) {
|
||||
if (num == -1 && errno == EINTR)
|
||||
continue;
|
||||
@@ -130,7 +174,7 @@ static void setup(void *arg)
|
||||
close(fd);
|
||||
free(rpi);
|
||||
if (rc < 0)
|
||||
logit(LOG_ERR, "Failed adding entropy to kernel random pool: %s", strerror(err));
|
||||
logit(LOG_WARNING, "Failed adding entropy to kernel random pool: %s", strerror(err));
|
||||
print_result(rc < 0);
|
||||
return;
|
||||
fallback:
|
||||
@@ -164,12 +208,12 @@ static plugin_t plugin = {
|
||||
.depends = { "bootmisc", }
|
||||
};
|
||||
|
||||
PLUGIN_INIT(plugin_init)
|
||||
PLUGIN_INIT(__init)
|
||||
{
|
||||
plugin_register(&plugin);
|
||||
}
|
||||
|
||||
PLUGIN_EXIT(plugin_exit)
|
||||
PLUGIN_EXIT(__exit)
|
||||
{
|
||||
plugin_unregister(&plugin);
|
||||
}
|
||||
|
||||
+4
-3
@@ -1,6 +1,6 @@
|
||||
/* 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
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -31,6 +31,7 @@
|
||||
#include "pid.h"
|
||||
#include "plugin.h"
|
||||
#include "iwatch.h"
|
||||
#include "log.h"
|
||||
|
||||
static struct iwatch iw_usr;
|
||||
|
||||
@@ -108,7 +109,7 @@ static plugin_t plugin = {
|
||||
.depends = { "bootmisc", },
|
||||
};
|
||||
|
||||
PLUGIN_INIT(plugin_init)
|
||||
PLUGIN_INIT(__init)
|
||||
{
|
||||
int fd;
|
||||
|
||||
@@ -123,7 +124,7 @@ PLUGIN_INIT(plugin_init)
|
||||
plugin_register(&plugin);
|
||||
}
|
||||
|
||||
PLUGIN_EXIT(plugin_exit)
|
||||
PLUGIN_EXIT(__exit)
|
||||
{
|
||||
plugin_unregister(&plugin);
|
||||
iwatch_exit(&iw_usr);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* 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
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -33,6 +33,8 @@
|
||||
#include "finit.h"
|
||||
#include "helpers.h"
|
||||
#include "plugin.h"
|
||||
#include "conf.h"
|
||||
#include "log.h"
|
||||
|
||||
static void setup(void *arg)
|
||||
{
|
||||
@@ -50,12 +52,12 @@ static plugin_t plugin = {
|
||||
.hook[HOOK_SVC_PLUGIN] = { .cb = setup },
|
||||
};
|
||||
|
||||
PLUGIN_INIT(plugin_init)
|
||||
PLUGIN_INIT(__init)
|
||||
{
|
||||
plugin_register(&plugin);
|
||||
}
|
||||
|
||||
PLUGIN_EXIT(plugin_exit)
|
||||
PLUGIN_EXIT(__exit)
|
||||
{
|
||||
plugin_unregister(&plugin);
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ logit
|
||||
reboot
|
||||
runparts
|
||||
sulogin
|
||||
tmpfiles
|
||||
watchdogd
|
||||
Makefile
|
||||
Makefile.in
|
||||
+7
-2
@@ -8,7 +8,8 @@ AM_LDFLAGS = -export-dynamic
|
||||
endif
|
||||
|
||||
sbin_PROGRAMS = finit initctl
|
||||
pkglibexec_PROGRAMS = getty logit runparts
|
||||
pkglibexec_PROGRAMS = getty logit runparts tmpfiles
|
||||
|
||||
if SULOGIN
|
||||
pkglibexec_PROGRAMS += sulogin
|
||||
endif
|
||||
@@ -43,6 +44,11 @@ sulogin_SOURCES = sulogin.c
|
||||
sulogin_CFLAGS = -W -Wall -Wextra -std=gnu99
|
||||
sulogin_LDADD = -lcrypt
|
||||
|
||||
tmpfiles_SOURCES = tmpfiles.c util.c util.h log.h
|
||||
tmpfiles_CFLAGS = -W -Wall -Wextra -std=gnu99
|
||||
tmpfiles_CFLAGS += $(lite_CFLAGS) $(uev_CFLAGS)
|
||||
tmpfiles_LDADD = $(lite_LIBS) $(uev_LIBS)
|
||||
|
||||
logit_SOURCES = logit.c logrotate.c
|
||||
logit_CFLAGS = -W -Wall -Wextra -Wno-unused-parameter -std=gnu99
|
||||
logit_CFLAGS += $(lite_CFLAGS)
|
||||
@@ -66,7 +72,6 @@ finit_SOURCES = api.c cgroup.c cgroup.h \
|
||||
sig.c sig.h \
|
||||
sm.c sm.h \
|
||||
svc.c svc.h \
|
||||
tmpfiles.c tmpfiles.h \
|
||||
tty.c tty.h \
|
||||
util.c util.h \
|
||||
utmp-api.c utmp-api.h
|
||||
|
||||
Loaded 100 of 207 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user