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 |
No files matched your search
@@ -8,14 +8,22 @@ on:
|
|||||||
- '**'
|
- '**'
|
||||||
- '!dev'
|
- '!dev'
|
||||||
pull_request:
|
pull_request:
|
||||||
branches:
|
types: [opened, synchronize, reopened, labeled]
|
||||||
- '**'
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: ${{ github.workflow }}-${{ github.head_ref || github.ref }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
# Verify we can build on latest Ubuntu with both gcc and clang
|
# Verify we can build on latest Ubuntu with both gcc and clang
|
||||||
name: ${{ matrix.compiler }}
|
name: ${{ matrix.compiler }}
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
# Skip redundant builds for PRs - prefer PR builds over push builds
|
||||||
|
if: github.event_name != 'push' || github.ref == 'refs/heads/master'
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
compiler: [gcc, clang]
|
compiler: [gcc, clang]
|
||||||
@@ -37,7 +45,8 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
./configure --prefix=/usr --exec-prefix= --sysconfdir=/etc --localstatedir=/var \
|
./configure --prefix=/usr --exec-prefix= --sysconfdir=/etc --localstatedir=/var \
|
||||||
--enable-x11-common-plugin --enable-testserv-plugin --with-watchdog \
|
--enable-x11-common-plugin --enable-testserv-plugin --with-watchdog \
|
||||||
--with-keventd
|
--with-keventd --with-libsystemd \
|
||||||
|
CFLAGS="-fsanitize=address -ggdb"
|
||||||
make -j3 clean
|
make -j3 clean
|
||||||
make -j3 V=1
|
make -j3 V=1
|
||||||
- name: Install to /tmp
|
- name: Install to /tmp
|
||||||
|
|||||||
@@ -6,6 +6,9 @@ on:
|
|||||||
- 'dev'
|
- 'dev'
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
env:
|
env:
|
||||||
PROJECT_NAME: finit
|
PROJECT_NAME: finit
|
||||||
CONTACT_EMAIL: troglobit@gmail.com
|
CONTACT_EMAIL: troglobit@gmail.com
|
||||||
@@ -63,7 +66,8 @@ jobs:
|
|||||||
- name: Configure
|
- name: Configure
|
||||||
run: |
|
run: |
|
||||||
./autogen.sh
|
./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
|
- name: Build
|
||||||
run: |
|
run: |
|
||||||
export PATH=`pwd`/coverity/bin:$PATH
|
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:
|
tags:
|
||||||
- '[0-9]+.[0-9]+*'
|
- '[0-9]+.[0-9]+*'
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
release:
|
release:
|
||||||
name: Build and upload release tarball
|
name: Build and upload release tarball
|
||||||
@@ -36,9 +39,10 @@ jobs:
|
|||||||
- name: Creating Makefiles ...
|
- name: Creating Makefiles ...
|
||||||
run: |
|
run: |
|
||||||
./autogen.sh
|
./autogen.sh
|
||||||
./configure --prefix=/usr --exec-prefix= --sysconfdir=/etc --localstatedir=/var \
|
./configure --prefix=/usr --exec-prefix= --sysconfdir=/etc \
|
||||||
--enable-x11-common-plugin --enable-testserv-plugin --with-watchdog \
|
--localstatedir=/var --enable-x11-common-plugin \
|
||||||
--with-keventd
|
--enable-testserv-plugin --with-watchdog \
|
||||||
|
--with-keventd --with-libsystemd
|
||||||
- name: Enable unprivileged userns (unshare)
|
- name: Enable unprivileged userns (unshare)
|
||||||
run: |
|
run: |
|
||||||
sudo sysctl kernel.apparmor_restrict_unprivileged_userns=0
|
sudo sysctl kernel.apparmor_restrict_unprivileged_userns=0
|
||||||
@@ -50,7 +54,7 @@ jobs:
|
|||||||
mv ../*.tar.* artifacts/
|
mv ../*.tar.* artifacts/
|
||||||
- name: Extract ChangeLog entry ...
|
- name: Extract ChangeLog entry ...
|
||||||
run: |
|
run: |
|
||||||
awk '/-----*/{if (x == 1) exit; x=1;next}x' ChangeLog.md \
|
awk '/-----*/{if (x == 1) exit; x=1;next}x' doc/ChangeLog.md \
|
||||||
|head -n -1 > release.md
|
|head -n -1 > release.md
|
||||||
cat release.md
|
cat release.md
|
||||||
- uses: ncipollo/release-action@v1
|
- uses: ncipollo/release-action@v1
|
||||||
|
|||||||
@@ -7,6 +7,9 @@ on:
|
|||||||
- cron: '0 0 * * 0'
|
- cron: '0 0 * * 0'
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
schedule:
|
schedule:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|||||||
@@ -1,7 +1,15 @@
|
|||||||
# GNU Global .conf file, see /etc/gtags/gtags.conf for details.
|
# GNU Global .conf file, see /etc/gtags/gtags.conf for details.
|
||||||
|
# This configuration is optimized for the Finit project structure.
|
||||||
|
|
||||||
default:\
|
default:\
|
||||||
:tc=default@/etc/gtags/gtags.conf:\
|
:tc=default@/etc/gtags/gtags.conf:\
|
||||||
:tc=common:
|
:tc=common:
|
||||||
|
|
||||||
common:\
|
common:\
|
||||||
:skip=tags,TAGS,ID,y.tab.c,y.tab.h,gtags.files,cscope.files,cscope.out,cscope.po.out,cscope.in.out,,{arch}/,autom4te.cache/,*.orig,*.rej,*.bak,*~,#*#,*.swp,*.tmp,*_flymake.*,*_flymake,*.o,*.a,*.so,*.lo,*.zip,*.gz,*.bz2,*.xz,*.lzh,*.Z,*.tgz,*.min.js,*min.css,sysroot/:
|
:skip=tags,TAGS,ID,y.tab.c,y.tab.h,gtags.files,cscope.files,cscope.out,cscope.po.out,cscope.in.out,\
|
||||||
|
{arch}/,autom4te.cache/,\
|
||||||
|
*.orig,*.rej,*.bak,*~,#*#,*.swp,*.tmp,*_flymake.*,*_flymake,\
|
||||||
|
*.o,*.a,*.so,*.lo,*.la,\
|
||||||
|
*.zip,*.gz,*.bz2,*.xz,*.lzh,*.Z,*.tgz,\
|
||||||
|
*.log,*.trs,test-suite.log,stamp-*,\
|
||||||
|
sysroot/:
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
Copyright (c) 2008-2010 Claudio Matsuoka <cmatsuoka@gmail.com>
|
Copyright (c) 2008-2010 Claudio Matsuoka <cmatsuoka@gmail.com>
|
||||||
Copyright (c) 2008-2024 Joachim Wiberg <troglobit@gmail.com>
|
Copyright (c) 2008-2025 Joachim Wiberg <troglobit@gmail.com>
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|||||||
+14
-8
@@ -1,7 +1,6 @@
|
|||||||
ACLOCAL_AMFLAGS = -I m4
|
ACLOCAL_AMFLAGS = -I m4
|
||||||
SUBDIRS = man plugins src system test tmpfiles.d
|
SUBDIRS = man plugins src system tmpfiles.d
|
||||||
doc_DATA = README.md LICENSE contrib/finit.conf
|
dist_doc_DATA = README.md LICENSE contrib/finit.conf
|
||||||
EXTRA_DIST = README.md LICENSE ChangeLog.md contrib/finit.conf
|
|
||||||
|
|
||||||
if CONTRIB
|
if CONTRIB
|
||||||
SUBDIRS += contrib
|
SUBDIRS += contrib
|
||||||
@@ -9,11 +8,18 @@ endif
|
|||||||
if DOC
|
if DOC
|
||||||
SUBDIRS += doc
|
SUBDIRS += doc
|
||||||
endif
|
endif
|
||||||
|
if LIBSYSTEMD
|
||||||
if BASH
|
SUBDIRS += libsystemd
|
||||||
bashdir = $(BASH_DIR)
|
|
||||||
dist_bash_DATA = initctl
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
if LIBSYSTEMD
|
||||||
|
SUBDIRS += test
|
||||||
|
# Explicit dependency to ensure libsystemd is built before test
|
||||||
|
test: libsystemd
|
||||||
|
else
|
||||||
|
SUBDIRS += test
|
||||||
|
endif
|
||||||
|
|
||||||
# Compat hook
|
# Compat hook
|
||||||
install-dev:
|
install-dev:
|
||||||
@make -C src install-pkgincludeHEADERS
|
@make -C src install-pkgincludeHEADERS
|
||||||
@@ -37,4 +43,4 @@ release: distcheck
|
|||||||
DISTCHECK_CONFIGURE_FLAGS = --prefix=/usr --sysconfdir=/etc --localstatedir=/var \
|
DISTCHECK_CONFIGURE_FLAGS = --prefix=/usr --sysconfdir=/etc --localstatedir=/var \
|
||||||
--enable-testserv-plugin --enable-x11-common-plugin \
|
--enable-testserv-plugin --enable-x11-common-plugin \
|
||||||
--with-watchdog --with-keventd --with-fstab=/etc/fstab \
|
--with-watchdog --with-keventd --with-fstab=/etc/fstab \
|
||||||
--with-bash-completion-dir=no
|
--with-libsystemd --with-bash-completion-dir=no
|
||||||
@@ -1,723 +1,46 @@
|
|||||||
[![License Badge][]][License] [![GitHub Status][]][GitHub] [![Coverity Status][]][Coverity Scan]
|
[![License Badge][]][License] [![GitHub Status][]][GitHub] [![Coverity Status][]][Coverity Scan]
|
||||||
<img align="right" src="img/finit3.png" alt="Finit: Fast Init">
|
<img align="right" src="doc/img/finit3.png" alt="Finit: Fast Init">
|
||||||
|
|
||||||
* [Introduction](#introduction)
|
Finit is an alternative to [SysV init](https://en.wikipedia.org/wiki/Init)
|
||||||
* [Features](#features)
|
and [systemd](https://www.freedesktop.org/wiki/Software/systemd/), focused
|
||||||
* [Runlevels](#runlevels)
|
on small and embedded Linux systems, although fully usable on server and
|
||||||
* [Syntax](doc/config.md#syntax)
|
[desktop systems][finix].
|
||||||
* [Runparts & /etc/rc.local](#runparts--etcrclocal)
|
|
||||||
* [Hooks, Callbacks & Plugins](doc/plugins.md#hooks-callbacks--plugins)
|
|
||||||
* [Rebooting & Halting](#rebooting--halting)
|
|
||||||
* [Commands & Status](#commands--status)
|
|
||||||
* [Tips & Tricks with the kernel cmdline](doc/cmdline.md)
|
|
||||||
* [Building](doc/build.md#building)
|
|
||||||
* [Running](doc/build.md#running)
|
|
||||||
* [Recovery](doc/build.md#recovery)
|
|
||||||
* [Debugging](doc/build.md#debugging)
|
|
||||||
* [Requirements](#requirements)
|
|
||||||
* [Origin & References](#origin--references)
|
|
||||||
|
|
||||||
|
> Reverse engineered from the [EeePC fastinit][]
|
||||||
|
> "gaps filled with frog DNA …"
|
||||||
|
> — [Claudio Matsuoka][]
|
||||||
|
|
||||||
Introduction
|
For detailed information, explore our extensive documentation
|
||||||
------------
|
:books: **<https://troglobit.github.io/finit/>**
|
||||||
|
|
||||||
Fast init for Linux systems. Reverse engineered from the [EeePC
|
<div align="center">
|
||||||
fastinit][] by [Claudio Matsuoka][] — "gaps filled with frog DNA …"
|
<img src="doc/img/alpine-screenshot2.png" alt="Alpine screenshot"><br/>
|
||||||
|
</div>
|
||||||
|
|
||||||

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

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

|
||||||
|
|
||||||
When a reconfiguration is requested, Finit transitions all conditions to
|
When a reconfiguration is requested, Finit transitions all conditions to
|
||||||
the `flux` state. As a result, services that depend on a condition are
|
the `flux` state. As a result, services that depend on a condition are
|
||||||
sent `SIGSTOP`. Once the new state of the condition is asserted, the
|
sent `SIGSTOP`. Once the new state of the condition is asserted, the
|
||||||
|
|||||||
-1459
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
|
||||||
+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 |
File renamed without changes.
File renamed without changes.
@@ -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.
|
||||||
+2
-8
@@ -1,12 +1,6 @@
|
|||||||
Hooks & Plugins
|
Hooks & Plugins
|
||||||
===============
|
===============
|
||||||
|
|
||||||
* [Plugins](#plugins)
|
|
||||||
* [Hooks](#hooks)
|
|
||||||
* [Bootstrap Hooks](#bootstrap-hooks)
|
|
||||||
* [Runtime Hooks](#runtime-hooks)
|
|
||||||
* [Shutdown Hooks](#shutdown-hooks)
|
|
||||||
|
|
||||||
Finit can be extended to add general functionality in the form of I/O
|
Finit can be extended to add general functionality in the form of I/O
|
||||||
monitors, or hook plugins. It is even possible to run scripts at these
|
monitors, or hook plugins. It is even possible to run scripts at these
|
||||||
hook points, see below.
|
hook points, see below.
|
||||||
@@ -65,7 +59,7 @@ For your convenience a set of *optional* plugins are available:
|
|||||||
Enabled by default.
|
Enabled by default.
|
||||||
|
|
||||||
> [!TIP]
|
> [!TIP]
|
||||||
> See the [Services](config.md#services) section in the configuration
|
> See the [Services](config/services.md) section in the configuration
|
||||||
> guide for an example how to run `mdevd`, alternative to plain mdev.
|
> guide for an example how to run `mdevd`, alternative to plain mdev.
|
||||||
|
|
||||||
* *rtc.so*: Restore and save system clock from/to RTC on boot/halt.
|
* *rtc.so*: Restore and save system clock from/to RTC on boot/halt.
|
||||||
@@ -135,7 +129,7 @@ the second is the condition name and hook script path. A hook script is
|
|||||||
a plain shell script, or program, that does a very small dedicated job
|
a plain shell script, or program, that does a very small dedicated job
|
||||||
at the below hook points.
|
at the below hook points.
|
||||||
|
|
||||||
See [Run-parts Scripts](config.md#run-parts-scripts) for details on the
|
See [Run-parts Scripts](config/runparts.md) for details on the
|
||||||
requirements, possibilities, and *limitations* of hook scripts.
|
requirements, possibilities, and *limitations* of hook scripts.
|
||||||
|
|
||||||
All hook scripts are called with at least one environment variable set,
|
All hook scripts are called with at least one environment variable set,
|
||||||
|
|||||||
@@ -0,0 +1,25 @@
|
|||||||
|
Requirements
|
||||||
|
============
|
||||||
|
|
||||||
|
Finit is capable of running on both desktop/server systems with udev and
|
||||||
|
embedded systems that usually come with BusyBox mdev. Some systems have
|
||||||
|
systemd-udev or eudev today instead of the original udev, Finit probes
|
||||||
|
for all of them at runtime and expects `/dev/` to be a writable file
|
||||||
|
system using `devtmpfs`. It is also possible to run on a statically set
|
||||||
|
up `/dev` if needed. It is however not a good idea to have both udev
|
||||||
|
and mdev installed at the same time, this will lead to unpredictable
|
||||||
|
results.
|
||||||
|
|
||||||
|
At boot Finit calls either `mdev` or `udevd` to populate `/dev`, this is
|
||||||
|
done slightly differently and on systems with udev you might want to add
|
||||||
|
the following one-shot task early in your `/etc/finit.conf`:
|
||||||
|
|
||||||
|
```conf
|
||||||
|
run [S] udevadm settle --timeout=120 -- Waiting for udev
|
||||||
|
```
|
||||||
|
|
||||||
|
Finit has a built-in Getty for TTYs, but requires a working `/bin/login`
|
||||||
|
or `/bin/sh`, if no TTYs are configured in `/etc/finit.conf`.
|
||||||
|
|
||||||
|
For a fully operational system `/var`, `/run` and `/tmp` must be set up
|
||||||
|
properly in `/etc/fstab` -- which is iterated over at boot.
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
Runlevel Support
|
||||||
|
================
|
||||||
|
|
||||||
|
Basic support for [runlevels][5] is included in Finit from v1.8. By
|
||||||
|
default all services, tasks, run commands and TTYs listed without a set
|
||||||
|
of runlevels get a default set `[234]` assigned. The default runlevel
|
||||||
|
after boot is 2.
|
||||||
|
|
||||||
|
Finit supports runlevels 0-9, and S, with 0 reserved for halt, 6 reboot
|
||||||
|
and S for services that only run at bootstrap. Runlevel 1 is the single
|
||||||
|
user level, where usually no networking is enabled. In Finit this is
|
||||||
|
more of a policy for the user to define. Normally only runlevels 1-6
|
||||||
|
are used, and even more commonly, only the default runlevel is used.
|
||||||
|
|
||||||
|
To specify an allowed set of runlevels for a `service`, `run` command,
|
||||||
|
`task`, or `tty`, add `[NNN]` to your `/etc/finit.conf`, like this:
|
||||||
|
|
||||||
|
```
|
||||||
|
service [S12345] syslogd -n -x -- System log daemon
|
||||||
|
run [S] /etc/init.d/acpid start -- Starting ACPI Daemon
|
||||||
|
task [S] /etc/init.d/kbd start -- Preparing console
|
||||||
|
service [S12345] <pid/syslogd> klogd -n -x -- Kernel log daemon
|
||||||
|
|
||||||
|
tty [12345] /dev/tty1
|
||||||
|
tty [2] /dev/tty2
|
||||||
|
tty [2] /dev/tty3
|
||||||
|
tty [2] /dev/tty4
|
||||||
|
tty [2] /dev/tty5
|
||||||
|
tty [2] /dev/tty6
|
||||||
|
```
|
||||||
|
|
||||||
|
In this example syslogd is first started, in parallel, and then acpid is
|
||||||
|
called using a conventional SysV init script. It is called with the run
|
||||||
|
command, meaning the following task command to start the kbd script is
|
||||||
|
not called until the acpid init script has fully completed. Then the
|
||||||
|
keyboard setup script is called in parallel with klogd as a monitored
|
||||||
|
service.
|
||||||
|
|
||||||
|
Again, tasks and services are started in parallel, while run commands
|
||||||
|
are called in the order listed and subsequent commands are not started
|
||||||
|
until a run command has completed. Also, task and run commands are run
|
||||||
|
in a shell, so pipes and redirects can be used.
|
||||||
|
|
||||||
|
The following examples illustrate this. Bootstrap task and run commands
|
||||||
|
are also removed when they have completed, `initctl show` will not list
|
||||||
|
them.
|
||||||
|
|
||||||
|
```
|
||||||
|
task [S] echo "foo" | cat >/tmp/bar
|
||||||
|
run [S] echo "$HOME" >/tmp/secret
|
||||||
|
```
|
||||||
|
|
||||||
|
Switching between runlevels can be done by calling init with a single
|
||||||
|
argument, e.g. <kbd>init 5</kbd>, or using `initctl runlevel 5`, both
|
||||||
|
switch to runlevel 5. When changing runlevels Finit also automatically
|
||||||
|
reloads all `.conf` files in the `/etc/finit.d/` directory. So if you
|
||||||
|
want to set a new system config, switch to runlevel 1, change all config
|
||||||
|
files in the system, and touch all `.conf` files in `/etc/finit.d`
|
||||||
|
before switching back to the previous runlevel again — that way Finit
|
||||||
|
can both stop old services and start any new ones for you, without
|
||||||
|
rebooting the system.
|
||||||
|
|
||||||
|
|
||||||
|
[5]: https://en.wikipedia.org/wiki/Runlevel
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
Runparts & `/etc/rc.local`
|
||||||
|
==========================
|
||||||
|
|
||||||
|
At the end of the boot, when all bootstrap (`S`) tasks and services have
|
||||||
|
started, but not networking, Finit calls its built-in [run-parts(8)][]
|
||||||
|
command on any configured `runparts <DIR>` directory. This happens just
|
||||||
|
before changing to the configured runlevel (default 2). (Networking is
|
||||||
|
enabled just prior to changing from single user mode.)
|
||||||
|
|
||||||
|
```shell
|
||||||
|
runparts /etc/rc.d/
|
||||||
|
```
|
||||||
|
|
||||||
|
Right after the runlevel change when all services have started properly,
|
||||||
|
`/etc/rc.local` is called.
|
||||||
|
|
||||||
|
No configuration stanza in `/etc/finit.conf` is required for `rc.local`.
|
||||||
|
If it exists and is an executable shell script Finit calls it at the very
|
||||||
|
end of the boot, before calling the `HOOK_SYSTEM_UP`. See more in the
|
||||||
|
[Hook Scripts](plugins.md#hooks) section.
|
||||||
|
|
||||||
|
|
||||||
|
### Limitations
|
||||||
|
|
||||||
|
It is not possible to call Finit via signals or use `initctl` in any
|
||||||
|
runparts or `/etc/rc.local` script. This because Finit is single
|
||||||
|
threaded and is calling these scripts in a blocking fashion at the end
|
||||||
|
of runlevel S, at which point the event loop has not yet been started.
|
||||||
|
|
||||||
|
The event loop is the whole thing which Finit is built around, except
|
||||||
|
for runlevel S, which remains a slow procession through a lot of set up,
|
||||||
|
with a few hooks and blocking call outs to external scripts.
|
||||||
|
|
||||||
|
However, not all `initctl` commands are prohibited. Supported commands:
|
||||||
|
|
||||||
|
- `initctl cond`: only operate on files in `/run/finit/cond`
|
||||||
|
- `initctl enable/disable`: enabled run/task/service is activated on
|
||||||
|
the runlevel change from S to 2
|
||||||
|
- `initctl touch/show/create/delete/list`: `create`, provided the
|
||||||
|
non-interactive mode is used, again changes take effect in the
|
||||||
|
runlevel change directly after bootstrap
|
||||||
|
- `initctl -f reboot/poweroff/halt`: provided the `-f` flag is used to
|
||||||
|
force direct kernel commands
|
||||||
|
|
||||||
|
> [!TIP]
|
||||||
|
> you can set a `usr/` condition in `/etc/rc.local` and have a
|
||||||
|
> service/task in runlevel 2 depend on it to execute.
|
||||||
|
|
||||||
|
[run-parts(8)]: https://manpages.debian.org/cgi-bin/man.cgi?query=run-parts
|
||||||
+11
-42
@@ -1,15 +1,13 @@
|
|||||||
Finit Services
|
|
||||||
==============
|
|
||||||
|
|
||||||
Starting & Monitoring
|
Starting & Monitoring
|
||||||
---------------------
|
=====================
|
||||||
|
|
||||||
Finit can start and monitor the following types of daemons:
|
Finit can start and monitor the following types of daemons:
|
||||||
|
|
||||||
* Forks to background, creates a PID file
|
* Forks to background, creates a PID file
|
||||||
* Runs in foreground:
|
* Runs in foreground and signals ready by:
|
||||||
- creates a PID file
|
- creating a PID file
|
||||||
- does not create a PID file -- Finit can create it for you (optional)
|
- does not create a PID file -- Finit can create it for you (optional)
|
||||||
|
- [other mechanism][1] (systemd, s6)
|
||||||
|
|
||||||
Finit can *not* start and monitor a daemon that:
|
Finit can *not* start and monitor a daemon that:
|
||||||
|
|
||||||
@@ -24,9 +22,10 @@ Finit can *not* start and monitor a daemon that:
|
|||||||
|
|
||||||
> [!NOTE]
|
> [!NOTE]
|
||||||
> PID files is one mechanism used to assert conditions to synchronize
|
> PID files is one mechanism used to assert conditions to synchronize
|
||||||
> the start and stop of other, dependent, services.
|
> the start and stop of other, dependent, services. Other mechanisms
|
||||||
|
> are described in the [Service Synchronization][1] section.
|
||||||
|
|
||||||
### Forks to Background w/ PID File
|
### Forks to bg w/ PID file
|
||||||
|
|
||||||
There are two syntax variants, type 1 and type 2. The former is the
|
There are two syntax variants, type 1 and type 2. The former is the
|
||||||
traditional one used also for `sysv` start/stop scripts, and the latter
|
traditional one used also for `sysv` start/stop scripts, and the latter
|
||||||
@@ -40,49 +39,19 @@ In this example the resulting files to watch for are `/run/serv.pid` and
|
|||||||
`/var/run/serv.pid`, respectively. On most modern Linux systems this is
|
`/var/run/serv.pid`, respectively. On most modern Linux systems this is
|
||||||
the same directory (`/var/run` is a symlink to `../run`).
|
the same directory (`/var/run` is a symlink to `../run`).
|
||||||
|
|
||||||
### Runs in Foreground w/ PID File
|
### Runs in fg w/ PID file
|
||||||
|
|
||||||
service serv -n -p -- Foreground service w/ PID file
|
service serv -n -p -- Foreground service w/ PID file
|
||||||
|
|
||||||
### Runs in Foreground w/o PID File
|
### Runs in fg w/o PID file
|
||||||
|
|
||||||
Same as previous, but we tell Finit to create the PID file, because we
|
Same as previous, but we tell Finit to create the PID file, because we
|
||||||
need it to synchronize start/stop of a dependent service.
|
need it to synchronize start/stop of a dependent service.
|
||||||
|
|
||||||
service pid:/run/serv.pid serv -n -- Foreground service w/o PID file
|
service pid:/run/serv.pid serv -n -- Foreground service w/o PID file
|
||||||
|
|
||||||
### Runs in Foreground w/ Custom PID File
|
### Runs in fg w/ custom PID file
|
||||||
|
|
||||||
service pid:/run/servy.pid serv -n -p -P /run/servy.pid -- Foreground service w/ custom PID file
|
service pid:/run/servy.pid serv -n -p -P /run/servy.pid -- Foreground service w/ custom PID file
|
||||||
|
|
||||||
|
[1]: config/service-sync.md
|
||||||
State Machine
|
|
||||||
-------------
|
|
||||||
|
|
||||||
A service is bound to a state machine that is in one of six (6) states.
|
|
||||||
For `run`s and `task`s there is an additional end state called `DONE`,
|
|
||||||
not shown in the diagram for brevity. Services start in the `HALTED`
|
|
||||||
state.
|
|
||||||
|
|
||||||

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

|
||||||
|
|
||||||
|
The current state depends on the two following conditions:
|
||||||
|
|
||||||
|
* `E`: Service enabled. In order for `E` to be satisfied, the service
|
||||||
|
must be allowed to run in the current runlevel and not be stopped.
|
||||||
|
|
||||||
|
A service may be stopped, or blocked, for several reasons:
|
||||||
|
|
||||||
|
- The user has manually stopped the service using `initctl stop NAME`
|
||||||
|
- The program exits immediately. I.e. keeps crashing (make sure to use
|
||||||
|
the 'run this service in the foreground' command line option)
|
||||||
|
- The binary is missing in the filesystem
|
||||||
|
|
||||||
|
* `C`: Service conditions are satisfied:
|
||||||
|
|
||||||
|
- `on` (+): The condition is asserted.
|
||||||
|
- `off` (-): The condition is deasserted.
|
||||||
|
- `flux` (~): The condition state is unknown.
|
||||||
|
|
||||||
|
For a detailed description of conditions, and how to debug them,
|
||||||
|
see the [Finit Conditions](conditions.md) document.
|
||||||
@@ -0,0 +1,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
|
.\" First parameter, NAME, should be all caps
|
||||||
.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection
|
.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection
|
||||||
.\" other parameters are allowed: see man(7), man(1)
|
.\" other parameters are allowed: see man(7), man(1)
|
||||||
.Dd Apr 22, 2023
|
.Dd Jul 9, 2025
|
||||||
.\" Please adjust this date whenever revising the manpage.
|
.\" Please adjust this date whenever revising the manpage.
|
||||||
.Dt FINIT 8 SMM
|
.Dt FINIT 8 SMM
|
||||||
.Os Linux
|
.Os Linux
|
||||||
@@ -10,30 +10,66 @@
|
|||||||
.Nm finit
|
.Nm finit
|
||||||
.Nd Fast init for Linux systems
|
.Nd Fast init for Linux systems
|
||||||
.Sh SYNOPSIS
|
.Sh SYNOPSIS
|
||||||
.Nm /sbin/finit
|
.Nm /sbin/finit --
|
||||||
.Op --
|
|
||||||
.Op debug
|
.Op debug
|
||||||
.Op finit.cond=foo[,bar[,baz]]
|
|
||||||
.Op finit.config=/path/to/alt/finit.conf
|
|
||||||
.Op finit.debug
|
|
||||||
.Op finit.fstab=/etc/fstab.alt
|
|
||||||
.Op finit.status=<on,off>
|
|
||||||
.Op finit.status_style=<classic,modern>
|
|
||||||
.Op loglevel=<0-7>
|
|
||||||
.Op panic=SEC
|
|
||||||
.Op quiet
|
.Op quiet
|
||||||
.Op rescue | recover
|
.Op rescue | recover
|
||||||
.Op single | S
|
.Op single | S
|
||||||
|
.Op panic=SEC
|
||||||
|
.Op loglevel=<0-7>
|
||||||
|
.Op fsck.mode=[auto,skip,force]
|
||||||
|
.Op fsck.repair=[no,yes,preen]
|
||||||
|
.Op finit.debug=<true,false>
|
||||||
|
.Op finit.fstab=/path/to/fstab
|
||||||
|
.Op finit.cond=foo[,bar[,baz]]
|
||||||
|
.Op finit.config=/path/to/finit.conf
|
||||||
|
.Op finit.status_style=<classic,modern>
|
||||||
|
.Op finit.status=<on,off>
|
||||||
.Nm /sbin/telinit
|
.Nm /sbin/telinit
|
||||||
.Op Fl hv
|
.Op Fl hv
|
||||||
.Op q | Q | 0-9
|
.Op q | Q | s | S | 0-9
|
||||||
.Sh DESCRIPTION
|
.Sh DESCRIPTION
|
||||||
Fast init for Linux systems. Reverse engineered from the EeePC
|
Fast init for Linux systems. Reverse engineered from the EeePC
|
||||||
fastinit, 10+ years ago by Claudio Matsuoka, "gaps filled with frog
|
fastinit, 10+ years ago by Claudio Matsuoka, "gaps filled with frog
|
||||||
DNA ...". Focus is on small and embedded systems, although Finit is
|
DNA ...". Focus is on small and embedded systems, although Finit is
|
||||||
fully usable on server and desktop systems as well.
|
fully usable on server and desktop systems as well.
|
||||||
|
.Sh OPTIONS
|
||||||
|
When
|
||||||
|
.Sy not
|
||||||
|
started as PID 1,
|
||||||
|
.Nm
|
||||||
|
behaves like
|
||||||
|
.Nm telinit ,
|
||||||
|
following classic UNIX command line syntax. The options are:
|
||||||
.Pp
|
.Pp
|
||||||
Features include:
|
.Bl -tag -width Ds -compact -offset indent
|
||||||
|
.It Fl h
|
||||||
|
Show built-in help text.
|
||||||
|
.It Fl v
|
||||||
|
Show program version.
|
||||||
|
.El
|
||||||
|
.Pp
|
||||||
|
More options are implemented for SysV init support, but are ignored.
|
||||||
|
.Sh ARGUMENTS
|
||||||
|
When
|
||||||
|
.Sy not
|
||||||
|
started as PID 1,
|
||||||
|
.Nm ,
|
||||||
|
or
|
||||||
|
.Nm telinit ,
|
||||||
|
take these arguments:
|
||||||
|
.Pp
|
||||||
|
.Bl -tag -width Ds -compact -offset indent
|
||||||
|
.It q | Q
|
||||||
|
Reload configuration, same as
|
||||||
|
.Cm initctl reload .
|
||||||
|
.It 0 - 9
|
||||||
|
Go to runlevel N, same as
|
||||||
|
.Cm initctl reload N .
|
||||||
|
.It s | S
|
||||||
|
Go to single user mode, runlevel 1.
|
||||||
|
.El
|
||||||
|
.Sh FEATURES
|
||||||
.Bl -bullet -width 1n -compact
|
.Bl -bullet -width 1n -compact
|
||||||
.It
|
.It
|
||||||
Runlevels, defined per service
|
Runlevels, defined per service
|
||||||
@@ -93,6 +129,27 @@ Enable kernel debug. Debug messages are printed to the console until
|
|||||||
Finit starts up, unless
|
Finit starts up, unless
|
||||||
.Cm loglevel=7
|
.Cm loglevel=7
|
||||||
(below) is used.
|
(below) is used.
|
||||||
|
.It Cm fsck.mode=<auto,force,skip>
|
||||||
|
Defaults to
|
||||||
|
.Cm auto ,
|
||||||
|
unless Finit is built with
|
||||||
|
.Cm configure --enable-fastboot ,
|
||||||
|
in which case the default is
|
||||||
|
.Cm skip .
|
||||||
|
.It Cm fsck.repair=<preen,yes,no>
|
||||||
|
Defaults to
|
||||||
|
.Cm preen ,
|
||||||
|
unless Finit is built with
|
||||||
|
.Cm configure --enable-fsckfix ,
|
||||||
|
in which case the default is
|
||||||
|
.Cm yes .
|
||||||
|
This configure option also sets
|
||||||
|
.Cm fsck.mode=force ,
|
||||||
|
unless fastboot is also enabled. I.e.,
|
||||||
|
.Cm configure --enable-fastboot
|
||||||
|
build option overrides the
|
||||||
|
.Cm fsck.mode
|
||||||
|
default value.
|
||||||
.It Cm finit.cond=foo[,bar[,baz]]
|
.It Cm finit.cond=foo[,bar[,baz]]
|
||||||
set
|
set
|
||||||
.Cm <boot/foo>
|
.Cm <boot/foo>
|
||||||
|
|||||||
+128
-13
@@ -2,7 +2,7 @@
|
|||||||
.\" First parameter, NAME, should be all caps
|
.\" First parameter, NAME, should be all caps
|
||||||
.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection
|
.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection
|
||||||
.\" other parameters are allowed: see man(7), man(1)
|
.\" other parameters are allowed: see man(7), man(1)
|
||||||
.Dd July 11, 2023
|
.Dd July 10, 2025
|
||||||
.Dt FINIT.CONF 5 SMM
|
.Dt FINIT.CONF 5 SMM
|
||||||
.Os Linux
|
.Os Linux
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
@@ -178,7 +178,7 @@ Similar to
|
|||||||
.Cm service
|
.Cm service
|
||||||
is the
|
is the
|
||||||
.Cm sysv
|
.Cm sysv
|
||||||
stanza, which can be used to call SysV style start/stop scripts. The
|
directive, which can be used to call SysV style start/stop scripts. The
|
||||||
primary intention for this command is to be able to re-use traditional
|
primary intention for this command is to be able to re-use traditional
|
||||||
SysV init scripts in Linux distributions.
|
SysV init scripts in Linux distributions.
|
||||||
.Pp
|
.Pp
|
||||||
@@ -194,7 +194,7 @@ on
|
|||||||
.Cm initctl reload .
|
.Cm initctl reload .
|
||||||
Similar to how
|
Similar to how
|
||||||
.Cm service
|
.Cm service
|
||||||
stanzas work.
|
directives work.
|
||||||
.Pp
|
.Pp
|
||||||
Forking services started with
|
Forking services started with
|
||||||
.Cm sysv
|
.Cm sysv
|
||||||
@@ -416,7 +416,30 @@ The post:script is called with the same environment variables
|
|||||||
for the
|
for the
|
||||||
.Cm EXIT_CODE
|
.Cm EXIT_CODE
|
||||||
variable which is set to
|
variable which is set to
|
||||||
.Cm "crashed" .
|
.Cm "crashed"
|
||||||
|
.It Cm reload:'script [args]'
|
||||||
|
some services do not support SIGHUP but may have other ways to update
|
||||||
|
the configuration of a running daemon. When
|
||||||
|
.Cm reload:script
|
||||||
|
is defined it is preferred over SIGHUP. Like systemd,
|
||||||
|
.Nm finit
|
||||||
|
sets
|
||||||
|
.Cm $MAINPID
|
||||||
|
as a convenience to scripts, which in effect also allow
|
||||||
|
.Cm reload:'kill -HUP $MAINPID'
|
||||||
|
.It Cm stop:'script [args]'
|
||||||
|
Some services may require alternate methods to be stopped. When
|
||||||
|
.Cm stop:script
|
||||||
|
is defined it is preferred over SIGTERM and stop, for
|
||||||
|
.Cm service
|
||||||
|
and
|
||||||
|
.Cm sysv
|
||||||
|
directives, respectively.
|
||||||
|
Similar to
|
||||||
|
.Cm reload:script ,
|
||||||
|
.Nm finit
|
||||||
|
sets
|
||||||
|
.Cm $MAINPID .
|
||||||
.El
|
.El
|
||||||
.Pp
|
.Pp
|
||||||
When stopping a service (run/task/sysv/service), either manually or when
|
When stopping a service (run/task/sysv/service), either manually or when
|
||||||
@@ -535,7 +558,7 @@ size limit is reached.
|
|||||||
.It Cm tty Oo LVLS Oc Ao COND Ac Ar DEV Oo BAUD Oc Oo noclear Oc Oo nowait Oc Oo nologin Oc Oo TERM Oc
|
.It Cm tty Oo LVLS Oc Ao COND Ac Ar DEV Oo BAUD Oc Oo noclear Oc Oo nowait Oc Oo nologin Oc Oo TERM Oc
|
||||||
This form of the
|
This form of the
|
||||||
.Cm tty
|
.Cm tty
|
||||||
stanza uses the built-in getty on the given TTY device
|
directive uses the built-in getty on the given TTY device
|
||||||
.Ar DEV ,
|
.Ar DEV ,
|
||||||
in the given runlevels.
|
in the given runlevels.
|
||||||
.Ar DEV may be the special keyword
|
.Ar DEV may be the special keyword
|
||||||
@@ -545,8 +568,8 @@ useful on embedded systems.
|
|||||||
.Pp
|
.Pp
|
||||||
The default baud rate is 0, i.e., keep kernel default.
|
The default baud rate is 0, i.e., keep kernel default.
|
||||||
.Pp
|
.Pp
|
||||||
The `tty` stanza inherits runlevel, condition (and other feature)
|
The `tty` directive inherits runlevel, condition (and other feature)
|
||||||
parsing from the `service` stanza. So TTYs can run in one or many
|
parsing from the `service` directive. So TTYs can run in one or many
|
||||||
runlevels and depend on any condition supported by Finit. This is
|
runlevels and depend on any condition supported by Finit. This is
|
||||||
useful e.g. to depend on `<pid/elogind>` before starting a TTY.
|
useful e.g. to depend on `<pid/elogind>` before starting a TTY.
|
||||||
.Bd -unfilled -offset indent
|
.Bd -unfilled -offset indent
|
||||||
@@ -555,7 +578,7 @@ tty [12345] /dev/ttyAMA0 115200 noclear vt220
|
|||||||
.It Cm tty Oo LVLS Oc Ao COND Ac Ar CMD DEV Oo noclear Oc Oo nowait Oc
|
.It Cm tty Oo LVLS Oc Ao COND Ac Ar CMD DEV Oo noclear Oc Oo nowait Oc
|
||||||
This form of the
|
This form of the
|
||||||
.Cm tty
|
.Cm tty
|
||||||
stanza is for using an external getty, like agetty or the BusyBox getty.
|
directive is for using an external getty, like agetty or the BusyBox getty.
|
||||||
.Pp
|
.Pp
|
||||||
By default, these first two syntax variants
|
By default, these first two syntax variants
|
||||||
.Em clear
|
.Em clear
|
||||||
@@ -625,7 +648,7 @@ board bringup and system debugging it can come in handy.
|
|||||||
.Pp
|
.Pp
|
||||||
One can also use the
|
One can also use the
|
||||||
.Cm service
|
.Cm service
|
||||||
stanza to start a stand-alone shell:
|
directive to start a stand-alone shell:
|
||||||
.Bd -unfilled -offset indent
|
.Bd -unfilled -offset indent
|
||||||
service [12345] /bin/sh -l
|
service [12345] /bin/sh -l
|
||||||
.Ed
|
.Ed
|
||||||
@@ -650,9 +673,9 @@ is started to present a bare-bones root login prompt. If the root
|
|||||||
(uid:0, gid:0) user does not have a password set, no rescue is possible.
|
(uid:0, gid:0) user does not have a password set, no rescue is possible.
|
||||||
.El
|
.El
|
||||||
.Sh COMMAND MODIFIERS
|
.Sh COMMAND MODIFIERS
|
||||||
The run/task/tty/service/sysv stanzas take modifiers, or options, to
|
The run/task/tty/service/sysv directives take modifiers, or options, to
|
||||||
control their behavior. This section lists them with their limitations.
|
control their behavior. This section lists them with their limitations.
|
||||||
All modifiers must be placed between the stanza and its command.
|
All modifiers must be placed between the directive and its command.
|
||||||
.Bl -tag -width 1n
|
.Bl -tag -width 1n
|
||||||
.It Cm @user:group
|
.It Cm @user:group
|
||||||
Every
|
Every
|
||||||
@@ -946,9 +969,10 @@ or
|
|||||||
service [...] <...> cgroup.maint /path/to/foo args -- description
|
service [...] <...> cgroup.maint /path/to/foo args -- description
|
||||||
.Ed
|
.Ed
|
||||||
.Pp
|
.Pp
|
||||||
The latter form also allows per-stanza limits on the form:
|
The latter form also allows per-stanza limits on the form (notice the
|
||||||
|
single quotes for arguments that contain spaces):
|
||||||
.Bd -unfilled -offset indent
|
.Bd -unfilled -offset indent
|
||||||
service [...] <...> cgroup.maint:cpu.max:10000,mem.max:655360 /path/to/foo args -- description
|
service [...] <...> cgroup.maint:cpu.max:'200000 100000',mem.max:655360 /path/to/foo args -- description
|
||||||
.Ed
|
.Ed
|
||||||
.Pp
|
.Pp
|
||||||
Notice the comma separation and the
|
Notice the comma separation and the
|
||||||
@@ -968,6 +992,97 @@ available in your Linux kernel, or the name is misspelled.
|
|||||||
Linux cgroups and details surrounding values are not explained in the
|
Linux cgroups and details surrounding values are not explained in the
|
||||||
Finit documentation. The Linux admin-guide cover this well:
|
Finit documentation. The Linux admin-guide cover this well:
|
||||||
.Lk https://www.kernel.org/doc/html/latest/admin-guide/cgroup-v2.html
|
.Lk https://www.kernel.org/doc/html/latest/admin-guide/cgroup-v2.html
|
||||||
|
.Sh CONDITIONAL LOADING
|
||||||
|
Finit support conditional loading of stanzas. The following example is
|
||||||
|
take from the
|
||||||
|
.Pa system/hotplug.conf
|
||||||
|
file in the Finit distribution. Here we only show a simplified subset.
|
||||||
|
.Pp
|
||||||
|
Starting with the
|
||||||
|
.Cm nowarn
|
||||||
|
option.
|
||||||
|
.Bd -unfilled -offset indent
|
||||||
|
service nowarn name:udevd pid:udevd /lib/systemd/systemd-udevd
|
||||||
|
service nowarn name:udevd pid:udevd udevd
|
||||||
|
.Ed
|
||||||
|
.Pp
|
||||||
|
When loading the .conf file Finit looks for
|
||||||
|
.Pa /lib/systemd/systemd-udevd
|
||||||
|
if that is not found Finit automatically logs a warning. The
|
||||||
|
.Cm nowarn
|
||||||
|
option disables this warning so that the second line can be evaluated,
|
||||||
|
which also provides a service named
|
||||||
|
.Cm udevd .
|
||||||
|
.Bd -unfilled -offset indent
|
||||||
|
run nowarn if:udevd <pid/udevd> :1 udevadm settle -t 0
|
||||||
|
.Ed
|
||||||
|
.Pp
|
||||||
|
This line is only loaded if we know of a service named
|
||||||
|
.Cm udevd .
|
||||||
|
Again, we do not warn if
|
||||||
|
.Cm udevadm
|
||||||
|
is not found, execution will also stop here until the PID condition is
|
||||||
|
asserted, i.e., Finit detecting udevd has started.
|
||||||
|
.Bd -unfilled -offset indent
|
||||||
|
run nowarn conflict:udevd [S] mdev -s -- Populating device tree
|
||||||
|
.Ed
|
||||||
|
.Pp
|
||||||
|
If
|
||||||
|
.Cm udevd
|
||||||
|
is not available, we try to run
|
||||||
|
.Cm mdev ,
|
||||||
|
but if that is not found, again we do not warn.
|
||||||
|
.Pp
|
||||||
|
Conditional loading statements can also be negated, so the previous stanza
|
||||||
|
can also be written as:
|
||||||
|
.Bd -unfilled -offset indent
|
||||||
|
run nowarn if:!udevd [S] mdev -s -- Populating device tree
|
||||||
|
.Ed
|
||||||
|
.Pp
|
||||||
|
The reason for using
|
||||||
|
.Cm conflict
|
||||||
|
in this example is that a conflict can be resolved. Stanzas marked with
|
||||||
|
.C, conflict:foo
|
||||||
|
are rechecked at runtime.
|
||||||
|
.Sh CONDITIONAL EXECUTION
|
||||||
|
Similar to conditional loading of stanzas there is conditional runtime
|
||||||
|
execution. This can be confusing at first, since Finit already has a
|
||||||
|
condition subsystem, but this is more akin to the qualification to a
|
||||||
|
runlevel. E.g., a
|
||||||
|
.Cm task [123]
|
||||||
|
is qualified to run only in runlevel 1, 2, and 3. It is not considered
|
||||||
|
for other runlevels.
|
||||||
|
.Pp
|
||||||
|
Conditional execution qualify a run/task/service based on a condition.
|
||||||
|
Consider this (simplified) example from the Infix operating system:
|
||||||
|
.Bd -unfilled -offset indent
|
||||||
|
run [S] name:startup <pid/sysrepo> confd -b --load startup-config
|
||||||
|
run [S] if:<usr/fail-startup> name:failure <pid/sysrepo> confd --load failure-config
|
||||||
|
.Ed
|
||||||
|
.Pp
|
||||||
|
The two run statements reside in the same .conf file so Finit runs them
|
||||||
|
in true sequence. If loading the file
|
||||||
|
.Cm startup-config
|
||||||
|
fails
|
||||||
|
.Cm confd
|
||||||
|
sets the condition
|
||||||
|
.Cm usr/fail-startup ,
|
||||||
|
thus allowing the next run statement to load
|
||||||
|
.Cm failure-config .
|
||||||
|
.Pp
|
||||||
|
Notice the critical difference between the
|
||||||
|
.Cm <pid/sysrepo>
|
||||||
|
condition and
|
||||||
|
.Cm if:<usr/fail-startup> .
|
||||||
|
The former is a condition for starting and the latter is a condition to
|
||||||
|
check if a run/task/service is qualified to even be considered.
|
||||||
|
.Pp
|
||||||
|
Conditional execution statements can also be negated, so provided the
|
||||||
|
file loaded did the opposite, i.e., set a condition on success, the
|
||||||
|
previous stanza can also be written as:
|
||||||
|
.Bd -unfilled -offset indent
|
||||||
|
run [S] if:<!usr/startup-ok> name:failure <pid/sysrepo> confd ...
|
||||||
|
.Ed
|
||||||
.Sh LIMITATIONS
|
.Sh LIMITATIONS
|
||||||
As of Finit v4 there are no limitations to where
|
As of Finit v4 there are no limitations to where
|
||||||
.Cm .conf
|
.Cm .conf
|
||||||
|
|||||||
+47
-44
@@ -2,7 +2,7 @@
|
|||||||
.\" First parameter, NAME, should be all caps
|
.\" First parameter, NAME, should be all caps
|
||||||
.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection
|
.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection
|
||||||
.\" other parameters are allowed: see man(7), man(1)
|
.\" other parameters are allowed: see man(7), man(1)
|
||||||
.Dd June 6, 2021
|
.Dd July 10, 2025
|
||||||
.\" Please adjust this date whenever revising the manpage.
|
.\" Please adjust this date whenever revising the manpage.
|
||||||
.Dt INITCTL 8 SMM
|
.Dt INITCTL 8 SMM
|
||||||
.Os Linux
|
.Os Linux
|
||||||
@@ -24,39 +24,39 @@ This program follows the usual UNIX command line syntax, with long
|
|||||||
options starting with two dashes (`-'). The options are as follows:
|
options starting with two dashes (`-'). The options are as follows:
|
||||||
.Bl -tag -width Ds
|
.Bl -tag -width Ds
|
||||||
.It Fl b, -batch
|
.It Fl b, -batch
|
||||||
Batch mode, no screen size probing. Useful for scripting.
|
Batch mode, no screen size probing. Useful for scripting
|
||||||
.It Fl c, -create
|
.It Fl c, -create
|
||||||
Create missing paths (and files) as needed. Useful with the
|
Create missing paths (and files) as needed. Useful with the
|
||||||
.Cm edit
|
.Cm edit
|
||||||
command.
|
command
|
||||||
.It Fl f, -force
|
.It Fl f, -force
|
||||||
Ignore missing files and arguments, never prompt.
|
Ignore missing files and arguments, never prompt
|
||||||
.It Fl h, -help
|
.It Fl h, -help
|
||||||
Show built-in help text.
|
Show built-in help text
|
||||||
.It Fl j, -json
|
.It Fl j, -json
|
||||||
JSON output in
|
JSON output in
|
||||||
.Ar status
|
.Ar status
|
||||||
and
|
and
|
||||||
.Ar cond
|
.Ar cond
|
||||||
commands.
|
commands
|
||||||
.It Fl n, -noerr
|
.It Fl n, -noerr
|
||||||
When scripting
|
When scripting
|
||||||
.Nm
|
.Nm
|
||||||
to stop, start, restart, or signal a task or service, this option can be
|
to stop, start, restart, or signal a task or service, this option can be
|
||||||
used to ignore error 69 (no such task or service) and instead return 0
|
used to ignore error 69 (no such task or service) and instead return 0
|
||||||
(OK).
|
(OK)
|
||||||
.It Fl 1, -once
|
.It Fl 1, -once
|
||||||
Only one lap in commands like top.
|
Only one lap in commands like top
|
||||||
.It Fl p, -plain
|
.It Fl p, -plain
|
||||||
Use plain table headings, no ANSI control characters.
|
Use plain table headings, no ANSI control characters
|
||||||
.It Fl q, -quiet
|
.It Fl q, -quiet
|
||||||
Silent, only return status of command.
|
Silent, only return status of command
|
||||||
.It Fl t, -no-heading
|
.It Fl t, -no-heading
|
||||||
Skip table headings.
|
Skip table headings
|
||||||
.It Fl v, -verbose
|
.It Fl v, -verbose
|
||||||
Verbose output, where applicable.
|
Verbose output, where applicable
|
||||||
.It Fl V, -version
|
.It Fl V, -version
|
||||||
Show program version.
|
Show program version
|
||||||
.El
|
.El
|
||||||
.Sh COMMANDS
|
.Sh COMMANDS
|
||||||
.Bl -tag -width Ds
|
.Bl -tag -width Ds
|
||||||
@@ -66,9 +66,9 @@ Toggle
|
|||||||
(daemon) debug to
|
(daemon) debug to
|
||||||
.Pa /dev/console
|
.Pa /dev/console
|
||||||
.It Nm Ar help
|
.It Nm Ar help
|
||||||
Show built-in help text.
|
Show built-in help text
|
||||||
.It Nm Ar version
|
.It Nm Ar version
|
||||||
Show program version.
|
Show program version
|
||||||
.It Nm Ar ls | list
|
.It Nm Ar ls | list
|
||||||
List all
|
List all
|
||||||
.Cm *.conf
|
.Cm *.conf
|
||||||
@@ -112,9 +112,10 @@ like
|
|||||||
.Ar edit
|
.Ar edit
|
||||||
this tells
|
this tells
|
||||||
.Nm finit
|
.Nm finit
|
||||||
that a configuration has been changed and is a candidate to be restarted
|
that a configuration has been changed and is a candidate to be reloaded
|
||||||
(or SIGHUP'ed) on
|
(SIGHUP'ed or restarted) on
|
||||||
.Cm initctl reload
|
.Cm initctl reload
|
||||||
|
in dependency order
|
||||||
.It Nm Ar enable Ar CONF
|
.It Nm Ar enable Ar CONF
|
||||||
Enable
|
Enable
|
||||||
.Cm .conf
|
.Cm .conf
|
||||||
@@ -127,12 +128,12 @@ Disable
|
|||||||
.Cm .conf
|
.Cm .conf
|
||||||
in
|
in
|
||||||
.Pa /etc/finit.d/enabled ,
|
.Pa /etc/finit.d/enabled ,
|
||||||
i.e., removes symlink.
|
i.e., removes symlink
|
||||||
.It Nm Ar reload
|
.It Nm Ar reload
|
||||||
Reload
|
Reload all (touched)
|
||||||
.Cm *.conf in
|
.Cm *.conf in
|
||||||
.Pa /etc/finit.d ,
|
.Pa /etc/finit.d
|
||||||
i.e., activates changes.
|
and activate changes
|
||||||
.It Nm Ar cond set Ar COND Op COND ...
|
.It Nm Ar cond set Ar COND Op COND ...
|
||||||
Set (assert) user-defined condition,
|
Set (assert) user-defined condition,
|
||||||
.Cm +usr/COND
|
.Cm +usr/COND
|
||||||
@@ -148,7 +149,7 @@ The command is geared for scripting, check the exit code to get the
|
|||||||
status of the condition: 0 - on, 1 - off, 255 - flux. For a more
|
status of the condition: 0 - on, 1 - off, 255 - flux. For a more
|
||||||
verbose output, use the
|
verbose output, use the
|
||||||
.Fl v
|
.Fl v
|
||||||
option.
|
option
|
||||||
.It Nm Ar cond clr | clear Ar COND Op COND ...
|
.It Nm Ar cond clr | clear Ar COND Op COND ...
|
||||||
Clear (deassert) user-defined condition,
|
Clear (deassert) user-defined condition,
|
||||||
.Cm -usr/COND
|
.Cm -usr/COND
|
||||||
@@ -157,28 +158,28 @@ Show condition status, default
|
|||||||
.Cm cond
|
.Cm cond
|
||||||
command. Also supports the
|
command. Also supports the
|
||||||
.Fl j
|
.Fl j
|
||||||
option for detailed JSON output.
|
option for detailed JSON output
|
||||||
.It Nm Ar cond dump Op Cm TYPE
|
.It Nm Ar cond dump Op Cm TYPE
|
||||||
Dump all, or a given type of, conditions and their status. Also
|
Dump all, or a given type of, conditions and their status. Also
|
||||||
supports the
|
supports the
|
||||||
.Fl j
|
.Fl j
|
||||||
option for detailed JSON output.
|
option for detailed JSON output
|
||||||
.It Nm Ar ident Op Cm NAME
|
.It Nm Ar ident Op Cm NAME
|
||||||
Display indentities of all run/task/services, or only instances
|
Display indentities of all run/task/services, or only instances
|
||||||
matching
|
matching
|
||||||
.Cm NAME .
|
.Cm NAME .
|
||||||
A partial string, e.g.,
|
A partial string, e.g.,
|
||||||
.Cm NAM ,
|
.Cm NAM ,
|
||||||
will not match anything.
|
will not match anything
|
||||||
.It Nm Ar log Op Cm NAME
|
.It Nm Ar log Op Cm NAME
|
||||||
Show ten last Finit, or
|
Show ten last Finit, or
|
||||||
.Cm NAME ,
|
.Cm NAME ,
|
||||||
messages from syslog.
|
messages from syslog
|
||||||
.It Nm Ar start Cm NAME[:ID]
|
.It Nm Ar start Cm NAME[:ID]
|
||||||
Start service by name, with optional ID, e.g.,
|
Start service by name, with optional ID, e.g.,
|
||||||
.Cm initctl start tty:1
|
.Cm initctl start tty:1
|
||||||
.It Nm Ar stop Cm NAME[:ID]
|
.It Nm Ar stop Cm NAME[:ID]
|
||||||
Stop/Pause a running service by name.
|
Stop/Pause a running service by name
|
||||||
.It Nm Ar reload Cm NAME[:ID]
|
.It Nm Ar reload Cm NAME[:ID]
|
||||||
Reload service as if its configuration had changed. Internally,
|
Reload service as if its configuration had changed. Internally,
|
||||||
.Nm finit
|
.Nm finit
|
||||||
@@ -193,17 +194,19 @@ it is the same as calling
|
|||||||
Except for two things:
|
Except for two things:
|
||||||
.Bl -enum -offset indent -compact
|
.Bl -enum -offset indent -compact
|
||||||
.It
|
.It
|
||||||
if the service supports HUP, it's signaled instead of stop-started, and
|
if the service supports HUP (or has a
|
||||||
|
.Cm reload:script )
|
||||||
|
it is signaled instead of stop-started, and
|
||||||
.It
|
.It
|
||||||
it allows restarting run/task in the same runlevel -- which is otherwise
|
it allows restarting run/task in the same runlevel -- which is otherwise
|
||||||
restricted.
|
restricted
|
||||||
.El
|
.El
|
||||||
.It Nm Ar signal Cm NAME:[ID] S
|
.It Nm Ar <kill | signal> Cm NAME:[ID] S
|
||||||
Send signal S to service, by name.
|
Send signal S to service, by name.
|
||||||
.Cm S
|
.Cm S
|
||||||
may be a complete signal name such as SIGHUP, or short name such as HUP, or the signal number such as 1 (SIGHUP).
|
may be a complete signal name such as SIGHUP, or short name such as HUP, or the signal number such as 1 (SIGHUP)
|
||||||
.It Nm Ar restart Cm NAME[:ID]
|
.It Nm Ar restart Cm NAME[:ID]
|
||||||
Restart (stop/start) service by name.
|
Restart (stop/start) service by name
|
||||||
.It Nm Ar status Cm NAME[:ID]
|
.It Nm Ar status Cm NAME[:ID]
|
||||||
Show service status, by name. If only
|
Show service status, by name. If only
|
||||||
.Cm NAME
|
.Cm NAME
|
||||||
@@ -225,48 +228,48 @@ option for detailed JSON output suitable for machine parsing.
|
|||||||
.Pp
|
.Pp
|
||||||
.Sy Tip:
|
.Sy Tip:
|
||||||
.Xr jq 1
|
.Xr jq 1
|
||||||
is a useful scripting tool in combination with JSON output.
|
is a useful scripting tool in combination with JSON output
|
||||||
.It Nm Ar status
|
.It Nm Ar status
|
||||||
Show status of all services, default command. Also supports the
|
Show status of all services, default command. Also supports the
|
||||||
.Fl j
|
.Fl j
|
||||||
option for detailed JSON output.
|
option for detailed JSON output
|
||||||
.It Nm Ar cgroup
|
.It Nm Ar cgroup
|
||||||
List cgroup config overview.
|
List cgroup config overview
|
||||||
.It Nm Ar ps
|
.It Nm Ar ps
|
||||||
List processes based on cgroups.
|
List processes based on cgroups
|
||||||
.It Nm Ar top
|
.It Nm Ar top
|
||||||
Show top-like listing based on cgroups.
|
Show top-like listing based on cgroups
|
||||||
.It Nm Ar plugins
|
.It Nm Ar plugins
|
||||||
List installed plugins.
|
List installed plugins
|
||||||
.It Nm Ar runlevel Op Ar 0-9
|
.It Nm Ar runlevel Op Ar 0-9
|
||||||
Show or set runlevel: 0 halt, 6 reboot.
|
Show or set runlevel: 0 halt, 6 reboot.
|
||||||
.Pp
|
.Pp
|
||||||
If called at boot (runlevel S) to set the runlevel, Finit only schedules
|
If called at boot (runlevel S) to set the runlevel, Finit only schedules
|
||||||
the change, effectively overriding the configured runlevel from
|
the change, effectively overriding the configured runlevel from
|
||||||
.Pa /etc/finit.conf .
|
.Pa /etc/finit.conf .
|
||||||
Useful to trigger a fail-safe mode, or similar.
|
Useful to trigger a fail-safe mode, or similar
|
||||||
.It Nm Ar reboot
|
.It Nm Ar reboot
|
||||||
Reboot system, default if
|
Reboot system, default if
|
||||||
.Cm reboot
|
.Cm reboot
|
||||||
is symlinked to
|
is symlinked to
|
||||||
.Nm .
|
.Nm
|
||||||
.It Nm Ar halt
|
.It Nm Ar halt
|
||||||
Halt system, default if
|
Halt system, default if
|
||||||
.Cm halt
|
.Cm halt
|
||||||
is symlinked to
|
is symlinked to
|
||||||
.Nm .
|
.Nm
|
||||||
.It Nm Ar poweroff
|
.It Nm Ar poweroff
|
||||||
Power-off system, default if
|
Power-off system, default if
|
||||||
.Cm poweroff
|
.Cm poweroff
|
||||||
is symlinked to
|
is symlinked to
|
||||||
.Nm .
|
.Nm
|
||||||
.It Nm Ar suspend
|
.It Nm Ar suspend
|
||||||
Suspend system, default if
|
Suspend system, default if
|
||||||
.Cm suspend
|
.Cm suspend
|
||||||
is symlinked to
|
is symlinked to
|
||||||
.Nm .
|
.Nm
|
||||||
.It Nm Ar utmp show
|
.It Nm Ar utmp show
|
||||||
Raw dump of UTMP/WTMP db.
|
Raw dump of UTMP/WTMP db
|
||||||
.El
|
.El
|
||||||
.Sh SEE ALSO
|
.Sh SEE ALSO
|
||||||
.Xr finit.conf 5
|
.Xr finit.conf 5
|
||||||
|
|||||||
+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
|
/* Save and restore ALSA sound settings using alsactl
|
||||||
*
|
*
|
||||||
* Copyright (c) 2012-2024 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (c) 2012-2025 Joachim Wiberg <troglobit@gmail.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -27,9 +27,11 @@
|
|||||||
# include <lite/lite.h>
|
# include <lite/lite.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "conf.h"
|
||||||
#include "finit.h"
|
#include "finit.h"
|
||||||
#include "helpers.h"
|
#include "helpers.h"
|
||||||
#include "plugin.h"
|
#include "plugin.h"
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
#define ALSACTL "alsactl"
|
#define ALSACTL "alsactl"
|
||||||
|
|
||||||
@@ -65,12 +67,12 @@ static plugin_t plugin = {
|
|||||||
.hook[HOOK_SHUTDOWN] = { .cb = save }
|
.hook[HOOK_SHUTDOWN] = { .cb = save }
|
||||||
};
|
};
|
||||||
|
|
||||||
PLUGIN_INIT(plugin_init)
|
PLUGIN_INIT(__init)
|
||||||
{
|
{
|
||||||
plugin_register(&plugin);
|
plugin_register(&plugin);
|
||||||
}
|
}
|
||||||
|
|
||||||
PLUGIN_EXIT(plugin_exit)
|
PLUGIN_EXIT(__exit)
|
||||||
{
|
{
|
||||||
plugin_unregister(&plugin);
|
plugin_unregister(&plugin);
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-5
@@ -1,6 +1,6 @@
|
|||||||
/* Setup necessary system files for, e.g. UTMP (tracking logins)
|
/* Setup necessary system files for, e.g. UTMP (tracking logins)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2012-2024 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (c) 2012-2025 Joachim Wiberg <troglobit@gmail.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -38,9 +38,9 @@
|
|||||||
#include "finit.h"
|
#include "finit.h"
|
||||||
#include "helpers.h"
|
#include "helpers.h"
|
||||||
#include "plugin.h"
|
#include "plugin.h"
|
||||||
#include "tmpfiles.h"
|
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "utmp-api.h"
|
#include "utmp-api.h"
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
static int is_tmpfs(char *path)
|
static int is_tmpfs(char *path)
|
||||||
{
|
{
|
||||||
@@ -163,7 +163,7 @@ static void setup(void *arg)
|
|||||||
kernel_links();
|
kernel_links();
|
||||||
|
|
||||||
/* Create all system tmpfiles.d(5) */
|
/* Create all system tmpfiles.d(5) */
|
||||||
tmpfilesd();
|
run_interactive(_PATH_TMPFILES " --create", "Creating required directories and files");
|
||||||
|
|
||||||
/* Set BOOT_TIME UTMP entry */
|
/* Set BOOT_TIME UTMP entry */
|
||||||
utmp_set_boot();
|
utmp_set_boot();
|
||||||
@@ -178,12 +178,12 @@ static plugin_t plugin = {
|
|||||||
.depends = { "pidfile" },
|
.depends = { "pidfile" },
|
||||||
};
|
};
|
||||||
|
|
||||||
PLUGIN_INIT(plugin_init)
|
PLUGIN_INIT(__init)
|
||||||
{
|
{
|
||||||
plugin_register(&plugin);
|
plugin_register(&plugin);
|
||||||
}
|
}
|
||||||
|
|
||||||
PLUGIN_EXIT(plugin_exit)
|
PLUGIN_EXIT(__exit)
|
||||||
{
|
{
|
||||||
plugin_unregister(&plugin);
|
plugin_unregister(&plugin);
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-3
@@ -1,6 +1,6 @@
|
|||||||
/* Setup and start system message bus, D-Bus
|
/* Setup and start system message bus, D-Bus
|
||||||
*
|
*
|
||||||
* Copyright (c) 2012-2024 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (c) 2012-2025 Joachim Wiberg <troglobit@gmail.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -33,7 +33,9 @@
|
|||||||
#include "helpers.h"
|
#include "helpers.h"
|
||||||
#include "plugin.h"
|
#include "plugin.h"
|
||||||
#include "service.h"
|
#include "service.h"
|
||||||
|
#include "util.h"
|
||||||
#include "conf.h"
|
#include "conf.h"
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
#define DBUS_DAEMON "dbus-daemon"
|
#define DBUS_DAEMON "dbus-daemon"
|
||||||
#define DBUS_ARGS "--nofork --system --syslog-only"
|
#define DBUS_ARGS "--nofork --system --syslog-only"
|
||||||
@@ -166,12 +168,12 @@ static plugin_t plugin = {
|
|||||||
.hook[HOOK_SVC_PLUGIN] = { .cb = setup },
|
.hook[HOOK_SVC_PLUGIN] = { .cb = setup },
|
||||||
};
|
};
|
||||||
|
|
||||||
PLUGIN_INIT(plugin_init)
|
PLUGIN_INIT(__init)
|
||||||
{
|
{
|
||||||
plugin_register(&plugin);
|
plugin_register(&plugin);
|
||||||
}
|
}
|
||||||
|
|
||||||
PLUGIN_EXIT(plugin_exit)
|
PLUGIN_EXIT(__exit)
|
||||||
{
|
{
|
||||||
plugin_unregister(&plugin);
|
plugin_unregister(&plugin);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -99,12 +99,12 @@ static plugin_t plugin = {
|
|||||||
*/
|
*/
|
||||||
};
|
};
|
||||||
|
|
||||||
PLUGIN_INIT(plugin_init)
|
PLUGIN_INIT(__init)
|
||||||
{
|
{
|
||||||
plugin_register(&plugin);
|
plugin_register(&plugin);
|
||||||
}
|
}
|
||||||
|
|
||||||
PLUGIN_EXIT(plugin_exit)
|
PLUGIN_EXIT(__exit)
|
||||||
{
|
{
|
||||||
plugin_unregister(&plugin);
|
plugin_unregister(&plugin);
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-3
@@ -1,6 +1,6 @@
|
|||||||
/* Coldplug modules using modalias magic
|
/* Coldplug modules using modalias magic
|
||||||
*
|
*
|
||||||
* Copyright (c) 2021-2024 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (c) 2021-2025 Joachim Wiberg <troglobit@gmail.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -50,6 +50,7 @@
|
|||||||
#include "finit.h"
|
#include "finit.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "plugin.h"
|
#include "plugin.h"
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
struct module {
|
struct module {
|
||||||
TAILQ_ENTRY(module) link;
|
TAILQ_ENTRY(module) link;
|
||||||
@@ -232,12 +233,12 @@ static plugin_t plugin = {
|
|||||||
.depends = { "bootmisc", }
|
.depends = { "bootmisc", }
|
||||||
};
|
};
|
||||||
|
|
||||||
PLUGIN_INIT(plugin_init)
|
PLUGIN_INIT(__init)
|
||||||
{
|
{
|
||||||
plugin_register(&plugin);
|
plugin_register(&plugin);
|
||||||
}
|
}
|
||||||
|
|
||||||
PLUGIN_EXIT(plugin_exit)
|
PLUGIN_EXIT(__exit)
|
||||||
{
|
{
|
||||||
plugin_unregister(&plugin);
|
plugin_unregister(&plugin);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -58,6 +58,7 @@
|
|||||||
#include "plugin.h"
|
#include "plugin.h"
|
||||||
#include "service.h"
|
#include "service.h"
|
||||||
#include "conf.h"
|
#include "conf.h"
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
#ifndef MODULES_LOAD_PATH
|
#ifndef MODULES_LOAD_PATH
|
||||||
#define MODULES_LOAD_PATH "/etc/modules-load.d"
|
#define MODULES_LOAD_PATH "/etc/modules-load.d"
|
||||||
@@ -216,12 +217,12 @@ static plugin_t plugin = {
|
|||||||
.hook[HOOK_SVC_PLUGIN] = { .cb = load },
|
.hook[HOOK_SVC_PLUGIN] = { .cb = load },
|
||||||
};
|
};
|
||||||
|
|
||||||
PLUGIN_INIT(plugin_init)
|
PLUGIN_INIT(__init)
|
||||||
{
|
{
|
||||||
plugin_register(&plugin);
|
plugin_register(&plugin);
|
||||||
}
|
}
|
||||||
|
|
||||||
PLUGIN_EXIT(plugin_exit)
|
PLUGIN_EXIT(__exit)
|
||||||
{
|
{
|
||||||
plugin_unregister(&plugin);
|
plugin_unregister(&plugin);
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-3
@@ -2,7 +2,7 @@
|
|||||||
/* Netlink plugin for IFUP/IFDN and GW events
|
/* Netlink plugin for IFUP/IFDN and GW events
|
||||||
*
|
*
|
||||||
* Copyright (C) 2009-2011 Mårten Wikström <marten.wikstrom@keystream.se>
|
* Copyright (C) 2009-2011 Mårten Wikström <marten.wikstrom@keystream.se>
|
||||||
* Copyright (C) 2009-2024 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (C) 2009-2025 Joachim Wiberg <troglobit@gmail.com>
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and/or distribute this software for any
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
@@ -29,6 +29,7 @@
|
|||||||
|
|
||||||
#include "finit.h"
|
#include "finit.h"
|
||||||
#include "cond.h"
|
#include "cond.h"
|
||||||
|
#include "log.h"
|
||||||
#include "helpers.h"
|
#include "helpers.h"
|
||||||
#include "plugin.h"
|
#include "plugin.h"
|
||||||
#include "service.h"
|
#include "service.h"
|
||||||
@@ -414,7 +415,7 @@ static plugin_t plugin = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
PLUGIN_INIT(plugin_init)
|
PLUGIN_INIT(__init)
|
||||||
{
|
{
|
||||||
struct sockaddr_nl sa;
|
struct sockaddr_nl sa;
|
||||||
int sd;
|
int sd;
|
||||||
@@ -447,7 +448,7 @@ PLUGIN_INIT(plugin_init)
|
|||||||
plugin_register(&plugin);
|
plugin_register(&plugin);
|
||||||
}
|
}
|
||||||
|
|
||||||
PLUGIN_EXIT(plugin_exit)
|
PLUGIN_EXIT(__exit)
|
||||||
{
|
{
|
||||||
plugin_unregister(&plugin);
|
plugin_unregister(&plugin);
|
||||||
close(plugin.io.fd);
|
close(plugin.io.fd);
|
||||||
|
|||||||
+21
-3
@@ -1,7 +1,7 @@
|
|||||||
/* Simple pidfile event monitor for the Finit condition engine
|
/* Simple pidfile event monitor for the Finit condition engine
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2016 Tobias Waldekranz <tobias@waldekranz.com>
|
* Copyright (c) 2015-2016 Tobias Waldekranz <tobias@waldekranz.com>
|
||||||
* Copyright (c) 2016-2024 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (c) 2016-2025 Joachim Wiberg <troglobit@gmail.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -34,6 +34,7 @@
|
|||||||
#include "plugin.h"
|
#include "plugin.h"
|
||||||
#include "service.h"
|
#include "service.h"
|
||||||
#include "iwatch.h"
|
#include "iwatch.h"
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
static struct iwatch iw_pidfile;
|
static struct iwatch iw_pidfile;
|
||||||
|
|
||||||
@@ -80,6 +81,23 @@ static void pidfile_update_conds(char *dir, char *name, uint32_t mask)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
switch (svc->state) {
|
||||||
|
case SVC_TEARDOWN_STATE:
|
||||||
|
case SVC_CLEANUP_STATE:
|
||||||
|
case SVC_SETUP_STATE:
|
||||||
|
/*
|
||||||
|
* E.g., a setup script for a container may run in lieu
|
||||||
|
* of crun, trying to fetch a container image from the
|
||||||
|
* network. This script may want to advertise its PID
|
||||||
|
* to the system for clean and swift reboots.
|
||||||
|
*/
|
||||||
|
dbg("%s[%d]: ignoring any PID file changes in CLEANUP/TEARDOWN/SETUP",
|
||||||
|
svc_ident(svc, NULL, 0), svc->pid);
|
||||||
|
return;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
/* Service condistion to set/clear */
|
/* Service condistion to set/clear */
|
||||||
mkcond(svc, cond, sizeof(cond));
|
mkcond(svc, cond, sizeof(cond));
|
||||||
|
|
||||||
@@ -321,7 +339,7 @@ static plugin_t plugin = {
|
|||||||
.depends = { "netlink" }, /* bootmisc depends on us */
|
.depends = { "netlink" }, /* bootmisc depends on us */
|
||||||
};
|
};
|
||||||
|
|
||||||
PLUGIN_INIT(plugin_init)
|
PLUGIN_INIT(__init)
|
||||||
{
|
{
|
||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
@@ -336,7 +354,7 @@ PLUGIN_INIT(plugin_init)
|
|||||||
plugin_register(&plugin);
|
plugin_register(&plugin);
|
||||||
}
|
}
|
||||||
|
|
||||||
PLUGIN_EXIT(plugin_exit)
|
PLUGIN_EXIT(__exit)
|
||||||
{
|
{
|
||||||
plugin_unregister(&plugin);
|
plugin_unregister(&plugin);
|
||||||
iwatch_exit(&iw_pidfile);
|
iwatch_exit(&iw_pidfile);
|
||||||
|
|||||||
+5
-3
@@ -1,6 +1,6 @@
|
|||||||
/* Set kernel variables from /etc/sysctl.conf et al
|
/* Set kernel variables from /etc/sysctl.conf et al
|
||||||
*
|
*
|
||||||
* Copyright (c) 2016-2024 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (c) 2016-2025 Joachim Wiberg <troglobit@gmail.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -31,6 +31,8 @@
|
|||||||
#include "finit.h"
|
#include "finit.h"
|
||||||
#include "helpers.h"
|
#include "helpers.h"
|
||||||
#include "plugin.h"
|
#include "plugin.h"
|
||||||
|
#include "conf.h"
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
#ifndef SYSCTL_PATH
|
#ifndef SYSCTL_PATH
|
||||||
#define SYSCTL_PATH "/sbin/sysctl"
|
#define SYSCTL_PATH "/sbin/sysctl"
|
||||||
@@ -74,12 +76,12 @@ static plugin_t plugin = {
|
|||||||
.depends = { "bootmisc", },
|
.depends = { "bootmisc", },
|
||||||
};
|
};
|
||||||
|
|
||||||
PLUGIN_INIT(plugin_init)
|
PLUGIN_INIT(__init)
|
||||||
{
|
{
|
||||||
plugin_register(&plugin);
|
plugin_register(&plugin);
|
||||||
}
|
}
|
||||||
|
|
||||||
PLUGIN_EXIT(plugin_exit)
|
PLUGIN_EXIT(__exit)
|
||||||
{
|
{
|
||||||
plugin_unregister(&plugin);
|
plugin_unregister(&plugin);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/* Setup necessary files for resolvconf
|
/* Setup necessary files for resolvconf
|
||||||
*
|
*
|
||||||
* Copyright (c) 2012-2024 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (c) 2012-2025 Joachim Wiberg <troglobit@gmail.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -30,6 +30,7 @@
|
|||||||
#include "finit.h"
|
#include "finit.h"
|
||||||
#include "helpers.h"
|
#include "helpers.h"
|
||||||
#include "plugin.h"
|
#include "plugin.h"
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* No need to clean up files in /etc/resolvconf/run/interface/
|
* No need to clean up files in /etc/resolvconf/run/interface/
|
||||||
@@ -57,12 +58,12 @@ static plugin_t plugin = {
|
|||||||
.depends = { "bootmisc", },
|
.depends = { "bootmisc", },
|
||||||
};
|
};
|
||||||
|
|
||||||
PLUGIN_INIT(plugin_init)
|
PLUGIN_INIT(__init)
|
||||||
{
|
{
|
||||||
plugin_register(&plugin);
|
plugin_register(&plugin);
|
||||||
}
|
}
|
||||||
|
|
||||||
PLUGIN_EXIT(plugin_exit)
|
PLUGIN_EXIT(__exit)
|
||||||
{
|
{
|
||||||
plugin_unregister(&plugin);
|
plugin_unregister(&plugin);
|
||||||
}
|
}
|
||||||
|
|||||||
+27
-16
@@ -1,6 +1,6 @@
|
|||||||
/* Save and restore RTC using hwclock
|
/* Save and restore RTC using hwclock
|
||||||
*
|
*
|
||||||
* Copyright (c) 2012-2024 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (c) 2012-2025 Joachim Wiberg <troglobit@gmail.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -35,6 +35,9 @@
|
|||||||
#include "finit.h"
|
#include "finit.h"
|
||||||
#include "helpers.h"
|
#include "helpers.h"
|
||||||
#include "plugin.h"
|
#include "plugin.h"
|
||||||
|
#include "private.h"
|
||||||
|
#include "conf.h"
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Kernel RTC driver validates against this date for sanity check. The
|
* Kernel RTC driver validates against this date for sanity check. The
|
||||||
@@ -167,16 +170,18 @@ static void file_save(void *arg)
|
|||||||
static void file_restore(void *arg)
|
static void file_restore(void *arg)
|
||||||
{
|
{
|
||||||
struct tm tm = { 0 };
|
struct tm tm = { 0 };
|
||||||
int rc = 1;
|
int rc = 0;
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
|
char msg[120];
|
||||||
|
|
||||||
if (!rtc_file) {
|
if (!rtc_file) {
|
||||||
logit(LOG_NOTICE, "System has no RTC (missing driver?), skipping restore.");
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
print_desc(NULL, "Restoring system clock from backup");
|
|
||||||
|
|
||||||
fp = fopen(rtc_file, "r");
|
fp = fopen(rtc_file, "r");
|
||||||
if (fp) {
|
if (fp) {
|
||||||
char buf[32];
|
char buf[32];
|
||||||
@@ -184,18 +189,25 @@ static void file_restore(void *arg)
|
|||||||
if (fgets(buf, sizeof(buf), fp)) {
|
if (fgets(buf, sizeof(buf), fp)) {
|
||||||
chomp(buf);
|
chomp(buf);
|
||||||
strptime(buf, RTC_FMT, &tm);
|
strptime(buf, RTC_FMT, &tm);
|
||||||
rc = time_set(&tm);
|
if (!strptime(buf, RTC_FMT, &tm))
|
||||||
|
rc = 1;
|
||||||
}
|
}
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
} else
|
}
|
||||||
logit(LOG_WARNING, "Missing %s", rtc_file);
|
rc = 1;
|
||||||
|
|
||||||
if (rc) {
|
if (rc) {
|
||||||
time_set(NULL);
|
print_desc(NULL, "Failed to restore system clock from restore file");
|
||||||
rc = 2;
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
print(rc, NULL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int rtc_open(void)
|
static int rtc_open(void)
|
||||||
@@ -289,8 +301,7 @@ static void rtc_restore(void *arg)
|
|||||||
print(2, NULL);
|
print(2, NULL);
|
||||||
|
|
||||||
/* Try restoring from last save game */
|
/* Try restoring from last save game */
|
||||||
if (rtc_file)
|
file_restore(arg);
|
||||||
file_restore(arg);
|
|
||||||
} else
|
} else
|
||||||
print(0, NULL);
|
print(0, NULL);
|
||||||
|
|
||||||
@@ -320,7 +331,7 @@ static plugin_t plugin = {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
PLUGIN_INIT(plugin_init)
|
PLUGIN_INIT(__init)
|
||||||
{
|
{
|
||||||
struct tm tm = { 0 };
|
struct tm tm = { 0 };
|
||||||
|
|
||||||
@@ -336,7 +347,7 @@ PLUGIN_INIT(plugin_init)
|
|||||||
plugin_register(&plugin);
|
plugin_register(&plugin);
|
||||||
}
|
}
|
||||||
|
|
||||||
PLUGIN_EXIT(plugin_exit)
|
PLUGIN_EXIT(__exit)
|
||||||
{
|
{
|
||||||
uev_timer_stop(&rtc_timer);
|
uev_timer_stop(&rtc_timer);
|
||||||
plugin_unregister(&plugin);
|
plugin_unregister(&plugin);
|
||||||
|
|||||||
+4
-3
@@ -1,6 +1,6 @@
|
|||||||
/* System condition event monitor for the Finit condition engine
|
/* System condition event monitor for the Finit condition engine
|
||||||
*
|
*
|
||||||
* Copyright (c) 2021-2024 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (c) 2021-2025 Joachim Wiberg <troglobit@gmail.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -32,6 +32,7 @@
|
|||||||
#include "pid.h"
|
#include "pid.h"
|
||||||
#include "plugin.h"
|
#include "plugin.h"
|
||||||
#include "iwatch.h"
|
#include "iwatch.h"
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
static struct iwatch iw_sys;
|
static struct iwatch iw_sys;
|
||||||
|
|
||||||
@@ -184,7 +185,7 @@ static plugin_t plugin = {
|
|||||||
.depends = { "bootmisc", },
|
.depends = { "bootmisc", },
|
||||||
};
|
};
|
||||||
|
|
||||||
PLUGIN_INIT(plugin_init)
|
PLUGIN_INIT(__init)
|
||||||
{
|
{
|
||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
@@ -199,7 +200,7 @@ PLUGIN_INIT(plugin_init)
|
|||||||
plugin_register(&plugin);
|
plugin_register(&plugin);
|
||||||
}
|
}
|
||||||
|
|
||||||
PLUGIN_EXIT(plugin_exit)
|
PLUGIN_EXIT(__exit)
|
||||||
{
|
{
|
||||||
plugin_unregister(&plugin);
|
plugin_unregister(&plugin);
|
||||||
iwatch_exit(&iw_sys);
|
iwatch_exit(&iw_sys);
|
||||||
|
|||||||
+4
-3
@@ -1,7 +1,7 @@
|
|||||||
/* Optional TTY Watcher, used to catch new TTYs that are discovered, e.g., USB
|
/* Optional TTY Watcher, used to catch new TTYs that are discovered, e.g., USB
|
||||||
*
|
*
|
||||||
* Copyright (c) 2013 Mattias Walström <lazzer@gmail.com>
|
* Copyright (c) 2013 Mattias Walström <lazzer@gmail.com>
|
||||||
* Copyright (c) 2013-2024 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (c) 2013-2025 Joachim Wiberg <troglobit@gmail.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -38,6 +38,7 @@
|
|||||||
#include "plugin.h"
|
#include "plugin.h"
|
||||||
#include "service.h"
|
#include "service.h"
|
||||||
#include "tty.h"
|
#include "tty.h"
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
static void tty_watcher(void *arg, int fd, int events);
|
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();
|
setup();
|
||||||
plugin_register(&plugin);
|
plugin_register(&plugin);
|
||||||
}
|
}
|
||||||
|
|
||||||
PLUGIN_EXIT(plugin_exit)
|
PLUGIN_EXIT(__exit)
|
||||||
{
|
{
|
||||||
plugin_unregister(&plugin);
|
plugin_unregister(&plugin);
|
||||||
if (plugin.io.fd)
|
if (plugin.io.fd)
|
||||||
|
|||||||
+13
-8
@@ -1,6 +1,6 @@
|
|||||||
/* Setup and save random seed at boot/shutdown
|
/* Setup and save random seed at boot/shutdown
|
||||||
*
|
*
|
||||||
* Copyright (c) 2012-2024 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (c) 2012-2025 Joachim Wiberg <troglobit@gmail.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -38,6 +38,8 @@
|
|||||||
#include "finit.h"
|
#include "finit.h"
|
||||||
#include "helpers.h"
|
#include "helpers.h"
|
||||||
#include "plugin.h"
|
#include "plugin.h"
|
||||||
|
#include "conf.h"
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
#ifndef RANDOM_BYTES
|
#ifndef RANDOM_BYTES
|
||||||
#define RANDOM_BYTES (32*1024)
|
#define RANDOM_BYTES (32*1024)
|
||||||
@@ -78,6 +80,7 @@ static void setup(void *arg)
|
|||||||
{
|
{
|
||||||
#ifdef RANDOMSEED
|
#ifdef RANDOMSEED
|
||||||
struct rand_pool_info *rpi;
|
struct rand_pool_info *rpi;
|
||||||
|
unsigned char *rpi_buf;
|
||||||
ssize_t len = 0;
|
ssize_t len = 0;
|
||||||
struct stat st;
|
struct stat st;
|
||||||
int rc = -1;
|
int rc = -1;
|
||||||
@@ -103,13 +106,14 @@ static void setup(void *arg)
|
|||||||
hw = fopen(hwrng, "r");
|
hw = fopen(hwrng, "r");
|
||||||
if (hw) {
|
if (hw) {
|
||||||
char buf[512];
|
char buf[512];
|
||||||
size_t len;
|
size_t num;
|
||||||
|
|
||||||
len = fread(buf, sizeof(buf[0]), sizeof(buf), hw);
|
num = fread(buf, sizeof(buf[0]), sizeof(buf), hw);
|
||||||
if (len == 0)
|
if (num == 0)
|
||||||
fallback(fp);
|
fallback(fp);
|
||||||
else
|
else
|
||||||
len = fwrite(buf, sizeof(buf[0]), len, fp);
|
fwrite(buf, sizeof(buf[0]), num, fp);
|
||||||
|
|
||||||
fclose(hw);
|
fclose(hw);
|
||||||
} else {
|
} else {
|
||||||
fallback(fp);
|
fallback(fp);
|
||||||
@@ -137,10 +141,11 @@ static void setup(void *arg)
|
|||||||
goto fallback;
|
goto fallback;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rpi_buf = (unsigned char *)rpi->buf;
|
||||||
do {
|
do {
|
||||||
ssize_t num;
|
ssize_t num;
|
||||||
|
|
||||||
num = read(fd, &rpi->buf[len], RANDOM_BYTES - len);
|
num = read(fd, &rpi_buf[len], RANDOM_BYTES - len);
|
||||||
if (num <= 0) {
|
if (num <= 0) {
|
||||||
if (num == -1 && errno == EINTR)
|
if (num == -1 && errno == EINTR)
|
||||||
continue;
|
continue;
|
||||||
@@ -203,12 +208,12 @@ static plugin_t plugin = {
|
|||||||
.depends = { "bootmisc", }
|
.depends = { "bootmisc", }
|
||||||
};
|
};
|
||||||
|
|
||||||
PLUGIN_INIT(plugin_init)
|
PLUGIN_INIT(__init)
|
||||||
{
|
{
|
||||||
plugin_register(&plugin);
|
plugin_register(&plugin);
|
||||||
}
|
}
|
||||||
|
|
||||||
PLUGIN_EXIT(plugin_exit)
|
PLUGIN_EXIT(__exit)
|
||||||
{
|
{
|
||||||
plugin_unregister(&plugin);
|
plugin_unregister(&plugin);
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-3
@@ -1,6 +1,6 @@
|
|||||||
/* User-defined condition event monitor for the Finit condition engine
|
/* User-defined condition event monitor for the Finit condition engine
|
||||||
*
|
*
|
||||||
* Copyright (c) 2021-2024 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (c) 2021-2025 Joachim Wiberg <troglobit@gmail.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -31,6 +31,7 @@
|
|||||||
#include "pid.h"
|
#include "pid.h"
|
||||||
#include "plugin.h"
|
#include "plugin.h"
|
||||||
#include "iwatch.h"
|
#include "iwatch.h"
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
static struct iwatch iw_usr;
|
static struct iwatch iw_usr;
|
||||||
|
|
||||||
@@ -108,7 +109,7 @@ static plugin_t plugin = {
|
|||||||
.depends = { "bootmisc", },
|
.depends = { "bootmisc", },
|
||||||
};
|
};
|
||||||
|
|
||||||
PLUGIN_INIT(plugin_init)
|
PLUGIN_INIT(__init)
|
||||||
{
|
{
|
||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
@@ -123,7 +124,7 @@ PLUGIN_INIT(plugin_init)
|
|||||||
plugin_register(&plugin);
|
plugin_register(&plugin);
|
||||||
}
|
}
|
||||||
|
|
||||||
PLUGIN_EXIT(plugin_exit)
|
PLUGIN_EXIT(__exit)
|
||||||
{
|
{
|
||||||
plugin_unregister(&plugin);
|
plugin_unregister(&plugin);
|
||||||
iwatch_exit(&iw_usr);
|
iwatch_exit(&iw_usr);
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/* Console setup (for X)
|
/* Console setup (for X)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2012-2024 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (c) 2012-2025 Joachim Wiberg <troglobit@gmail.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -33,6 +33,8 @@
|
|||||||
#include "finit.h"
|
#include "finit.h"
|
||||||
#include "helpers.h"
|
#include "helpers.h"
|
||||||
#include "plugin.h"
|
#include "plugin.h"
|
||||||
|
#include "conf.h"
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
static void setup(void *arg)
|
static void setup(void *arg)
|
||||||
{
|
{
|
||||||
@@ -50,12 +52,12 @@ static plugin_t plugin = {
|
|||||||
.hook[HOOK_SVC_PLUGIN] = { .cb = setup },
|
.hook[HOOK_SVC_PLUGIN] = { .cb = setup },
|
||||||
};
|
};
|
||||||
|
|
||||||
PLUGIN_INIT(plugin_init)
|
PLUGIN_INIT(__init)
|
||||||
{
|
{
|
||||||
plugin_register(&plugin);
|
plugin_register(&plugin);
|
||||||
}
|
}
|
||||||
|
|
||||||
PLUGIN_EXIT(plugin_exit)
|
PLUGIN_EXIT(__exit)
|
||||||
{
|
{
|
||||||
plugin_unregister(&plugin);
|
plugin_unregister(&plugin);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ logit
|
|||||||
reboot
|
reboot
|
||||||
runparts
|
runparts
|
||||||
sulogin
|
sulogin
|
||||||
|
tmpfiles
|
||||||
watchdogd
|
watchdogd
|
||||||
Makefile
|
Makefile
|
||||||
Makefile.in
|
Makefile.in
|
||||||
+7
-2
@@ -8,7 +8,8 @@ AM_LDFLAGS = -export-dynamic
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
sbin_PROGRAMS = finit initctl
|
sbin_PROGRAMS = finit initctl
|
||||||
pkglibexec_PROGRAMS = getty logit runparts
|
pkglibexec_PROGRAMS = getty logit runparts tmpfiles
|
||||||
|
|
||||||
if SULOGIN
|
if SULOGIN
|
||||||
pkglibexec_PROGRAMS += sulogin
|
pkglibexec_PROGRAMS += sulogin
|
||||||
endif
|
endif
|
||||||
@@ -43,6 +44,11 @@ sulogin_SOURCES = sulogin.c
|
|||||||
sulogin_CFLAGS = -W -Wall -Wextra -std=gnu99
|
sulogin_CFLAGS = -W -Wall -Wextra -std=gnu99
|
||||||
sulogin_LDADD = -lcrypt
|
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_SOURCES = logit.c logrotate.c
|
||||||
logit_CFLAGS = -W -Wall -Wextra -Wno-unused-parameter -std=gnu99
|
logit_CFLAGS = -W -Wall -Wextra -Wno-unused-parameter -std=gnu99
|
||||||
logit_CFLAGS += $(lite_CFLAGS)
|
logit_CFLAGS += $(lite_CFLAGS)
|
||||||
@@ -66,7 +72,6 @@ finit_SOURCES = api.c cgroup.c cgroup.h \
|
|||||||
sig.c sig.h \
|
sig.c sig.h \
|
||||||
sm.c sm.h \
|
sm.c sm.h \
|
||||||
svc.c svc.h \
|
svc.c svc.h \
|
||||||
tmpfiles.c tmpfiles.h \
|
|
||||||
tty.c tty.h \
|
tty.c tty.h \
|
||||||
util.c util.h \
|
util.c util.h \
|
||||||
utmp-api.c utmp-api.h
|
utmp-api.c utmp-api.h
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/* External client API, using UNIX domain socket.
|
/* External client API, using UNIX domain socket.
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2024 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (c) 2015-2025 Joachim Wiberg <troglobit@gmail.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -47,6 +47,7 @@
|
|||||||
#include "private.h"
|
#include "private.h"
|
||||||
#include "schedule.h"
|
#include "schedule.h"
|
||||||
#include "service.h"
|
#include "service.h"
|
||||||
|
#include "sm.h"
|
||||||
#include "sig.h"
|
#include "sig.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
@@ -59,26 +60,32 @@ static int call(int (*action)(svc_t *, void *), char *buf, size_t len)
|
|||||||
|
|
||||||
static int stop(svc_t *svc, void *user_data)
|
static int stop(svc_t *svc, void *user_data)
|
||||||
{
|
{
|
||||||
|
(void)user_data;
|
||||||
|
|
||||||
if (!svc)
|
if (!svc)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
service_timeout_cancel(svc);
|
service_timeout_cancel(svc);
|
||||||
svc_stop(svc);
|
svc_stop(svc);
|
||||||
service_step(svc);
|
service_step(svc);
|
||||||
service_step_all(SVC_TYPE_ANY);
|
if (!IS_RESERVED_RUNLEVEL(runlevel))
|
||||||
|
service_step_all(SVC_TYPE_ANY);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int start(svc_t *svc, void *user_data)
|
static int start(svc_t *svc, void *user_data)
|
||||||
{
|
{
|
||||||
|
(void)user_data;
|
||||||
|
|
||||||
if (!svc)
|
if (!svc)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
service_timeout_cancel(svc);
|
service_timeout_cancel(svc);
|
||||||
svc_start(svc);
|
svc_start(svc);
|
||||||
service_step(svc);
|
service_step(svc);
|
||||||
service_step_all(SVC_TYPE_ANY);
|
if (!IS_RESERVED_RUNLEVEL(runlevel))
|
||||||
|
service_step_all(SVC_TYPE_ANY);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -105,6 +112,8 @@ static int restart(svc_t *svc, void *user_data)
|
|||||||
|
|
||||||
static int reload(svc_t *svc, void *user_data)
|
static int reload(svc_t *svc, void *user_data)
|
||||||
{
|
{
|
||||||
|
(void)user_data;
|
||||||
|
|
||||||
if (!svc)
|
if (!svc)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
@@ -149,6 +158,8 @@ static int missing(char *job, char *id, void *user_data)
|
|||||||
{
|
{
|
||||||
char buf[20];
|
char buf[20];
|
||||||
|
|
||||||
|
(void)user_data;
|
||||||
|
|
||||||
if (!job)
|
if (!job)
|
||||||
job = "";
|
job = "";
|
||||||
if (!id)
|
if (!id)
|
||||||
@@ -228,6 +239,8 @@ struct wq emergency = { .cb = bypass_shutdown };
|
|||||||
|
|
||||||
static void bypass_shutdown(void *unused)
|
static void bypass_shutdown(void *unused)
|
||||||
{
|
{
|
||||||
|
(void)unused;
|
||||||
|
|
||||||
cprintf("TIMEOUT TIMEOUT SHUTTING DOWN NOW!!\n");
|
cprintf("TIMEOUT TIMEOUT SHUTTING DOWN NOW!!\n");
|
||||||
do_shutdown(halt);
|
do_shutdown(halt);
|
||||||
}
|
}
|
||||||
@@ -265,19 +278,19 @@ static int do_reboot(int cmd, int timeout, char *buf, size_t len)
|
|||||||
case INIT_CMD_REBOOT:
|
case INIT_CMD_REBOOT:
|
||||||
dbg("reboot");
|
dbg("reboot");
|
||||||
halt = SHUT_REBOOT;
|
halt = SHUT_REBOOT;
|
||||||
service_runlevel(6);
|
sm_runlevel(6);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case INIT_CMD_HALT:
|
case INIT_CMD_HALT:
|
||||||
dbg("halt");
|
dbg("halt");
|
||||||
halt = SHUT_HALT;
|
halt = SHUT_HALT;
|
||||||
service_runlevel(0);
|
sm_runlevel(0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case INIT_CMD_POWEROFF:
|
case INIT_CMD_POWEROFF:
|
||||||
dbg("poweroff");
|
dbg("poweroff");
|
||||||
halt = SHUT_OFF;
|
halt = SHUT_OFF;
|
||||||
service_runlevel(0);
|
sm_runlevel(0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case INIT_CMD_SUSPEND:
|
case INIT_CMD_SUSPEND:
|
||||||
@@ -306,7 +319,7 @@ typedef struct {
|
|||||||
} ev_t;
|
} ev_t;
|
||||||
|
|
||||||
ev_t ev_list[] = {
|
ev_t ev_list[] = {
|
||||||
{ "RELOAD", service_reload_dynamic },
|
{ "RELOAD", sm_reload },
|
||||||
{ NULL, NULL }
|
{ NULL, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -332,11 +345,19 @@ static void api_cb(uev_t *w, void *arg, int events)
|
|||||||
int sd, lvl;
|
int sd, lvl;
|
||||||
svc_t *svc;
|
svc_t *svc;
|
||||||
|
|
||||||
|
(void)arg;
|
||||||
|
|
||||||
if (UEV_ERROR == events) {
|
if (UEV_ERROR == events) {
|
||||||
dbg("%s(): api socket %d invalid.", __func__, w->fd);
|
dbg("%s(): api socket %d invalid.", __func__, w->fd);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TODO: refactor to use accept4() and a new uev handler for the
|
||||||
|
* client socket instead of risking blocking PID 1 if the client
|
||||||
|
* is misbehaving.
|
||||||
|
*/
|
||||||
|
// sd = accept4(w->fd, NULL, NULL, SOCK_NONBLOCK);
|
||||||
sd = accept(w->fd, NULL, NULL);
|
sd = accept(w->fd, NULL, NULL);
|
||||||
if (sd < 0) {
|
if (sd < 0) {
|
||||||
err(1, "Failed serving API request");
|
err(1, "Failed serving API request");
|
||||||
@@ -372,11 +393,6 @@ static void api_cb(uev_t *w, void *arg, int events)
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch (rq.cmd) {
|
switch (rq.cmd) {
|
||||||
case INIT_CMD_RELOAD:
|
|
||||||
case INIT_CMD_START_SVC:
|
|
||||||
case INIT_CMD_RESTART_SVC:
|
|
||||||
case INIT_CMD_STOP_SVC:
|
|
||||||
case INIT_CMD_RELOAD_SVC:
|
|
||||||
case INIT_CMD_REBOOT:
|
case INIT_CMD_REBOOT:
|
||||||
case INIT_CMD_HALT:
|
case INIT_CMD_HALT:
|
||||||
case INIT_CMD_POWEROFF:
|
case INIT_CMD_POWEROFF:
|
||||||
@@ -419,7 +435,7 @@ static void api_cb(uev_t *w, void *arg, int events)
|
|||||||
if (runlevel == INIT_LEVEL)
|
if (runlevel == INIT_LEVEL)
|
||||||
cfglevel = lvl;
|
cfglevel = lvl;
|
||||||
else
|
else
|
||||||
service_runlevel(lvl);
|
sm_runlevel(lvl);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@@ -434,8 +450,12 @@ static void api_cb(uev_t *w, void *arg, int events)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case INIT_CMD_RELOAD: /* 'init q' and 'initctl reload' */
|
case INIT_CMD_RELOAD: /* 'init q' and 'initctl reload' */
|
||||||
|
if (IS_RESERVED_RUNLEVEL(runlevel)) {
|
||||||
|
warnx("Ignoring reload in runlevel S and 6/0.");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
dbg("reload");
|
dbg("reload");
|
||||||
service_reload_dynamic();
|
sm_reload();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case INIT_CMD_START_SVC:
|
case INIT_CMD_START_SVC:
|
||||||
@@ -553,25 +573,11 @@ static void api_cb(uev_t *w, void *arg, int events)
|
|||||||
result = do_signal(rq.data, sizeof(rq.data), rq.runlevel);
|
result = do_signal(rq.data, sizeof(rq.data), rq.runlevel);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case INIT_CMD_NOTIFY_SOCKET:
|
|
||||||
svc = svc_find_by_pid(rq.runlevel);
|
|
||||||
if (!svc) {
|
|
||||||
errx(1, "Unknown PID, cannot register notify socket");
|
|
||||||
result = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (uev_io_init(ctx, &svc->notify_watcher, service_notify_cb, svc, sd, UEV_READ)) {
|
|
||||||
err(1, "Failed initializing %s readiness notifier", svc_ident(svc, NULL, 0));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return; /* Don't close sd, used for notify */
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
dbg("Unsupported cmd: %d", rq.cmd);
|
dbg("Unsupported cmd: %d", rq.cmd);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
done:
|
||||||
if (result)
|
if (result)
|
||||||
rq.cmd = INIT_CMD_NACK;
|
rq.cmd = INIT_CMD_NACK;
|
||||||
else
|
else
|
||||||
@@ -601,7 +607,7 @@ int api_init(uev_ctx_t *ctx)
|
|||||||
int sd;
|
int sd;
|
||||||
|
|
||||||
dbg("Setting up external API socket ...");
|
dbg("Setting up external API socket ...");
|
||||||
sd = socket(AF_UNIX, SOCK_SEQPACKET | SOCK_CLOEXEC, 0);
|
sd = socket(AF_UNIX, SOCK_SEQPACKET | SOCK_NONBLOCK | SOCK_CLOEXEC, 0);
|
||||||
if (-1 == sd) {
|
if (-1 == sd) {
|
||||||
err(1, "Failed starting external API socket");
|
err(1, "Failed starting external API socket");
|
||||||
return 1;
|
return 1;
|
||||||
|
|||||||
+11
-2
@@ -1,6 +1,6 @@
|
|||||||
/* Finit control group support functions
|
/* Finit control group support functions
|
||||||
*
|
*
|
||||||
* Copyright (c) 2019-2024 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (c) 2019-2025 Joachim Wiberg <troglobit@gmail.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -37,6 +37,8 @@
|
|||||||
#include "cgroup.h"
|
#include "cgroup.h"
|
||||||
#include "finit.h"
|
#include "finit.h"
|
||||||
#include "iwatch.h"
|
#include "iwatch.h"
|
||||||
|
#include "conf.h"
|
||||||
|
#include "service.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
@@ -86,6 +88,12 @@ static void cgset(const char *path, char *ctrl, char *prop)
|
|||||||
}
|
}
|
||||||
*val++ = 0;
|
*val++ = 0;
|
||||||
|
|
||||||
|
/* unquote value, if quoted */
|
||||||
|
if (unquote(&val, NULL)) {
|
||||||
|
errx(1, "Syntax error, unterminated quote in %s/%s.%s=%s", path, ctrl, prop, val);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* disallow sneaky relative paths */
|
/* disallow sneaky relative paths */
|
||||||
if (strstr(ctrl, "..") || strstr(prop, "..")) {
|
if (strstr(ctrl, "..") || strstr(prop, "..")) {
|
||||||
errx(1, "Possible security violation; '..' not allowed in cgroup config!");
|
errx(1, "Possible security violation; '..' not allowed in cgroup config!");
|
||||||
@@ -259,6 +267,7 @@ static void cgroup_events_cb(uev_t *w, void *arg, int events)
|
|||||||
ssize_t sz;
|
ssize_t sz;
|
||||||
size_t off;
|
size_t off;
|
||||||
|
|
||||||
|
(void)arg;
|
||||||
if (UEV_ERROR == events) {
|
if (UEV_ERROR == events) {
|
||||||
dbg("%s(): inotify socket %d invalid.", __func__, w->fd);
|
dbg("%s(): inotify socket %d invalid.", __func__, w->fd);
|
||||||
return;
|
return;
|
||||||
@@ -294,7 +303,7 @@ static void cgroup_events_cb(uev_t *w, void *arg, int events)
|
|||||||
|
|
||||||
#ifdef AUTO_RELOAD
|
#ifdef AUTO_RELOAD
|
||||||
if (conf_any_change())
|
if (conf_any_change())
|
||||||
service_reload_dynamic();
|
sm_reload();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
/* Finit control group support functions
|
/* Finit control group support functions
|
||||||
*
|
*
|
||||||
* Copyright (c) 2019-2024 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (c) 2019-2025 Joachim Wiberg <troglobit@gmail.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|||||||
+65
-46
@@ -1,6 +1,6 @@
|
|||||||
/* New client tool, replaces old /dev/initctl API and telinit tool
|
/* New client tool, replaces old /dev/initctl API and telinit tool
|
||||||
*
|
*
|
||||||
* Copyright (c) 2019-2024 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (c) 2019-2025 Joachim Wiberg <troglobit@gmail.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -58,73 +58,90 @@ int cgroup_avail(void)
|
|||||||
return fismnt(FINIT_CGPATH);
|
return fismnt(FINIT_CGPATH);
|
||||||
}
|
}
|
||||||
|
|
||||||
char *pid_cmdline(int pid, char *buf, size_t len)
|
static size_t flen(FILE *fp)
|
||||||
{
|
{
|
||||||
size_t i, sz;
|
size_t total = 0, sz;
|
||||||
char *ptr;
|
char buf[512];
|
||||||
|
|
||||||
|
while ((sz = fread(buf, 1, sizeof(buf), fp)) > 0)
|
||||||
|
total += sz;
|
||||||
|
rewind(fp);
|
||||||
|
|
||||||
|
return total;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *pid_cmdline(int pid)
|
||||||
|
{
|
||||||
|
size_t i, len;
|
||||||
|
char *buf;
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
|
|
||||||
fp = fopenf("r", "/proc/%d/cmdline", pid);
|
fp = fopenf("r", "/proc/%d/cmdline", pid);
|
||||||
if (!fp) {
|
if (!fp)
|
||||||
buf[0] = 0;
|
return strdup(""); /* regular process */
|
||||||
return buf;
|
|
||||||
}
|
|
||||||
|
|
||||||
sz = fread(buf, sizeof(buf[0]), len - 1, fp);
|
len = flen(fp);
|
||||||
fclose(fp);
|
if (len == 0) {
|
||||||
if (!sz)
|
fail:
|
||||||
|
fclose(fp);
|
||||||
return NULL; /* kernel thread */
|
return NULL; /* kernel thread */
|
||||||
|
|
||||||
buf[sz] = 0;
|
|
||||||
|
|
||||||
ptr = strchr(buf, 0);
|
|
||||||
if (ptr && ptr != buf) {
|
|
||||||
ptr++;
|
|
||||||
sz -= ptr - buf;
|
|
||||||
memmove(buf, ptr, sz + 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < sz; i++) {
|
buf = calloc(len + 1, 1);
|
||||||
if (buf[i] == 0)
|
if (!buf)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
if (fread(buf, 1, len, fp) < len) {
|
||||||
|
free(buf);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* replace all NUL chars with space */
|
||||||
|
for (i = 0; i < len; i++) {
|
||||||
|
if (buf[i] == '\0')
|
||||||
buf[i] = ' ';
|
buf[i] = ' ';
|
||||||
}
|
}
|
||||||
|
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *pid_comm(int pid, char *buf, size_t len)
|
char *pid_cgroup(int pid)
|
||||||
{
|
{
|
||||||
char *ptr = NULL;
|
char *buf, *ptr = NULL;
|
||||||
FILE *fp;
|
size_t len;
|
||||||
|
|
||||||
fp = fopenf("r", "/proc/%d/comm", pid);
|
|
||||||
if (!fp)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
if (fgets(buf, len, fp))
|
|
||||||
ptr = chomp(buf);
|
|
||||||
fclose(fp);
|
|
||||||
|
|
||||||
return ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
char *pid_cgroup(int pid, char *buf, size_t len)
|
|
||||||
{
|
|
||||||
char *ptr = NULL;
|
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
|
|
||||||
fp = fopenf("r", "/proc/%d/cgroup", pid);
|
fp = fopenf("r", "/proc/%d/cgroup", pid);
|
||||||
if (!fp)
|
if (!fp)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
len = flen(fp);
|
||||||
|
if (len == 0) {
|
||||||
|
fclose(fp);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
len++;
|
||||||
|
|
||||||
|
buf = calloc(1, len);
|
||||||
|
if (!buf) {
|
||||||
|
fclose(fp);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (fgets(buf, len, fp))
|
if (fgets(buf, len, fp))
|
||||||
ptr = chomp(buf);
|
ptr = chomp(buf);
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
|
|
||||||
if (ptr)
|
if (ptr) {
|
||||||
ptr = strchr(buf, '/');
|
ptr = strchr(ptr, '/');
|
||||||
|
if (ptr) {
|
||||||
|
memmove(buf, ptr, strlen(ptr) + 1);
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return ptr;
|
free(buf);
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *cgroup_val(char *path, char *file, char *buf, size_t len)
|
static char *cgroup_val(char *path, char *file, char *buf, size_t len)
|
||||||
@@ -423,7 +440,7 @@ int cgroup_tree(char *path, char *pfx, int mode, int pos)
|
|||||||
|
|
||||||
i = 0;
|
i = 0;
|
||||||
while (fgets(buf, sizeof(buf), fp)) {
|
while (fgets(buf, sizeof(buf), fp)) {
|
||||||
char comm[80] = { 0 };
|
char *cmdline;
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
|
|
||||||
pid = atoi(chomp(buf));
|
pid = atoi(chomp(buf));
|
||||||
@@ -431,8 +448,8 @@ int cgroup_tree(char *path, char *pfx, int mode, int pos)
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* skip kernel threads for now (no cmdline) */
|
/* skip kernel threads for now (no cmdline) */
|
||||||
pid_comm(pid, comm, sizeof(comm));
|
cmdline = pid_cmdline(pid);
|
||||||
if (pid_cmdline(pid, buf, sizeof(buf))) {
|
if (cmdline) {
|
||||||
char proc[ttcols];
|
char proc[ttcols];
|
||||||
|
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
@@ -450,7 +467,7 @@ int cgroup_tree(char *path, char *pfx, int mode, int pos)
|
|||||||
strlcat(row, pfx, rplen);
|
strlcat(row, pfx, rplen);
|
||||||
strlcat(row, ++i == num ? END : FORK, rlen);
|
strlcat(row, ++i == num ? END : FORK, rlen);
|
||||||
|
|
||||||
snprintf(proc, sizeof(proc), " %d %s %s", pid, comm, buf);
|
snprintf(proc, sizeof(proc), " %d %s", pid, cmdline);
|
||||||
|
|
||||||
if (plain) {
|
if (plain) {
|
||||||
strlcat(row, proc, rplen);
|
strlcat(row, proc, rplen);
|
||||||
@@ -468,6 +485,8 @@ int cgroup_tree(char *path, char *pfx, int mode, int pos)
|
|||||||
}
|
}
|
||||||
|
|
||||||
puts(row);
|
puts(row);
|
||||||
|
|
||||||
|
free(cmdline);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mode == 1) {
|
if (mode == 1) {
|
||||||
|
|||||||
+3
-4
@@ -1,6 +1,6 @@
|
|||||||
/* Cgroup utility functions for initctl
|
/* Cgroup utility functions for initctl
|
||||||
*
|
*
|
||||||
* Copyright (c) 2019-2024 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (c) 2019-2025 Joachim Wiberg <troglobit@gmail.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -54,9 +54,8 @@ struct cg {
|
|||||||
|
|
||||||
int cgroup_avail(void);
|
int cgroup_avail(void);
|
||||||
|
|
||||||
char *pid_cmdline (int pid, char *buf, size_t len);
|
char *pid_cmdline (int pid);
|
||||||
char *pid_comm (int pid, char *buf, size_t len);
|
char *pid_cgroup (int pid);
|
||||||
char *pid_cgroup (int pid, char *buf, size_t len);
|
|
||||||
|
|
||||||
uint64_t cgroup_memory(char *group);
|
uint64_t cgroup_memory(char *group);
|
||||||
|
|
||||||
|
|||||||
+1
-11
@@ -1,6 +1,6 @@
|
|||||||
/* External client API, using UNIX domain socket.
|
/* External client API, using UNIX domain socket.
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2024 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (c) 2015-2025 Joachim Wiberg <troglobit@gmail.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -97,16 +97,6 @@ int client_request(struct init_request *rq, ssize_t len)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Exception, only command that don't need to wait for a
|
|
||||||
* response from Finit. Registers the client socket as a
|
|
||||||
* readiness notification socket with Finit
|
|
||||||
*/
|
|
||||||
if (rq->cmd == INIT_CMD_NOTIFY_SOCKET) {
|
|
||||||
rq->cmd = INIT_CMD_ACK;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
pfd.fd = sd;
|
pfd.fd = sd;
|
||||||
pfd.events = POLLIN | POLLERR | POLLHUP;
|
pfd.events = POLLIN | POLLERR | POLLHUP;
|
||||||
if ((rc = poll(&pfd, 1, REQUEST_TIMEOUT)) <= 0) {
|
if ((rc = poll(&pfd, 1, REQUEST_TIMEOUT)) <= 0) {
|
||||||
|
|||||||
Loaded 100 of 194 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user