mirror of
https://github.com/troglobit/finit.git
synced 2026-10-13 10:14:47 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
70a44d3860 | ||
|
|
f29a3db86c | ||
|
|
f6b394e0a2 | ||
|
|
ccaa4caf48 | ||
|
|
77d199f1a4 | ||
|
|
0448151c0a | ||
|
|
75739fbeef | ||
|
|
3a72d1263c | ||
|
|
7e2b154f9b | ||
|
|
547e59b2ad | ||
|
|
7f37d0c4e9 | ||
|
|
dd77f63ad3 | ||
|
|
e0f9df1f27 | ||
|
|
b56ffc155e | ||
|
|
4596e27eb0 | ||
|
|
a3eac3a85e | ||
|
|
7d09e34b80 | ||
|
|
3febc7d513 | ||
|
|
309ad1bea7 | ||
|
|
30f2ca3b2e | ||
|
|
4a53f610cd | ||
|
|
e74dff96ba | ||
|
|
9ed4407b20 | ||
|
|
eb913e8bf2 | ||
|
|
17d04779fb | ||
|
|
ab661423ba | ||
|
|
8e77ea68b2 | ||
|
|
b0e672bc9a | ||
|
|
ad76e15949 | ||
|
|
b8735cc893 | ||
|
|
c058b3f9ce | ||
|
|
8f6c61606a | ||
|
|
96f944b816 | ||
|
|
a81530754b | ||
|
|
1518eb9466 | ||
|
|
50b9e46e19 | ||
|
|
c01faef99b | ||
|
|
4867b7268b | ||
|
|
662293e194 | ||
|
|
4ce810cc1f | ||
|
|
184c079c08 | ||
|
|
17c6791c70 | ||
|
|
42f24f5af5 | ||
|
|
cef5049bf0 | ||
|
|
ec251f1ce1 | ||
|
|
98ec30d308 | ||
|
|
e1fe870aaf | ||
|
|
f04fce544d | ||
|
|
7aa9ed5982 | ||
|
|
a1a92a04bd | ||
|
|
804f655d87 | ||
|
|
2c78e7429a | ||
|
|
d77f0127b4 | ||
|
|
4253d0de25 | ||
|
|
d47181a4a7 | ||
|
|
8642007d0e | ||
|
|
96c74ed48b | ||
|
|
03a14bcaa5 | ||
|
|
4bb2c33859 | ||
|
|
ab81272083 | ||
|
|
1fbf03bc1e | ||
|
|
92a2861b1c | ||
|
|
922714780a | ||
|
|
b206c3d655 | ||
|
|
109d8826bd | ||
|
|
60478106eb | ||
|
|
0de9cfb020 | ||
|
|
0b182c063e | ||
|
|
f0914f6d32 | ||
|
|
7090321ff3 | ||
|
|
266f1132a4 | ||
|
|
5f7e8457af | ||
|
|
a215747355 | ||
|
|
dacda5ab5d | ||
|
|
39044adcf8 | ||
|
|
9396cd1d26 | ||
|
|
c9fd4418e7 | ||
|
|
7206f745a2 | ||
|
|
25bcde12d4 | ||
|
|
7459ede806 | ||
|
|
6bf35513c3 | ||
|
|
0b8d39329a | ||
|
|
84098dd8b7 | ||
|
|
c4463ec64f | ||
|
|
6f1808248e | ||
|
|
29029bb78f | ||
|
|
bbe588ac16 | ||
|
|
34bf9a7776 | ||
|
|
bb111f98fc | ||
|
|
c7faf4f9e2 | ||
|
|
18774539c0 | ||
|
|
abaad560f0 | ||
|
|
0ef325d86c | ||
|
|
2c94f4e45f | ||
|
|
da184e7922 | ||
|
|
1e93fc1671 | ||
|
|
8e7d1b7bb5 | ||
|
|
373738f3d1 | ||
|
|
e6d3eb2526 | ||
|
|
d7fd5bc902 | ||
|
|
3f98220d5d | ||
|
|
0ca509a42e | ||
|
|
d17144d16f | ||
|
|
a608c5a5c9 | ||
|
|
9b44b99480 | ||
|
|
ad225156f1 | ||
|
|
eb92a915d3 | ||
|
|
69a4f2c115 | ||
|
|
9ce95fe8c0 | ||
|
|
06889cc014 | ||
|
|
329f11b4da | ||
|
|
ce40e2b9d2 | ||
|
|
d0176612c9 | ||
|
|
21753e26dd | ||
|
|
0dc2513b32 | ||
|
|
d16bfa789b | ||
|
|
0b27778c96 | ||
|
|
3e25297e3c | ||
|
|
6560968c8b | ||
|
|
c9a3c5c885 | ||
|
|
a2d45e8f5e | ||
|
|
f6c69eb108 | ||
|
|
f0032ab6b7 | ||
|
|
53c5d0e55a | ||
|
|
7c8ab7915f | ||
|
|
12f7855a78 | ||
|
|
bcc3360b53 | ||
|
|
d3408d14a8 | ||
|
|
804060444a | ||
|
|
de544a5b36 | ||
|
|
0d48d1df49 | ||
|
|
b46592e818 | ||
|
|
22bc218c84 | ||
|
|
702a606d26 | ||
|
|
a3d9b6e9b1 | ||
|
|
390a0f48c1 | ||
|
|
f4a13687e8 | ||
|
|
43ca51c3b1 | ||
|
|
864b71af14 | ||
|
|
44a928e5e6 | ||
|
|
f513348963 | ||
|
|
820b9a77c1 | ||
|
|
85baafe99c | ||
|
|
e635ea882a | ||
|
|
f908c8d43a | ||
|
|
308f75b209 | ||
|
|
d87d298c85 | ||
|
|
ae7931f68e | ||
|
|
8422d2715c | ||
|
|
2eefaa5db6 | ||
|
|
fb0ad18d3a | ||
|
|
2681444b07 | ||
|
|
dd36116a97 | ||
|
|
e756d6f8ac | ||
|
|
567c695954 | ||
|
|
4877aecc1e | ||
|
|
65644f5956 | ||
|
|
a02760f499 | ||
|
|
7aab3bb421 | ||
|
|
b5beb2b8d4 | ||
|
|
09b4aee5bc | ||
|
|
d9a0c2dce9 | ||
|
|
178301baf2 | ||
|
|
4e18affa9b | ||
|
|
21f40fb95e | ||
|
|
24f0cee49a | ||
|
|
fee38d4359 | ||
|
|
0c85ea844a | ||
|
|
c3839edc40 | ||
|
|
be2a0ec3e7 | ||
|
|
c23952cd9e | ||
|
|
13a8f56b46 | ||
|
|
927acdbd7e | ||
|
|
6f6267f3b3 | ||
|
|
dec89d4054 | ||
|
|
193e114596 | ||
|
|
1be67c434e | ||
|
|
4f8dab75b2 | ||
|
|
37d063fd3b | ||
|
|
97be3da126 | ||
|
|
e7f97f8264 | ||
|
|
6415aeebac | ||
|
|
e69200ea43 | ||
|
|
26d5018224 | ||
|
|
1b7699ca93 | ||
|
|
8eab099f09 | ||
|
|
c7c5426586 | ||
|
|
85484178e0 | ||
|
|
e958189e6a | ||
|
|
eb13309a34 | ||
|
|
4f01856313 | ||
|
|
2aa9e5bad6 | ||
|
|
b897c62a73 | ||
|
|
6c133e85f2 | ||
|
|
d30959e909 | ||
|
|
2badd840fa | ||
|
|
e00476250f | ||
|
|
c3f758de96 | ||
|
|
29761b69ea | ||
|
|
e08d56af71 | ||
|
|
a370ddc3c0 | ||
|
|
8377f0e736 | ||
|
|
f42a1fd356 | ||
|
|
ab82e6f696 | ||
|
|
cd0ddd6bfc | ||
|
|
31b78817dd | ||
|
|
5599aca0a3 | ||
|
|
d77773d8ee | ||
|
|
efadbb0694 | ||
|
|
de4be1557b | ||
|
|
a73e02afac | ||
|
|
a3c5dfd543 | ||
|
|
4c208c18e2 | ||
|
|
0a9ac65609 | ||
|
|
167d75ac4a | ||
|
|
0cd51fb7d3 | ||
|
|
bf2c0542ca | ||
|
|
0bef874cf3 | ||
|
|
eadd01da1f | ||
|
|
80b0750523 | ||
|
|
4525aec118 | ||
|
|
61be1ef880 | ||
|
|
a7428ababa | ||
|
|
b4b7ee1b71 | ||
|
|
ff91d5c836 | ||
|
|
d652211621 | ||
|
|
9f95934df9 | ||
|
|
261d604ea3 | ||
|
|
085fc4c660 | ||
|
|
ce7d4cebab | ||
|
|
d5a47e2d8b | ||
|
|
020eefe732 | ||
|
|
14336bd407 | ||
|
|
bb841383b8 | ||
|
|
e49763d834 | ||
|
|
57545e1ab0 | ||
|
|
7ad802b092 | ||
|
|
e319a606b8 | ||
|
|
7d434b1eaa | ||
|
|
58d48b54b3 | ||
|
|
7d4603e13b | ||
|
|
d0c5d7be5b | ||
|
|
db840bdc19 | ||
|
|
3df3c51dae | ||
|
|
d37d241647 | ||
|
|
b18b21830a | ||
|
|
06daf2e4a5 | ||
|
|
eb13ccc227 | ||
|
|
0861373d14 | ||
|
|
1b9e69414e | ||
|
|
39f4aa3f2c | ||
|
|
dedb56a9d0 | ||
|
|
a27903c745 | ||
|
|
f24f76fc80 | ||
|
|
d95fc5f790 | ||
|
|
10a1257e47 | ||
|
|
a7b8e1b94d | ||
|
|
da83462731 | ||
|
|
1396177706 | ||
|
|
7cf0a293fd | ||
|
|
d0d9b83b66 | ||
|
|
76f8a18816 | ||
|
|
dc497bcd57 | ||
|
|
0da6bbe4a8 | ||
|
|
91f7a75bee | ||
|
|
f217d493b4 | ||
|
|
77404a2ea0 | ||
|
|
d42a1d438b | ||
|
|
1275f05343 | ||
|
|
61a92aa0b6 | ||
|
|
b38ff0cc79 | ||
|
|
168f5bf1d8 | ||
|
|
ffd00f646c | ||
|
|
5e2e273cad | ||
|
|
33f6697cd5 | ||
|
|
6f0ba22a0f | ||
|
|
ecb690c9ec | ||
|
|
0459bb432a | ||
|
|
2760616c73 | ||
|
|
62ab990129 | ||
|
|
0c2836d747 | ||
|
|
8be7a462e0 | ||
|
|
5993b4bb5d | ||
|
|
2957246092 | ||
|
|
a5710125f6 | ||
|
|
ff95ebeb91 | ||
|
|
1921b3f2c5 | ||
|
|
051ef81e53 | ||
|
|
90993c237a | ||
|
|
b0b4f7b2ba | ||
|
|
4d79d84fb8 | ||
|
|
d318aa00c3 | ||
|
|
9684127eb7 | ||
|
|
8d2cfd69fa | ||
|
|
4f252858e4 | ||
|
|
1ccd1d6926 | ||
|
|
b87c51209d | ||
|
|
6b7478ff43 | ||
|
|
6c4c16cbdb | ||
|
|
e539dbfe37 | ||
|
|
90c6bcd365 | ||
|
|
c9c268f218 | ||
|
|
3feff37ba5 | ||
|
|
c67d15e272 | ||
|
|
8984c655f8 | ||
|
|
1a7b26bac3 | ||
|
|
1f47718012 | ||
|
|
fa13cddc28 | ||
|
|
185a72bd14 | ||
|
|
cd32c623cf | ||
|
|
ac4b9c2f93 | ||
|
|
5e9591d0a8 | ||
|
|
e3bcf9bf16 | ||
|
|
84fd3196b0 | ||
|
|
994e51e34f | ||
|
|
0a7814b391 | ||
|
|
73f72b39cf | ||
|
|
02e0aa7383 | ||
|
|
6528628b5c | ||
|
|
1480657982 | ||
|
|
33e378a345 | ||
|
|
b695b46a9d | ||
|
|
0e61ed727f | ||
|
|
e9d60a6c04 | ||
|
|
5e9edf9deb | ||
|
|
8ed2751ae1 | ||
|
|
7fec66dc09 | ||
|
|
75fa868a4b | ||
|
|
7b321de339 | ||
|
|
1691ebb292 |
No files matched your search
@@ -24,7 +24,8 @@ the maintainer(s) and make it easier for them to include your code.
|
|||||||
Coding Style
|
Coding Style
|
||||||
------------
|
------------
|
||||||
|
|
||||||
> **Tip:** Always submit code that follows the style of surrounding code!
|
> [!TIP]
|
||||||
|
> Always submit code that follows the style of surrounding code!
|
||||||
|
|
||||||
First of all, lines are allowed to be longer than 72 characters these
|
First of all, lines are allowed to be longer than 72 characters these
|
||||||
days. In fact, there exist no enforced maximum, but keeping it around
|
days. In fact, there exist no enforced maximum, but keeping it around
|
||||||
|
|||||||
+1
-1
@@ -5,7 +5,7 @@
|
|||||||
finit is a small project, as such we have no possibility to support older versions.
|
finit is a small project, as such we have no possibility to support older versions.
|
||||||
The only supported version is the latest released on GitHub:
|
The only supported version is the latest released on GitHub:
|
||||||
|
|
||||||
<https://github.com/troglobit/finit/releases>
|
<https://github.com/finit-project/finit/releases>
|
||||||
|
|
||||||
## Reporting a Vulnerability
|
## Reporting a Vulnerability
|
||||||
|
|
||||||
|
|||||||
+31
-14
@@ -1,15 +1,22 @@
|
|||||||
name: Bob the Builder
|
name: Bob the Builder
|
||||||
|
|
||||||
# Run on all branches, including all pull requests, except the 'dev'
|
# Run on push to release branches (master and maintenance N.x), and
|
||||||
# branch since that's where we run Coverity Scan (limited tokens/day)
|
# on all pull requests. The 'dev' branch is where we run Coverity
|
||||||
|
# Scan (limited tokens/day)
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- '**'
|
- master
|
||||||
- '!dev'
|
- '[0-9]+.x'
|
||||||
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:
|
||||||
@@ -26,20 +33,29 @@ jobs:
|
|||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: |
|
run: |
|
||||||
sudo apt-get -y update
|
sudo apt-get -y update
|
||||||
sudo apt-get -y install pkg-config tree jq libuev-dev libite-dev
|
sudo apt-get -y install pkg-config tree jq libcap-dev
|
||||||
- uses: actions/checkout@v4
|
sudo apt-get -y install pkg-config
|
||||||
|
wget https://github.com/troglobit/libuev/releases/download/v2.4.1/libuev-2.4.1.tar.xz
|
||||||
|
wget https://github.com/troglobit/libite/releases/download/v2.6.2/libite-2.6.2.tar.gz
|
||||||
|
tar xf libuev-2.4.1.tar.xz
|
||||||
|
tar xf libite-2.6.2.tar.gz
|
||||||
|
(cd libuev-2.4.1 && ./configure && make -j9 && sudo make install-strip)
|
||||||
|
(cd libite-2.6.2 && ./configure && make -j9 && sudo make install-strip)
|
||||||
|
sudo ldconfig
|
||||||
|
- uses: actions/checkout@v7
|
||||||
- name: Static Finit
|
- name: Static Finit
|
||||||
run: |
|
run: |
|
||||||
./autogen.sh
|
./autogen.sh
|
||||||
./configure --prefix= --enable-static
|
./configure --prefix= --enable-static
|
||||||
make -j3 V=1
|
make -j9 V=1
|
||||||
- name: Regular Finit
|
- name: Regular Finit
|
||||||
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 \
|
||||||
make -j3 clean
|
CFLAGS="-fsanitize=address -ggdb"
|
||||||
make -j3 V=1
|
make -j9 clean
|
||||||
|
make -j9 V=1
|
||||||
- name: Install to /tmp
|
- name: Install to /tmp
|
||||||
run: |
|
run: |
|
||||||
DESTDIR=/tmp make install-strip
|
DESTDIR=/tmp make install-strip
|
||||||
@@ -61,9 +77,10 @@ jobs:
|
|||||||
sudo sysctl kernel.apparmor_restrict_unprivileged_userns=0
|
sudo sysctl kernel.apparmor_restrict_unprivileged_userns=0
|
||||||
- name: Run Unit Tests
|
- name: Run Unit Tests
|
||||||
run: |
|
run: |
|
||||||
make check || (cat test/test-suite.log; false)
|
make -j1 check || (cat test/test-suite.log; false)
|
||||||
- name: Upload Test Results
|
- name: Upload Test Results
|
||||||
uses: actions/upload-artifact@v4
|
if: always()
|
||||||
|
uses: actions/upload-artifact@v7
|
||||||
with:
|
with:
|
||||||
name: finit-test-${{ matrix.compiler }}
|
name: finit-test-${{ matrix.compiler }}
|
||||||
path: test/*.log
|
path: test/*.log
|
||||||
@@ -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
|
||||||
@@ -16,7 +19,7 @@ jobs:
|
|||||||
coverity:
|
coverity:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v7
|
||||||
- name: Fetch latest Coverity Scan MD5
|
- name: Fetch latest Coverity Scan MD5
|
||||||
id: var
|
id: var
|
||||||
env:
|
env:
|
||||||
@@ -26,7 +29,7 @@ jobs:
|
|||||||
--post-data "token=$TOKEN&project=${COVERITY_PROJ}&md5=1" \
|
--post-data "token=$TOKEN&project=${COVERITY_PROJ}&md5=1" \
|
||||||
-O coverity-latest.tar.gz.md5
|
-O coverity-latest.tar.gz.md5
|
||||||
echo "md5=$(cat coverity-latest.tar.gz.md5)" | tee -a $GITHUB_OUTPUT
|
echo "md5=$(cat coverity-latest.tar.gz.md5)" | tee -a $GITHUB_OUTPUT
|
||||||
- uses: actions/cache@v4
|
- uses: actions/cache@v6
|
||||||
id: cache
|
id: cache
|
||||||
with:
|
with:
|
||||||
path: coverity-latest.tar.gz
|
path: coverity-latest.tar.gz
|
||||||
@@ -52,18 +55,19 @@ jobs:
|
|||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: |
|
run: |
|
||||||
sudo apt-get -y update
|
sudo apt-get -y update
|
||||||
sudo apt-get -y install pkg-config
|
sudo apt-get -y install pkg-config libcap-dev
|
||||||
wget https://github.com/troglobit/libuev/releases/download/v2.4.0/libuev-2.4.0.tar.xz
|
wget https://github.com/troglobit/libuev/releases/download/v2.4.1/libuev-2.4.1.tar.xz
|
||||||
wget https://github.com/troglobit/libite/releases/download/v2.5.2/libite-2.5.2.tar.gz
|
wget https://github.com/troglobit/libite/releases/download/v2.6.2/libite-2.6.2.tar.gz
|
||||||
tar xf libuev-2.4.0.tar.xz
|
tar xf libuev-2.4.1.tar.xz
|
||||||
tar xf libite-2.5.2.tar.gz
|
tar xf libite-2.6.2.tar.gz
|
||||||
(cd libuev-2.4.0 && ./configure --prefix=/usr && make && sudo make install-strip)
|
(cd libuev-2.4.1 && ./configure && make -j9 && sudo make install-strip)
|
||||||
(cd libite-2.5.2 && ./configure --prefix=/usr && make && sudo make install-strip)
|
(cd libite-2.6.2 && ./configure && make -j9 && sudo make install-strip)
|
||||||
sudo ldconfig
|
sudo ldconfig
|
||||||
- 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
|
||||||
@@ -82,7 +86,7 @@ jobs:
|
|||||||
--form description="${PROJECT_NAME} $(git rev-parse HEAD)" \
|
--form description="${PROJECT_NAME} $(git rev-parse HEAD)" \
|
||||||
https://scan.coverity.com/builds?project=${COVERITY_PROJ}
|
https://scan.coverity.com/builds?project=${COVERITY_PROJ}
|
||||||
- name: Upload build.log
|
- name: Upload build.log
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v7
|
||||||
with:
|
with:
|
||||||
name: coverity-build.log
|
name: coverity-build.log
|
||||||
path: cov-int/build-log.txt
|
path: cov-int/build-log.txt
|
||||||
@@ -0,0 +1,163 @@
|
|||||||
|
name: Dotty the Documenteer
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
- '[0-9]+.x'
|
||||||
|
paths:
|
||||||
|
- 'doc/**'
|
||||||
|
- 'README.md'
|
||||||
|
- 'mkdocs.yml'
|
||||||
|
- 'configure.ac'
|
||||||
|
- '.github/workflows/docs.yml'
|
||||||
|
pull_request:
|
||||||
|
types: [opened, synchronize, reopened, labeled]
|
||||||
|
paths:
|
||||||
|
- 'doc/**'
|
||||||
|
- 'README.md'
|
||||||
|
- 'mkdocs.yml'
|
||||||
|
- 'configure.ac'
|
||||||
|
- '.github/workflows/docs.yml'
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
outputs:
|
||||||
|
version: ${{ steps.version.outputs.version }}
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v7
|
||||||
|
with:
|
||||||
|
fetch-depth: 0 # Needed for git-revision-date-localized plugin
|
||||||
|
|
||||||
|
- name: Determine docs version
|
||||||
|
id: version
|
||||||
|
run: |
|
||||||
|
version=$(sed -n 's/^AC_INIT(\[Finit\], *\[\([0-9]*\)\..*/\1.x/p' configure.ac)
|
||||||
|
test -n "$version"
|
||||||
|
echo "version=$version" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
|
- name: Setup Python
|
||||||
|
uses: actions/setup-python@v7
|
||||||
|
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
|
||||||
|
pipx inject mkdocs mkdocs-glightbox
|
||||||
|
|
||||||
|
- name: Build documentation
|
||||||
|
run: mkdocs build --clean
|
||||||
|
|
||||||
|
- name: Upload site artifact
|
||||||
|
uses: actions/upload-artifact@v7
|
||||||
|
with:
|
||||||
|
name: site
|
||||||
|
path: site/
|
||||||
|
|
||||||
|
deploy:
|
||||||
|
if: github.event_name == 'push'
|
||||||
|
needs: build
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
env:
|
||||||
|
VERSION: ${{ needs.build.outputs.version }}
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Download site artifact
|
||||||
|
uses: actions/download-artifact@v8
|
||||||
|
with:
|
||||||
|
name: site
|
||||||
|
path: site/
|
||||||
|
|
||||||
|
- name: Checkout pages repo
|
||||||
|
uses: actions/checkout@v7
|
||||||
|
with:
|
||||||
|
repository: finit-project/finit-project.github.io
|
||||||
|
path: pages
|
||||||
|
ssh-key: ${{ secrets.DOCS_DEPLOY_KEY }}
|
||||||
|
persist-credentials: true
|
||||||
|
|
||||||
|
- name: Setup SSH for push
|
||||||
|
run: |
|
||||||
|
mkdir -p ~/.ssh
|
||||||
|
chmod 700 ~/.ssh
|
||||||
|
ssh-keyscan github.com >> ~/.ssh/known_hosts
|
||||||
|
|
||||||
|
- name: Sync site to pages repo
|
||||||
|
run: |
|
||||||
|
rsync -a --delete site/ "pages/$VERSION/"
|
||||||
|
|
||||||
|
- name: Update version index and redirects
|
||||||
|
run: |
|
||||||
|
cd pages/
|
||||||
|
|
||||||
|
# The root holds only version directories and the files
|
||||||
|
# generated below, drop anything else (pre-versioned site)
|
||||||
|
find . -maxdepth 1 ! -name . ! -name .git ! -name CNAME \
|
||||||
|
! -name '[0-9]*.x' -exec rm -rf {} +
|
||||||
|
|
||||||
|
latest=$(ls -d [0-9]*.x | sort -rV | head -1)
|
||||||
|
|
||||||
|
sep=
|
||||||
|
printf '[' > versions.json
|
||||||
|
for v in $(ls -d [0-9]*.x | sort -rV); do
|
||||||
|
printf '%s{"version": "%s", "title": "%s", "aliases": []}' \
|
||||||
|
"$sep" "$v" "$v" >> versions.json
|
||||||
|
sep=', '
|
||||||
|
done
|
||||||
|
printf ']\n' >> versions.json
|
||||||
|
|
||||||
|
cat > index.html <<EOF
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta http-equiv="refresh" content="0; url=$latest/">
|
||||||
|
<link rel="canonical" href="https://finit-project.github.io/$latest/">
|
||||||
|
</head>
|
||||||
|
</html>
|
||||||
|
EOF
|
||||||
|
|
||||||
|
cat > 404.html <<EOF
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Finit — page not found</title>
|
||||||
|
<script>
|
||||||
|
var path = window.location.pathname;
|
||||||
|
if (!/^\/[0-9]+\.x(\/|$)/.test(path))
|
||||||
|
window.location.replace("/$latest" + path);
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<p>Page not found. Try the <a href="/$latest/">latest User Guide</a>.</p>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
EOF
|
||||||
|
|
||||||
|
- name: Commit and push
|
||||||
|
run: |
|
||||||
|
cd pages/
|
||||||
|
if [ -z "$(git status --porcelain)" ]; then
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
SRC_REPO="${GITHUB_REPOSITORY}"
|
||||||
|
SRC_REF="${GITHUB_SHA::7}"
|
||||||
|
SRC_URL="https://github.com/${SRC_REPO}/commit/${SRC_REF}"
|
||||||
|
|
||||||
|
git config user.name "GitHub Actions"
|
||||||
|
git config user.email "actions@github.com"
|
||||||
|
git add -A
|
||||||
|
git commit -m "docs: update from ${SRC_REPO}@${SRC_REF}" \
|
||||||
|
-m "For details, see ${SRC_URL}"
|
||||||
|
git push
|
||||||
@@ -5,30 +5,43 @@ 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
|
||||||
if: startsWith(github.ref, 'refs/tags/')
|
if: startsWith(github.ref, 'refs/tags/')
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
env:
|
|
||||||
MAKEFLAGS: -j3
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v7
|
||||||
- name: Installing dependencies ...
|
- name: Installing dependencies ...
|
||||||
run: |
|
run: |
|
||||||
sudo apt-get -y update
|
sudo apt-get -y update
|
||||||
sudo apt-get -y install pkg-config jq libuev-dev libite-dev
|
sudo apt-get -y install pkg-config jq libcap-dev
|
||||||
|
wget https://github.com/troglobit/libuev/releases/download/v2.4.1/libuev-2.4.1.tar.xz
|
||||||
|
wget https://github.com/troglobit/libite/releases/download/v2.6.2/libite-2.6.2.tar.gz
|
||||||
|
tar xf libuev-2.4.1.tar.xz
|
||||||
|
tar xf libite-2.6.2.tar.gz
|
||||||
|
(cd libuev-2.4.1 && ./configure && make -j9 && sudo make install-strip)
|
||||||
|
(cd libite-2.6.2 && ./configure && make -j9 && sudo make install-strip)
|
||||||
|
sudo ldconfig
|
||||||
- name: Setting release variables ...
|
- name: Setting release variables ...
|
||||||
id: build
|
id: build
|
||||||
run: |
|
run: |
|
||||||
ver=${GITHUB_REF#refs/tags/}
|
ver=${GITHUB_REF#refs/tags/}
|
||||||
echo "ver=${ver}" >> $GITHUB_OUTPUT
|
echo "ver=${ver}" >> $GITHUB_OUTPUT
|
||||||
if echo $ver | grep -qE '^[0-9]+\.[0-9]+(\.[0-9]+)?(-alpha|-beta|-rc)[0-9]*$'; then
|
stable='[0-9]+\.[0-9]+(\.[0-9]+)?'
|
||||||
|
if echo $ver | grep -qE "^${stable}(-alpha|-beta|-rc)[0-9]*$"; then
|
||||||
echo "pre=true" >> $GITHUB_OUTPUT
|
echo "pre=true" >> $GITHUB_OUTPUT
|
||||||
else
|
else
|
||||||
echo "pre=false" >> $GITHUB_OUTPUT
|
echo "pre=false" >> $GITHUB_OUTPUT
|
||||||
fi
|
fi
|
||||||
if echo $ver | grep -qE '^[0-9.]+\.[0-9.]+(\.[0-9]+)?$'; then
|
# Mark as latest release only if this is the highest stable
|
||||||
|
# tag, so a 4.x maintenance release doesn't outrank 5.x
|
||||||
|
newest=$(git ls-remote --tags --refs origin | awk -F/ '{print $NF}' \
|
||||||
|
| grep -E "^${stable}$" | sort -V | tail -1)
|
||||||
|
if [ "$ver" = "$newest" ]; then
|
||||||
echo "latest=true" >> $GITHUB_OUTPUT
|
echo "latest=true" >> $GITHUB_OUTPUT
|
||||||
else
|
else
|
||||||
echo "latest=false" >> $GITHUB_OUTPUT
|
echo "latest=false" >> $GITHUB_OUTPUT
|
||||||
@@ -36,21 +49,33 @@ 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
|
||||||
- name: Build release ...
|
- name: Build release ...
|
||||||
run: |
|
run: |
|
||||||
make release || (cat test/test-suite.log; false)
|
# Get version for finding distcheck build directory
|
||||||
|
./configure --version | head -1
|
||||||
|
ver=$(./configure --version | head -1 | awk '{print $NF}')
|
||||||
|
dir=finit-$ver/_build/sub
|
||||||
|
|
||||||
|
make -j1 release || (cat $dir/test/test-suite.log; false)
|
||||||
ls -lF ../
|
ls -lF ../
|
||||||
mkdir -p artifacts/
|
mkdir -p artifacts/
|
||||||
mv ../*.tar.* artifacts/
|
mv ../*.tar.* artifacts/
|
||||||
|
- name: Upload Test Results
|
||||||
|
if: always()
|
||||||
|
uses: actions/upload-artifact@v7
|
||||||
|
with:
|
||||||
|
name: finit-release-test-logs
|
||||||
|
path: finit-*/_build/sub/test/*.log
|
||||||
- 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,32 +7,53 @@ 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
|
||||||
outputs:
|
outputs:
|
||||||
run: ${{ steps.check.outputs.run }}
|
branches: ${{ steps.schedule.outputs.branches }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v7
|
||||||
- name: Check for any commits since last week
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
- name: Check for branches with no commits since last week
|
||||||
id: schedule
|
id: schedule
|
||||||
run: |
|
run: |
|
||||||
commits="$(git log --format=%H --since='1 week ago')"
|
branches=
|
||||||
if [ -n "$commits" ]; then
|
maint=$(git branch -r --format='%(refname:lstrip=3)' | grep -E '^[0-9]+\.x$')
|
||||||
echo "run=true" >> $GITHUB_OUTPUT
|
for branch in master $maint; do
|
||||||
else
|
commits="$(git log --format=%H --since='1 week ago' origin/$branch)"
|
||||||
echo "run=false" >> $GITHUB_OUTPUT
|
if [ -z "$commits" ]; then
|
||||||
fi
|
branches="$branches\"$branch\","
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
echo "branches=[${branches%,}]" >> $GITHUB_OUTPUT
|
||||||
distcheck:
|
distcheck:
|
||||||
needs: schedule
|
needs: schedule
|
||||||
if: ${{ needs.schedule.outputs.run == 'true' }}
|
if: ${{ needs.schedule.outputs.branches != '[]' }}
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
branch: ${{ fromJSON(needs.schedule.outputs.branches) }}
|
||||||
|
fail-fast: false
|
||||||
steps:
|
steps:
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: |
|
run: |
|
||||||
sudo apt-get -y update
|
sudo apt-get -y update
|
||||||
sudo apt-get -y install pkg-config jq libuev-dev libite-dev
|
sudo apt-get -y install pkg-config jq libcap-dev
|
||||||
- uses: actions/checkout@v4
|
wget https://github.com/troglobit/libuev/releases/download/v2.4.1/libuev-2.4.1.tar.xz
|
||||||
|
wget https://github.com/troglobit/libite/releases/download/v2.6.2/libite-2.6.2.tar.gz
|
||||||
|
tar xf libuev-2.4.1.tar.xz
|
||||||
|
tar xf libite-2.6.2.tar.gz
|
||||||
|
(cd libuev-2.4.1 && ./configure && make -j9 && sudo make install-strip)
|
||||||
|
(cd libite-2.6.2 && ./configure && make -j9 && sudo make install-strip)
|
||||||
|
sudo ldconfig
|
||||||
|
- uses: actions/checkout@v7
|
||||||
|
with:
|
||||||
|
ref: ${{ matrix.branch }}
|
||||||
- name: Base run
|
- name: Base run
|
||||||
run: |
|
run: |
|
||||||
./autogen.sh
|
./autogen.sh
|
||||||
@@ -49,3 +70,9 @@ jobs:
|
|||||||
ver=$(/tmp/sbin/initctl -V | awk '/Finit.*/ {print $2;}')
|
ver=$(/tmp/sbin/initctl -V | awk '/Finit.*/ {print $2;}')
|
||||||
dir=finit-$ver/_build/sub
|
dir=finit-$ver/_build/sub
|
||||||
make -j1 distcheck || (cat $dir/test/test-suite.log; false)
|
make -j1 distcheck || (cat $dir/test/test-suite.log; false)
|
||||||
|
- name: Upload Test Results
|
||||||
|
if: always()
|
||||||
|
uses: actions/upload-artifact@v7
|
||||||
|
with:
|
||||||
|
name: finit-weekly-test-logs-${{ matrix.branch }}
|
||||||
|
path: finit-*/_build/sub/test/*.log
|
||||||
@@ -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,719 +1,50 @@
|
|||||||
[![License Badge][]][License] [![GitHub Status][]][GitHub] [![Coverity Status][]][Coverity Scan]
|
[![License Badge][]][License] [![Release Badge][]][Release] [![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 a fast, simple alternative to [SysV init](https://en.wikipedia.org/wiki/Init)
|
||||||
* [Features](#features)
|
and [systemd](https://systemd.io), designed for small and embedded Linux systems.
|
||||||
* [Runlevels](#runlevels)
|
It can also run on desktop and server systems, like [finix][].
|
||||||
* [Syntax](doc/config.md#syntax)
|
|
||||||
* [Runparts & /etc/rc.local](#runparts--etcrclocal)
|
|
||||||
* [Hooks, Callbacks & Plugins](doc/plugins.md#hooks-callbacks--plugins)
|
|
||||||
* [Rebooting & Halting](#rebooting--halting)
|
|
||||||
* [Commands & Status](#commands--status)
|
|
||||||
* [Tips & Tricks with the kernel cmdline](doc/cmdline.md)
|
|
||||||
* [Building](doc/build.md#building)
|
|
||||||
* [Running](doc/build.md#running)
|
|
||||||
* [Recovery](doc/build.md#recovery)
|
|
||||||
* [Debugging](doc/build.md#debugging)
|
|
||||||
* [Requirements](#requirements)
|
|
||||||
* [Origin & References](#origin--references)
|
|
||||||
|
|
||||||
|
> Reverse engineered from the [EeePC fastinit][]
|
||||||
|
> "gaps filled with frog DNA …"
|
||||||
|
> — [Claudio Matsuoka][]
|
||||||
|
|
||||||
Introduction
|
For detailed information, explore our extensive documentation
|
||||||
------------
|
:books: **<http://finit-project.github.io>**
|
||||||
|
|
||||||
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][br2demo],
|
||||||
|
* :package: [Debian GNU/Linux](contrib/debian/),
|
||||||
|
* :mountain: [Alpine Linux](contrib/alpine/), and
|
||||||
|
* :milky_way: [Void Linux](contrib/void/)
|
||||||
|
|
||||||
* Runlevels, defined per service
|
> [!NOTE]
|
||||||
* One-shot tasks, services (daemons), or [SysV init][4] start/stop scripts
|
> Finit can run on various Linux distributions, but the bundled install
|
||||||
* Runparts and `/etc/rc.local` support
|
> scripts are examples only. They have been tested on amd64 (x86_64) systems
|
||||||
* Process supervision similar to [systemd][]
|
> with standard configurations.
|
||||||
* Sourcing environment files
|
>
|
||||||
* Conditions for network/process/custom dependencies
|
> For embedded systems, see these [Buildroot][]-based examples:
|
||||||
* Readiness notification; PID files (native) for synchronizing system
|
> [myLinux][], [Infix][], or [br2-finit-demo][].
|
||||||
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
|
[finix]: https://github.com/finix-community/finix
|
||||||
on server and desktop systems as well. For working examples, see the
|
|
||||||
[contrib/](contrib/) section with tutorials for the following Linux
|
|
||||||
distributions:
|
|
||||||
|
|
||||||
* [Void Linux](contrib/void/),
|
|
||||||
* [Alpine Linux](contrib/alpine/), and
|
|
||||||
* [Debian GNU/Linux](contrib/debian/), also works on Ubuntu/Linux Mint
|
|
||||||
|
|
||||||
> **Note:** support for various Linux distributions does not mean Finit
|
|
||||||
> installs easily on all architectures. The bundled install scripts are
|
|
||||||
> examples for standard installations, tested on amd64 (x86_64) systems.
|
|
||||||
> Custom setups, e.g., for embedded systems, can be found in any of the
|
|
||||||
> following [Buildroot][] based examples: [myLinux][], [Infix][], or the
|
|
||||||
> plain [br2-finit-demo](https://github.com/troglobit/br2-finit-demo).
|
|
||||||
|
|
||||||
|
|
||||||
Example
|
|
||||||
-------
|
|
||||||
|
|
||||||
This example `/etc/finit.conf` can also be split up in multiple `.conf`
|
|
||||||
files in `/etc/finit.d`. Available, but not yet enabled, services can
|
|
||||||
be placed in `/etc/finit.d/available` and enabled by an operator using
|
|
||||||
the [initctl](#commands--status) tool. See the above mentioned Linux
|
|
||||||
distributions, or [myLinux][].
|
|
||||||
|
|
||||||
> **Note:** as of Finit v4.4, .conf lines can be broken up using the
|
|
||||||
> standard UNIX continuation character (`\`), also trailing comments are
|
|
||||||
> now supported. The latter means you need to escape any hashes used in
|
|
||||||
> directives and descriptions (`\#`). For more on this and examples,
|
|
||||||
> see the [finit.conf(5)][] manual or [doc/config.md](doc/config.md).
|
|
||||||
|
|
||||||
```ApacheConf
|
|
||||||
# Fallback if /etc/hostname is missing
|
|
||||||
host default
|
|
||||||
|
|
||||||
# Runlevel to start after bootstrap, 'S', default: 2
|
|
||||||
#runlevel 2
|
|
||||||
|
|
||||||
# Support for setting global environment variables, using foo=bar syntax
|
|
||||||
# be careful though with variables like PATH, SHELL, LOGNAME, etc.
|
|
||||||
#PATH=/usr/bin:/bin:/usr/sbin:/sbin
|
|
||||||
|
|
||||||
# Max file size for each log file: 100 kiB, rotate max 4 copies:
|
|
||||||
# log => log.1 => log.2.gz => log.3.gz => log.4.gz
|
|
||||||
log size=100k count=4
|
|
||||||
|
|
||||||
# Services to be monitored and respawned as needed
|
|
||||||
service [S12345] env:-/etc/conf.d/watchdog watchdog $WATCHDOG_OPTS $WATCHDOG_DEV -- System watchdog daemon
|
|
||||||
service [S12345] env:-/etc/conf.d/syslog syslogd -n $SYSLOGD_OPTS -- System log daemon
|
|
||||||
service [S12345] <pid/syslogd> env:-/etc/conf.d/klogd klogd -n $KLOGD_OPTS -- Kernel log daemon
|
|
||||||
service [2345] env:-/etc/conf.d/lldpd lldpd -d $LLDPD_OPTS -- LLDP daemon (IEEE 802.1ab)
|
|
||||||
|
|
||||||
# The BusyBox ntpd does not use syslog when running in the foreground
|
|
||||||
# So we use this trick to redirect stdout/stderr to a log file. The
|
|
||||||
# log file is rotated with the above settings. The condition declares
|
|
||||||
# a dependency on a system default route (gateway) to be set. A single
|
|
||||||
# <!> at the beginning means ntpd does not respect SIGHUP for restart.
|
|
||||||
service [2345] log:/var/log/ntpd.log <!net/route/default> ntpd -n -l -I eth0 -- NTP daemon
|
|
||||||
|
|
||||||
# For multiple instances of the same service, add :ID somewhere between
|
|
||||||
# the service/run/task keyword and the command.
|
|
||||||
service :80 [2345] merecat -n -p 80 /var/www -- Web server
|
|
||||||
service :8080 [2345] merecat -n -p 8080 /var/www -- Old web server
|
|
||||||
|
|
||||||
# Alternative method instead of below runparts, can also use /etc/rc.local
|
|
||||||
#sysv [S] /etc/init.d/keyboard-setup -- Setting up preliminary keymap
|
|
||||||
#sysv [S] /etc/init.d/acpid -- Starting ACPI Daemon
|
|
||||||
#task [S] /etc/init.d/kbd -- Preparing console
|
|
||||||
|
|
||||||
# Hidden from boot progress, using empty `--` description
|
|
||||||
#sysv [S] /etc/init.d/keyboard-setup --
|
|
||||||
#sysv [S] /etc/init.d/acpid --
|
|
||||||
#task [S] /etc/init.d/kbd --
|
|
||||||
|
|
||||||
# Run start scripts from this directory
|
|
||||||
# runparts /etc/start.d
|
|
||||||
|
|
||||||
# Virtual consoles run BusyBox getty, keep kernel default speed
|
|
||||||
tty [12345] /sbin/getty -L 0 /dev/tty1 linux nowait noclear
|
|
||||||
tty [2345] /sbin/getty -L 0 /dev/tty2 linux nowait noclear
|
|
||||||
tty [2345] /sbin/getty -L 0 /dev/tty3 linux nowait noclear
|
|
||||||
|
|
||||||
# Use built-in getty for serial port and USB serial
|
|
||||||
#tty [12345] /dev/ttyAMA0 noclear nowait
|
|
||||||
#tty [12345] /dev/ttyUSB0 noclear
|
|
||||||
|
|
||||||
# Just give me a shell, I need to debug this embedded system!
|
|
||||||
#tty [12345] console noclear nologin
|
|
||||||
```
|
|
||||||
|
|
||||||
The `service` stanza, as well as `task`, `run` and others are described
|
|
||||||
in full in [doc/config.md](doc/config.md). Here's a quick overview of
|
|
||||||
some of the most common components needed to start a UNIX daemon:
|
|
||||||
|
|
||||||
```
|
|
||||||
service [LVLS] <COND> log env:[-]/etc/default/daemon daemon ARGS -- Daemon daemon
|
|
||||||
^ ^ ^ ^ ^ ^ ^ ^
|
|
||||||
| | | | | | | `---------- Optional description
|
|
||||||
| | | | | | `------------------ Daemon arguments
|
|
||||||
| | | | | `------------------------- Path to daemon
|
|
||||||
| | | | `---------------------------------------------------- Optional env. file
|
|
||||||
| | | `-------------------------------------------------------- Redirect output to log
|
|
||||||
| | `--------------------------------------------------------------- Optional conditions
|
|
||||||
| `---------------------------------------------------------------------- Optional Runlevels
|
|
||||||
`------------------------------------------------------------------------------ Monitored application
|
|
||||||
```
|
|
||||||
|
|
||||||
Some components are optional: runlevel(s), condition(s) and description,
|
|
||||||
making it easy to create simple start scripts and still possible for more
|
|
||||||
advanced uses as well:
|
|
||||||
|
|
||||||
service /usr/sbin/sshd -D
|
|
||||||
|
|
||||||
Dependencies are handled using [conditions](doc/conditions.md). One of
|
|
||||||
the most common conditions is to wait for basic networking to become
|
|
||||||
available:
|
|
||||||
|
|
||||||
service <net/route/default> nginx -- High performance HTTP server
|
|
||||||
|
|
||||||
Here is another example where we instruct Finit to not start BusyBox
|
|
||||||
`ntpd` until `syslogd` has started properly. Finit waits for `syslogd`
|
|
||||||
to create its PID file, by default `/var/run/syslogd.pid`.
|
|
||||||
|
|
||||||
service [2345] log <!pid/syslogd> ntpd -n -N -p pool.ntp.org
|
|
||||||
service [S12345] syslogd -n -- Syslog daemon
|
|
||||||
|
|
||||||
Notice the `log` keyword, BusyBox `ntpd` uses `stderr` for logging when
|
|
||||||
run in the foreground. With `log` Finit redirects `stdout` + `stderr`
|
|
||||||
to the system log daemon using the command line `logger(1)` tool.
|
|
||||||
|
|
||||||
A service, or task, can have multiple dependencies listed. Here we wait
|
|
||||||
for *both* `syslogd` to have started and basic networking to be up:
|
|
||||||
|
|
||||||
service [2345] log <pid/syslogd,net/route/default> ntpd -n -N -p pool.ntp.org
|
|
||||||
|
|
||||||
If either condition fails, e.g. loss of networking, `ntpd` is stopped
|
|
||||||
and as soon as it comes back up again `ntpd` is restarted automatically.
|
|
||||||
|
|
||||||
**Note:** Make sure daemons *do not* fork and detach themselves from the
|
|
||||||
controlling TTY, usually an `-n` or `-f` flag, or `-D` as in the case
|
|
||||||
of OpenSSH above. If it detaches itself, Finit cannot monitor it and
|
|
||||||
will instead try to restart it.
|
|
||||||
|
|
||||||
|
|
||||||
Features
|
|
||||||
--------
|
|
||||||
|
|
||||||
**Process Supervision**
|
|
||||||
|
|
||||||
Start, monitor and restart services should they fail.
|
|
||||||
|
|
||||||
|
|
||||||
**Getty**
|
|
||||||
|
|
||||||
Finit supports external getty but also comes with a limited built-in
|
|
||||||
Getty, useful for really small systems. A getty sets up the TTY and
|
|
||||||
waits for user input before handing over to `/bin/login`, which is
|
|
||||||
responsible for handling the actual authentication.
|
|
||||||
|
|
||||||
```conf
|
|
||||||
tty [12345] /dev/tty1 nowait linux
|
|
||||||
tty [12345] /dev/ttyAMA0 noclear vt100
|
|
||||||
tty [12345] /sbin/getty -L /dev/ttyAMA0 vt100
|
|
||||||
```
|
|
||||||
|
|
||||||
Users of embedded systems may want to enable automatic serial console
|
|
||||||
with the special `@console` device. This works regardless weather the
|
|
||||||
system uses `ttyS0`, `ttyAMA0`, `ttyMXC0`, or anything else. Finit
|
|
||||||
figures it out by querying sysfs: `/sys/class/tty/console/active`.
|
|
||||||
|
|
||||||
```conf
|
|
||||||
tty [12345] @console linux noclear
|
|
||||||
```
|
|
||||||
|
|
||||||
Notice the optional `noclear`, `nowait`, and `nologin` flags. The
|
|
||||||
latter is for skipping the login process entirely. For more information,
|
|
||||||
see [doc/config.md](doc/config.md#syntax).
|
|
||||||
|
|
||||||
|
|
||||||
**Runlevels**
|
|
||||||
|
|
||||||
Support for SysV init-style [runlevels][5] is available, in the same
|
|
||||||
minimal style as everything else in Finit. The `[2345]` syntax can be
|
|
||||||
applied to service, task, run, and TTY stanzas.
|
|
||||||
|
|
||||||
Reserved runlevels are 0 and 6, halt and reboot, respectively just like
|
|
||||||
SysV init. Runlevel 1 can be configured freely, but is recommended to
|
|
||||||
be kept as the system single-user runlevel since Finit will not start
|
|
||||||
networking here. The configured `runlevel NUM` from `/etc/finit.conf`
|
|
||||||
is what Finit changes to after bootstrap, unless 'single' (or 'S') is
|
|
||||||
given on the kernel cmdline, in which case runlevel 1 is started.
|
|
||||||
|
|
||||||
All services in runlevel S) are started first, followed by the desired
|
|
||||||
run-time runlevel. Run tasks in runlevel S can be started in sequence
|
|
||||||
by using `run [S] cmd`. Changing runlevels at runtime is done like any
|
|
||||||
other init, e.g. <kbd>init 4</kbd>, but also using the more advanced
|
|
||||||
`intictl` tool.
|
|
||||||
|
|
||||||
|
|
||||||
**Conditions**
|
|
||||||
|
|
||||||
As mentioned previously, Finit has an advanced dependency system to
|
|
||||||
handle synchronization, called [conditions](doc/conditions.md). It can
|
|
||||||
be used in many ways; depend on another service, network availability,
|
|
||||||
etc.
|
|
||||||
|
|
||||||
One *really cool* example useful for embedded systems is to run certain
|
|
||||||
scripts if a board has a certain feature encoded in its device tree. At
|
|
||||||
bootstrap we run the following `ident` script:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
#!/bin/sh
|
|
||||||
conddir=/var/run/finit/cond/hw/model
|
|
||||||
dtmodel=/sys/firmware/devicetree/base/model
|
|
||||||
|
|
||||||
if ! test -e $dtmodel; then
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
model=$(cat $dtmodel | tr "[A-Z] " "[a-z]-")
|
|
||||||
mkdir -p $conddir && ln -s ../../reconf $conddir/$model
|
|
||||||
```
|
|
||||||
|
|
||||||
Provided the device tree node exists, and is a string, we can then use
|
|
||||||
the condition `<hw/model/foo>` when starting other scripts. Here is an
|
|
||||||
example:
|
|
||||||
|
|
||||||
```
|
|
||||||
run [S] /path/to/ident --
|
|
||||||
task [2] <hw/model/foo> /path/to/foo-init -- Initializing Foo board
|
|
||||||
```
|
|
||||||
|
|
||||||
> Notice the trick with an empty description to hide the call to `ident`
|
|
||||||
> in the Finit progress output.
|
|
||||||
|
|
||||||
|
|
||||||
**Plugins**
|
|
||||||
|
|
||||||
Plugins can *extend* the functionality of Finit and *hook into* the
|
|
||||||
different stages of the boot process and at runtime. Plugins are
|
|
||||||
written in C and compiled into a dynamic library loaded automatically by
|
|
||||||
finit at boot. A basic set of plugins are bundled in the `plugins/`
|
|
||||||
directory.
|
|
||||||
|
|
||||||
Capabilities:
|
|
||||||
|
|
||||||
- **Hooks**
|
|
||||||
Hook into the boot at predefined points to extend Finit
|
|
||||||
- **I/O**
|
|
||||||
Listen to external events and control Finit behavior/services
|
|
||||||
|
|
||||||
Extensions and functionality not purely related to what an `/sbin/init`
|
|
||||||
needs to start a system are available as a set of plugins that either
|
|
||||||
hook into the boot process or respond to various I/O.
|
|
||||||
|
|
||||||
For more information, see [doc/plugins.md](doc/plugins.md).
|
|
||||||
|
|
||||||
|
|
||||||
**Automatic Reload**
|
|
||||||
|
|
||||||
By default, Finit monitors `/etc/finit.d/` and `/etc/finit.d/enabled/`
|
|
||||||
registering any changes to `.conf` files. To activate a change the user
|
|
||||||
must call `initctl reload`, which reloads all modified files, stops any
|
|
||||||
removed services, starts new ones, and restarts any modified ones. If the
|
|
||||||
command line arguments of a service have changed, the process will be
|
|
||||||
terminated and then started again with the updated arguments. If the arguments
|
|
||||||
have not been modified and the process supports SIGHUP, the process will
|
|
||||||
receive a SIGHUP rather than being terminated and started.
|
|
||||||
|
|
||||||
For some use-cases the extra step of calling `initctl reload` creates an
|
|
||||||
unnecessary overhead, which can be removed at build-time using:
|
|
||||||
|
|
||||||
configure --enable-auto-reload
|
|
||||||
|
|
||||||
|
|
||||||
**Cgroups**
|
|
||||||
|
|
||||||
Finit supports cgroups v2 and comes with the following default groups in
|
|
||||||
which services and user sessions are placed in:
|
|
||||||
|
|
||||||
/sys/fs/cgroup
|
|
||||||
|-- init/ # cpu.weight:100
|
|
||||||
|-- system/ # cpu.weight:9800
|
|
||||||
`-- user/ # cpu.weight:100
|
|
||||||
|
|
||||||
Finit itself and its helper scripts and services are placed in the
|
|
||||||
top-level leaf-node group `init/`, which also is _reserved_.
|
|
||||||
|
|
||||||
All run/task/service/sysv processes are placed in their own sub-group
|
|
||||||
in `system/`. The name of each sub-group is taken from the respective
|
|
||||||
`.conf` file from `/etc/finit.d`.
|
|
||||||
|
|
||||||
All getty/tty processes are placed in their own sub-group in `user/`.
|
|
||||||
The name of each sub-group is taken from the username.
|
|
||||||
|
|
||||||
A fourth group also exists, the `root` group. It is also _reserved_ and
|
|
||||||
primarily intended for RT tasks. If you have RT tasks they need to be
|
|
||||||
declared as such in their service stanza like this:
|
|
||||||
|
|
||||||
service [...] <...> cgroup.root /path/to/foo args -- description
|
|
||||||
|
|
||||||
or
|
|
||||||
|
|
||||||
cgroup.root
|
|
||||||
service [...] <...> /path/to/foo args -- description
|
|
||||||
service [...] <...> /path/to/bar args -- description
|
|
||||||
|
|
||||||
See [doc/config.md](doc/config.md#cgroups) for more information, e.g.,
|
|
||||||
how to configure per-group limits.
|
|
||||||
|
|
||||||
The `initctl` tool has three commands to help debug and optimize the
|
|
||||||
setup and monitoring of cgroups. See the `ps`, `top`, and `cgroup`
|
|
||||||
commands for details.
|
|
||||||
|
|
||||||
> **Note:** systems that do not support cgroups, specifically version 2,
|
|
||||||
> are automatically detected. On such systems the above functionality
|
|
||||||
> is disabled early at boot.
|
|
||||||
|
|
||||||
|
|
||||||
Runparts & /etc/rc.local
|
|
||||||
------------------------
|
|
||||||
|
|
||||||
At the end of the boot, when all bootstrap (`S`) tasks and services have
|
|
||||||
started, but not networking, Finit calls its built-in [run-parts(8)][]
|
|
||||||
command on any configured `runparts <DIR>` directory. This happens just
|
|
||||||
before changing to the configured runlevel (default 2). (Networking is
|
|
||||||
enabled just prior to changing from single user mode.)
|
|
||||||
|
|
||||||
```shell
|
|
||||||
runparts /etc/rc.d/
|
|
||||||
```
|
|
||||||
|
|
||||||
Right after the runlevel change when all services have started properly,
|
|
||||||
`/etc/rc.local` is called.
|
|
||||||
|
|
||||||
No configuration stanza in `/etc/finit.conf` is required for `rc.local`.
|
|
||||||
If it exists and is an executable shell script Finit calls it at the very
|
|
||||||
end of the boot, before calling the `HOOK_SYSTEM_UP`. See more on hooks
|
|
||||||
in [doc/plugins.md](doc/plugins.md#hooks).
|
|
||||||
|
|
||||||
|
|
||||||
### Limitations
|
|
||||||
|
|
||||||
It is not possible to call Finit via signals or use `initctl` in any
|
|
||||||
runparts or `/etc/rc.local` script. This because Finit is single
|
|
||||||
threaded and is calling these scripts in a blocking fashion at the end
|
|
||||||
of runlevel S, at which point the event loop has not yet been started.
|
|
||||||
|
|
||||||
The event loop is the whole thing which Finit is built around, except
|
|
||||||
for runlevel S, which remains a slow procession through a lot of set up,
|
|
||||||
with a few hooks and blocking call outs to external scripts.
|
|
||||||
|
|
||||||
However, not all `initctl` commands are prohibited. Supported commands:
|
|
||||||
|
|
||||||
- `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/
|
||||||
|
[br2demo]: https://troglobit.com/post/2022-12-26-buildroot-demo-of-fastinit-finit/
|
||||||
|
[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/
|
[Release]: https://github.com/finit-project/finit/releases
|
||||||
[watchdogd]: https://github.com/troglobit/watchdogd/
|
[Release Badge]: https://img.shields.io/github/v/release/finit-project/finit
|
||||||
[sysklogd]: https://github.com/troglobit/sysklogd/
|
[GitHub]: https://github.com/finit-project/finit/actions/workflows/build.yml/
|
||||||
[GitHub]: https://github.com/troglobit/finit/actions/workflows/build.yml/
|
[GitHub Status]: https://github.com/finit-project/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
|
||||||
[Coverity Status]: https://scan.coverity.com/projects/3545/badge.svg
|
[Coverity Status]: https://scan.coverity.com/projects/3545/badge.svg
|
||||||
|
[br2-finit-demo]: https://github.com/finit-project/br2-finit-demo
|
||||||
@@ -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
|
|
||||||
+40
-14
@@ -1,7 +1,7 @@
|
|||||||
AC_INIT([Finit], [4.10-rc2], [https://github.com/troglobit/finit/issues],
|
AC_INIT([Finit], [4.18-pre], [https://github.com/finit-project/finit/issues],
|
||||||
[finit], [https://troglobit.com/projects/finit/])
|
[finit], [https://http://finit-project.github.io/])
|
||||||
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
|
||||||
@@ -47,8 +48,8 @@ AC_TYPE_UINT32_T
|
|||||||
PKG_PROG_PKG_CONFIG
|
PKG_PROG_PKG_CONFIG
|
||||||
|
|
||||||
# Check for required libraries
|
# Check for required libraries
|
||||||
PKG_CHECK_MODULES([uev], [libuev >= 2.2.0])
|
PKG_CHECK_MODULES([uev], [libuev >= 2.4.1])
|
||||||
PKG_CHECK_MODULES([lite], [libite >= 2.2.0])
|
PKG_CHECK_MODULES([lite], [libite >= 2.6.1])
|
||||||
|
|
||||||
# Check for configured Finit features
|
# Check for configured Finit features
|
||||||
AC_ARG_ENABLE(auto_reload,
|
AC_ARG_ENABLE(auto_reload,
|
||||||
@@ -71,6 +72,10 @@ AC_ARG_ENABLE(cgroup,
|
|||||||
AS_HELP_STRING([--disable-cgroup], [Disable cgroup v2 support, default: autodetect from /sys/fs/cgroup]),,[
|
AS_HELP_STRING([--disable-cgroup], [Disable cgroup v2 support, default: autodetect from /sys/fs/cgroup]),,[
|
||||||
enable_cgroup=yes])
|
enable_cgroup=yes])
|
||||||
|
|
||||||
|
AC_ARG_ENABLE(libcap,
|
||||||
|
AS_HELP_STRING([--disable-libcap], [Disable Linux capabilities support]),,[
|
||||||
|
enable_libcap=yes])
|
||||||
|
|
||||||
AC_ARG_ENABLE(redirect,
|
AC_ARG_ENABLE(redirect,
|
||||||
AS_HELP_STRING([--disable-redirect], [Disable redirection of service output to /dev/null]),,[
|
AS_HELP_STRING([--disable-redirect], [Disable redirection of service output to /dev/null]),,[
|
||||||
enable_redirect=yes])
|
enable_redirect=yes])
|
||||||
@@ -111,6 +116,7 @@ AC_PLUGIN([hotplug], [yes], [Start udevd or mdev kernel event datamon])
|
|||||||
AC_PLUGIN([rtc], [yes], [Save and restore RTC using hwclock])
|
AC_PLUGIN([rtc], [yes], [Save and restore RTC using hwclock])
|
||||||
AC_PLUGIN([tty], [yes], [Automatically activate new TTYs, e.g. USB-to-serial])
|
AC_PLUGIN([tty], [yes], [Automatically activate new TTYs, e.g. USB-to-serial])
|
||||||
AC_PLUGIN([urandom], [yes], [Setup and save random seed at boot/shutdown])
|
AC_PLUGIN([urandom], [yes], [Setup and save random seed at boot/shutdown])
|
||||||
|
AC_PLUGIN([plymouth], [no], [Plymouth boot splash integration])
|
||||||
AC_PLUGIN([testserv], [no], [Test plugin to start test serv daemon])
|
AC_PLUGIN([testserv], [no], [Test plugin to start test serv daemon])
|
||||||
|
|
||||||
# Check for extra arguments or packages
|
# Check for extra arguments or packages
|
||||||
@@ -168,6 +174,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])
|
||||||
@@ -199,6 +209,16 @@ AS_IF([test "x$enable_kernel_logging" = "xyes"], [
|
|||||||
AS_IF([test "x$enable_cgroup" = "xyes"], [
|
AS_IF([test "x$enable_cgroup" = "xyes"], [
|
||||||
AC_DEFINE(CGROUP2_ENABLED, 1, [Autodetect cgroup v2 support from /sys/fs/cgroup])])
|
AC_DEFINE(CGROUP2_ENABLED, 1, [Autodetect cgroup v2 support from /sys/fs/cgroup])])
|
||||||
|
|
||||||
|
AS_IF([test "x$enable_libcap" = "xyes"], [
|
||||||
|
AC_CHECK_LIB([cap], [cap_from_text], [
|
||||||
|
AC_DEFINE(HAVE_LIBCAP, 1, [Have libcap for Linux capabilities support])
|
||||||
|
LIBS="$LIBS -lcap"
|
||||||
|
], [
|
||||||
|
AC_MSG_WARN([libcap not found, capabilities support disabled])
|
||||||
|
enable_libcap=no
|
||||||
|
])
|
||||||
|
])
|
||||||
|
|
||||||
AS_IF([test "x$enable_fastboot" = "xyes"], [
|
AS_IF([test "x$enable_fastboot" = "xyes"], [
|
||||||
AC_DEFINE(FAST_BOOT, 1, [Skip fsck check on filesystems listed in /etc/fstab])])
|
AC_DEFINE(FAST_BOOT, 1, [Skip fsck check on filesystems listed in /etc/fstab])])
|
||||||
|
|
||||||
@@ -308,6 +328,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 +342,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,7 +432,9 @@ 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
|
||||||
|
Use libcap............: $enable_libcap
|
||||||
Parse kernel cmdline..: $enable_kernel_cmdline
|
Parse kernel cmdline..: $enable_kernel_cmdline
|
||||||
Keep kernel logging...: $enable_kernel_logging
|
Keep kernel logging...: $enable_kernel_logging
|
||||||
Skip fsck check.......: $enable_fastboot
|
Skip fsck check.......: $enable_fastboot
|
||||||
|
|||||||
@@ -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! :)
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
HowTo: Finit on Alpine Linux 3.4...3.19
|
HowTo: Finit on Alpine Linux 3.4...3.19
|
||||||
=======================================
|
=======================================
|
||||||
|
|
||||||
> **Blog** https://troglobit.com/post/2021-02-12-alpine-linux-with-finit/
|
> [!TIP]
|
||||||
|
> https://troglobit.com/post/2021-02-12-alpine-linux-with-finit/
|
||||||
|
|
||||||
HowTo use Finit to boot an [Alpine Linux][] system. It is assumed that
|
HowTo use Finit to boot an [Alpine Linux][] system. It is assumed that
|
||||||
the user has already installed make, a compiler, C library header files,
|
the user has already installed make, a compiler, C library header files,
|
||||||
|
|||||||
@@ -20,8 +20,9 @@ tools pre-systemd work as intended.
|
|||||||
|
|
||||||
root@debian:~# apt install initscripts console-setup
|
root@debian:~# apt install initscripts console-setup
|
||||||
|
|
||||||
> **Note:** as of Debian 11 (Bullseye), libuev and libite are part of
|
> [!TIP]
|
||||||
> the main section of Debian. So just install the -dev packages :)
|
> As of Debian 11 (Bullseye), libuev and libite are part of the main
|
||||||
|
> section of Debian. So just install the -dev packages :)
|
||||||
|
|
||||||
The following script can then be used to configure, build, install and
|
The following script can then be used to configure, build, install and
|
||||||
set up your system to run Finit:
|
set up your system to run Finit:
|
||||||
@@ -47,7 +48,8 @@ comands to `initctl`, followed by `reload` to activate your changes.
|
|||||||
You can also use a standard [/etc/rc.local](rc.local) for one-shot tasks
|
You can also use a standard [/etc/rc.local](rc.local) for one-shot tasks
|
||||||
and initialization like keyboard language etc.
|
and initialization like keyboard language etc.
|
||||||
|
|
||||||
> **NOTE:** X Window system, you may need to `sudo apt install elogind`
|
> [!NOTE]
|
||||||
|
> For the X Window system, you may need to `sudo apt install elogind`
|
||||||
> (Bullseye and later), followed by `initctl reload` to activate it (it
|
> (Bullseye and later), followed by `initctl reload` to activate it (it
|
||||||
> is enabled by default), and logout/login again. The elogind daemon
|
> is enabled by default), and logout/login again. The elogind daemon
|
||||||
> ensures a regular non-root user can start and interact with an X
|
> ensures a regular non-root user can start and interact with an X
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# On some systems, bootstrap can be really quick and cause elogind
|
# On some systems, bootstrap can be really quick and cause elogind
|
||||||
# to not start before a user has managed to log in. To prevent
|
# to not start before a user has managed to log in. To prevent
|
||||||
# this, add <pid/elogind> as condition to your TTYs in getty.conf
|
# this, add <pid/elogind> as condition to your TTYs in getty.conf
|
||||||
service [2345] <pid/syslogd> /lib/elogind/elogind -- Login manager
|
service [2345] <pid/syslogd> /usr/libexec/elogind -- Login manager
|
||||||
File renamed without changes.
File renamed without changes.
+337
-40
@@ -3,8 +3,296 @@ Change Log
|
|||||||
|
|
||||||
All relevant changes are documented in this file.
|
All relevant changes are documented in this file.
|
||||||
|
|
||||||
|
[Unreleased]
|
||||||
|
------------
|
||||||
|
|
||||||
[4.10][] - 2025-02-28
|
### Changes
|
||||||
|
|
||||||
|
- Restart log now spells out the signal name and flags core dumps,
|
||||||
|
e.g. `killed by SIGKILL` or `killed by SIGSEGV, core dumped`, in
|
||||||
|
place of the bare numeric `by signal: N`. Gives operators a much
|
||||||
|
stronger breadcrumb when a daemon dies unexpectedly
|
||||||
|
- Service `user:` and `group:` names, including supplementary groups,
|
||||||
|
can now be up to 63 characters, up from 15. Longer names were
|
||||||
|
silently truncated before the lookup, so the service never started.
|
||||||
|
By Anees Rehman
|
||||||
|
- Shutdown now stops after the first successful remount of `/` read
|
||||||
|
only. The plain `mount -n -o remount,ro /`, which reads
|
||||||
|
`/etc/fstab`, is only used when both device-agnostic forms fail,
|
||||||
|
the same order as Debian's `umountroot`. By Anees Rehman
|
||||||
|
|
||||||
|
### Fixes
|
||||||
|
|
||||||
|
- Remove stale daemon-owned (`pid:!`) pidfiles after unclean exits.
|
||||||
|
When a daemon dies via SIGKILL/OOM/segfault, or exits early during
|
||||||
|
startup, its pidfile lingers and can prevent the next instance from
|
||||||
|
starting -- `dbus-daemon` for example refuses to start when its
|
||||||
|
pidfile already exists, so Finit's restart loop gives up. Finit now
|
||||||
|
drops the file when it still names the just-reaped PID and that PID
|
||||||
|
is no longer alive (the liveness check guards against PID reuse).
|
||||||
|
This is a controlled exception to the long-standing rule that Finit
|
||||||
|
does not touch service-owned pidfiles
|
||||||
|
- Fix misspelled `SIGUNKOWN` returned by `sig_name()` for unknown
|
||||||
|
signal numbers, now spelled correctly as `SIGUNKNOWN`. Surfaced by
|
||||||
|
the new restart log above
|
||||||
|
- Fix mode of existing `d`/`D` directories in tmpfiles, the chmod branch
|
||||||
|
never ran because the directory creation swallowed `EEXIST`. Mode and
|
||||||
|
owner of `d`/`D`, `e`, and `f`/`F` entries, and of the directories
|
||||||
|
`mksubsys()` creates for the dbus plugin, are now set through an open fd
|
||||||
|
and only when they differ, so an immutable directory like `/var/empty`
|
||||||
|
no longer warns on every boot. By Sam Brkopac
|
||||||
|
- Fix crash at config load for a `stop:` or `reload:` script written
|
||||||
|
with a timeout, e.g. `stop:5,/bin/true`, which took PID 1 down
|
||||||
|
- Fix a lost reload for a service paused mid-reload by a condition in
|
||||||
|
flux. A second reload arriving meanwhile re-parsed the unchanged .conf
|
||||||
|
and cleared the pending mark, so the service resumed without ever being
|
||||||
|
reloaded. Seen on Infix, where sshd kept its old listen addresses after
|
||||||
|
a change that landed as two reloads in a row
|
||||||
|
|
||||||
|
[4.17][] - 2026-04-28
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
### Changes
|
||||||
|
|
||||||
|
- Add Plymouth boot splash plugin to manage the `plymouthd` lifecycle across boot,
|
||||||
|
`switch_root`, and shutdown. Activated by the `splash` kernel command line
|
||||||
|
argument. By Aaron Andersen
|
||||||
|
- Add `tty:` option for run/task/service stanzas to acquire a controlling
|
||||||
|
terminal. The device is opened as stdin, set as the session's controlling TTY
|
||||||
|
via `TIOCSCTTY`, and `TERM` is set automatically — `linux` for virtual terminals
|
||||||
|
and `vt102` for serial lines. By Ollie Gutierrez
|
||||||
|
- Improve console output atomicity at boot and shutdown: description and status
|
||||||
|
(`[ OK ]` / `[FAIL]`) are emitted in a single write so kernel messages cannot
|
||||||
|
split them. If output has been scrolled away, the description is re-printed
|
||||||
|
before the final status line. Console buffer is drained with `tcdrain(2)` and
|
||||||
|
ANSI attributes are reset before handing control back to the kernel at
|
||||||
|
shutdown/reboot
|
||||||
|
|
||||||
|
### Fixes
|
||||||
|
|
||||||
|
- Fix reverse-dependency condition handling on reload: when a service without
|
||||||
|
SIGHUP support is reloaded, its condition is now cleared immediately so
|
||||||
|
dependents transition to `STOPPING` before `SIGTERM` is sent to the parent,
|
||||||
|
preventing them from crashing with an incremented restart counter
|
||||||
|
- Fix `/var/tmp` mode in `tmpfiles.d/var.conf` from `0777` to `1777` (sticky bit)
|
||||||
|
to match `/tmp`, by Aaron Andersen
|
||||||
|
- Fix potential memory corruption in config parser: stale pointer captures of
|
||||||
|
`PATH` and `SHELL` at startup could dangle after environment modification;
|
||||||
|
`conf_reset_env()` now reads from the live environment instead, by Vasily Zubko
|
||||||
|
- Fix plugin name registration: replace `__FILE__` macro with explicit string
|
||||||
|
literals in all plugin structs and debug messages, preventing subtle build-
|
||||||
|
system–dependent macro expansion issues, by Vasily Zubko
|
||||||
|
|
||||||
|
|
||||||
|
[4.16][] - 2026-02-27
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
### Changes
|
||||||
|
|
||||||
|
- Add `initctl switch-root` command and plugin hook point. Useful for
|
||||||
|
systems requiring early boot tasks like LUKS unlock, LVM activation,
|
||||||
|
or network boot before mounting the real root, by Aaron Andersen
|
||||||
|
- Set USER and LOGNAME environment variables when dropping privileges.
|
||||||
|
Fixes issues with software like rootless Podman that determines user
|
||||||
|
identity from environment variables, by Aaron Andersen
|
||||||
|
- Add `remain:yes` option for run/task oneshot commands, similar to the
|
||||||
|
systemd `RemainAfterExit=yes`, by Aaron Andersen
|
||||||
|
- Clear service conditions on `initctl reload NAME` to ensure dependent
|
||||||
|
services are properly updated
|
||||||
|
- Run service `stop:` and `reload:` scripts as non-blocking processes,
|
||||||
|
preventing Finit from stalling on long-running helper scripts
|
||||||
|
- Guard shutdown with timer watchdog to detect and debug shutdown hangs
|
||||||
|
- Add `~` condition prefix to propagate reload from a dependency to the
|
||||||
|
dependent service. E.g., `<!~pid/netd>` means not only a regular
|
||||||
|
condition, but when `netd` reloads, restart this service too. Similar
|
||||||
|
to systemd's directive `PropagatesReloadTo=`, but declared on the
|
||||||
|
consumer side. Issue #416
|
||||||
|
- `tmpfiles`: add support for `-E` and `--exclude-prefix` flags
|
||||||
|
contributed by Aaron Andersen
|
||||||
|
|
||||||
|
### Fixes
|
||||||
|
- Fix #464: invalid user:group examples in cgroups.md
|
||||||
|
- Fix #466: elogind path for Debian-based distros, by Jackie Liu
|
||||||
|
- Fix #467: TTY services stuck in restart state after non-zero exit.
|
||||||
|
Throttling logic introduced in v4.15 had duplicate checks causing
|
||||||
|
infinite timer loop, and TTYs lacked default restart timeout
|
||||||
|
- Fix #475: clear pid condition on service collection to fix stale
|
||||||
|
deps. When a service crashes (SIGKILL), the RUNNING → HALTED path
|
||||||
|
bypasses STOPPING where `cond_clear()` is normally called, leaving
|
||||||
|
dependents stuck
|
||||||
|
- Fix #476: dependents not restarted after SIGHUP reload of service in
|
||||||
|
dependency chain. Add `service_step_all()` at end of reload cycle to
|
||||||
|
guarantee convergence after conditions are reasserted. See also the
|
||||||
|
new `~` condition prefix (above) to propagate reload to dependents
|
||||||
|
- Fix #478: fix `<dev/foo>` conditions at boot, conditions that exist
|
||||||
|
before inotify was set up. Found and fixed by Mattias Walström
|
||||||
|
- Fix reload of SIGHUP-capable services incorrectly disrupting their
|
||||||
|
dependents. E.g., `initctl reload syslogd` would stop dbus, dnsmasq,
|
||||||
|
etc. even though syslogd handles SIGHUP gracefully and its PID persists
|
||||||
|
- Only remove managed pidfiles in service cleanup. For SysV services
|
||||||
|
with `pid:!/path`, the pidfile belongs to the service itself and Finit
|
||||||
|
should not delete it
|
||||||
|
- Silence spurious cgroup warnings for short-lived processes where the
|
||||||
|
kernel reaps the child before cgroup assignment completes
|
||||||
|
- Fix handling of already-mounted cgroups in `cgroup_init()`, can occur
|
||||||
|
after switch_root or in container environments
|
||||||
|
- Improve cgroups documentation clarity, grammar, and examples
|
||||||
|
|
||||||
|
|
||||||
|
[4.15][] - 2026-01-01
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
The Finit project now has a new home page: <https://finit-project.github.io>
|
||||||
|
|
||||||
|
### Changes
|
||||||
|
- Change default reboot to SOC reset from WDT reset, issue #460
|
||||||
|
- Bump required versions of libite (v2.6.2) and libuev (v2.4.1)
|
||||||
|
- Allow longer service identifiers (`:id`), up to 64 characters
|
||||||
|
- Allow skipping bootstrap wait (180 sec) with Ctrl-C
|
||||||
|
- Unlock `initctl` commands start/stop/restart/reload service during bootstrap,
|
||||||
|
shutdown, and reboot. Also, allow `initctl reload` in bootstrap. This makes
|
||||||
|
it possible to start manual:yes type services at botostrap, for example, which
|
||||||
|
has been a common feature request
|
||||||
|
- Add support for `clone3()` syscall with atomic cgroup assignment, from Linux
|
||||||
|
kernel 5.3+. Eliminates race conditions where forked processes (e.g., logger
|
||||||
|
processes) ended up in wrong cgroups. Falls back to `fork()` on older kernels
|
||||||
|
- Add support for cgroup delegation, useful for, e.g., container runtimes
|
||||||
|
creating sub-groups for the container instance's processes
|
||||||
|
- Add cgroup leaf name override: `cgroup.system,name:udevd` allows using
|
||||||
|
descriptive names like `/system/udevd/` instead of filename derived names
|
||||||
|
like `/system/10-hotplug/`. Syntax supports combining with other options:
|
||||||
|
`cgroup.system,name:foo,delegate,cpu.max:10000`
|
||||||
|
- Add support for Linux capabilities, allowing services to run with minimal
|
||||||
|
required privileges instead of running as root. Uses the modern IAB API
|
||||||
|
(Inheritable, Ambient, Bounding) from libcap. By Aaron Andersen
|
||||||
|
- Add support for supplementary groups for services. Uses the syntax
|
||||||
|
`@user:group,sup1,sup2` to explicitly specify supplementary groups, in
|
||||||
|
addition to reading group membership from `/etc/group`. By Aaron Andersen
|
||||||
|
- Add CPU throttled information to `initctl` output, showing when a service
|
||||||
|
has been throttled due to reaching its CPU quota
|
||||||
|
- Add memory field to `initctl --json` status output for cgroup-enabled
|
||||||
|
services
|
||||||
|
- Default to user and group `root` (UID 0) for services
|
||||||
|
- Always check that service user and group resolve to valid UID/GID pairs,
|
||||||
|
otherwise log error and refuse to start service
|
||||||
|
- Hide cursor at boot and shutdown for cleaner visual experience
|
||||||
|
- Rename `tty` services early from `init` -> `getty` even though no getty
|
||||||
|
process has been started yet. This to aid in boot timing detection using
|
||||||
|
tools like `bootchartd` (BusyBox version or bootchart2 project) when Finit
|
||||||
|
only shows *"Please press Enter to activate this console."*
|
||||||
|
- Services with `respawn` option (including TTYs) now delay retry on non-zero
|
||||||
|
exit codes instead of immediate respawn. Prevents busy-loop when service
|
||||||
|
fails repeatedly, which on some systems may have a crippling effect
|
||||||
|
|
||||||
|
### Fixes
|
||||||
|
- Fix #453: RTC plugin fixes by Ming Liu, Atlas Copco
|
||||||
|
- Fix #455: ANSI escape sequences logged by tools using glib logging,
|
||||||
|
caused by use of PTY instead of pipe for stdout/stderr redirection
|
||||||
|
- Fix #462: `/dev/pts` mounted with wrong mode (400 instead of 620), causing
|
||||||
|
permission issues with pseudo-terminals
|
||||||
|
- getty: fix terminal scrollback issues after login on console TTY. Mouse
|
||||||
|
scroll wheel and Shift+PgUp/PgDn sometimes would not work properly
|
||||||
|
- Fix flickering and artifacts in `initctl top`
|
||||||
|
- Fix file descriptor leak in `initctl top`
|
||||||
|
- Fix incorrect "max" limit reporting in `initctl [top|cgroup|--json]` output
|
||||||
|
for child cgroups. Resolves effective limits by walking the cgroup hierarchy
|
||||||
|
- Fix issue with running Finit under `bootchartd` (bootchart2 project), always
|
||||||
|
set `PATH` and `SHELL` envs early, before attempting to mount `/proc` et al
|
||||||
|
- Always reset ownership and permissions on TTY device nodes before launching getty
|
||||||
|
- Ensure mount/unmount skips `noauto` entries
|
||||||
|
|
||||||
|
|
||||||
|
[4.14][] - 2025-08-29
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
Minor bug fix release.
|
||||||
|
|
||||||
|
### Changes
|
||||||
|
- Add exit status/signal info when a process dies, by Mattias Berthel
|
||||||
|
- Extend `service kill:SEC` to support up to 300 sec.
|
||||||
|
- Extend `norespawn` debug to cover `service_retry()`
|
||||||
|
- Build *without* libsystemd replacement by default
|
||||||
|
|
||||||
|
### Fixes
|
||||||
|
- Fix #449: ALSA plugin fail-to-build-from-source
|
||||||
|
- Fix `sysv` stop command process environment, should be same as start
|
||||||
|
- Fix state machine ordering issue: enter new config generation *after*
|
||||||
|
services disabled in previous generation have been stopped
|
||||||
|
|
||||||
|
|
||||||
|
[4.13][] - 2025-07-10
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
> [!NOTE]
|
||||||
|
> This release introduce a bare bones `libsystemd` replacement with an
|
||||||
|
> `<systemd/sd-daemon>.h` include file. Other systemd features are the
|
||||||
|
> `reload:script` and `stop:script`, mimicking ExecReload and ExecStop.
|
||||||
|
|
||||||
|
### Changes
|
||||||
|
- `initctl signal` command has been renamed to `initctl kill`
|
||||||
|
- Drop xz tarballs from distribution, gzip is good enough
|
||||||
|
- New `tmpfiles` stand-alone program, refactored from the existing
|
||||||
|
tmpfiles.d support in Finit, by Aaron Andersen, PR #439
|
||||||
|
- `--remove` command runs only the `r` and `R` rules
|
||||||
|
- `--create` is used for all other cases (bootstrap)
|
||||||
|
- All `notify:systemd` services now log with `logit` by default. This
|
||||||
|
because it supports systemd style log severity, leading `"<NUM>"`
|
||||||
|
- Support for quoted arguments to run/task/service options, issue #441
|
||||||
|
- Clear command line arguments after bootstrap, issue #442
|
||||||
|
- Support for `stop:'script [args]'` to stop a sysv/service instead of
|
||||||
|
the common `foo-stop-start.sh stop`, or `SIGTERM`, issue #412
|
||||||
|
- Support for `reload:'script [args]'` to trigger a configuration
|
||||||
|
reload in a service, issue #446
|
||||||
|
|
||||||
|
### Fixes
|
||||||
|
- Fix #437: buffer overflow in `initctl status`
|
||||||
|
- Fix #438: support very long command lines in `initctl ps/top`
|
||||||
|
- Fix #440: broken systemd and s6 readiness notification
|
||||||
|
- Fix #443: build warnings, by Ming Liu, Atlas Copco
|
||||||
|
- Fix #444: handle loooooong arguments, by Aaron Andersen
|
||||||
|
- Fix service's redirected stdout/stderr log priority in fallback mode,
|
||||||
|
when neither `logger` or `logit` is available. This fix also checks
|
||||||
|
for systemd style log severity, leading `"<NUM>"` in log messages
|
||||||
|
- Ensure API socket used by `initctl` is non-blocking (event loop)
|
||||||
|
|
||||||
|
|
||||||
|
[4.12][] - 2025-04-28
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
### Changes
|
||||||
|
- Improve notify:s6 readiness compatibility, by Aaron Andersen
|
||||||
|
- Update `runparts` usage text
|
||||||
|
|
||||||
|
### Fixes
|
||||||
|
- Fix variable overloading in urandom plugin
|
||||||
|
- Fix buffer overwrite in urandom plugin, reported by Aaron Andersen
|
||||||
|
|
||||||
|
|
||||||
|
[4.11][] - 2025-03-27
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
### Changes
|
||||||
|
- Update documentation regarding transition from runlevel S to 2, how
|
||||||
|
run/tasks must "complete" before Finit can move to the next runlevel
|
||||||
|
- Improve argument handling in bundled getty when launching login
|
||||||
|
|
||||||
|
### Fixes
|
||||||
|
- Fix #432: allow services in `setup` state to be stopped. This fixes
|
||||||
|
a serious blocker introduced in 4.10 that prevented systems from
|
||||||
|
being rebooted when any service was in this state
|
||||||
|
- Fix fallback `SIGKILL` when stopping a service with `SIGTERM` does
|
||||||
|
not work. This fixes a serious issue with services not responding to
|
||||||
|
the default `SIGTERM`
|
||||||
|
- Fix pre/post/ready/cleanup script execution if service has an
|
||||||
|
optional `env:file` (leading `-`)
|
||||||
|
- Fix blocked signals for pre/post/ready/cleanup scripts preventing
|
||||||
|
normal shutdown when a service/sysv is stopped in its setup state
|
||||||
|
- Fix issue where a pre:script creates a PID file in `/run` cause the
|
||||||
|
service to move from setup state to running. Any `svc_t` in setup,
|
||||||
|
teardown, or cleanup state should be ignored in the pidfile plugin
|
||||||
|
|
||||||
|
|
||||||
|
[4.10][] - 2025-03-03
|
||||||
---------------------
|
---------------------
|
||||||
|
|
||||||
### Changes
|
### Changes
|
||||||
@@ -22,6 +310,7 @@ All relevant changes are documented in this file.
|
|||||||
- Finit now waits until all `post:scripts` have run before returning
|
- Finit now waits until all `post:scripts` have run before returning
|
||||||
OK to `initctl <reload|runlevel>`. This also applies to the new
|
OK to `initctl <reload|runlevel>`. This also applies to the new
|
||||||
`cleanup:scripts` introduced in this release
|
`cleanup:scripts` introduced in this release
|
||||||
|
- RFC3154 conformance formatting fix for `/dev/kmsg` fallback logging
|
||||||
|
|
||||||
|
|
||||||
[4.9][] - 2025-02-15
|
[4.9][] - 2025-02-15
|
||||||
@@ -88,7 +377,7 @@ All relevant changes are documented in this file.
|
|||||||
|
|
||||||
### Fixes
|
### Fixes
|
||||||
- Fix #397: system shutdown/reboot can block on console input if action
|
- Fix #397: system shutdown/reboot can block on console input if action
|
||||||
is started remotely (ssh). Caused by legact TTY screen size probing,
|
is started remotely (ssh). Caused by legacy TTY screen size probing,
|
||||||
removed from both bootstrap and shutdown/reboot
|
removed from both bootstrap and shutdown/reboot
|
||||||
- Fix #400: both `HOOK_MOUNT_ERROR` and `sulogin()` fail to trigger on
|
- Fix #400: both `HOOK_MOUNT_ERROR` and `sulogin()` fail to trigger on
|
||||||
either mount or `fsck` errors. Problem caused by unresolved status
|
either mount or `fsck` errors. Problem caused by unresolved status
|
||||||
@@ -346,7 +635,7 @@ All relevant changes are documented in this file.
|
|||||||
`/etc/finit.conf`.
|
`/etc/finit.conf`.
|
||||||
|
|
||||||
For the complete experience a new top-level configuration file directive
|
For the complete experience a new top-level configuration file directive
|
||||||
`rcsd PATH` has aslo been added. It in turn can be used by `factory.conf`
|
`rcsd PATH` has also been added. It in turn can be used by `factory.conf`
|
||||||
as follows to override `/etc/finit.d`:
|
as follows to override `/etc/finit.d`:
|
||||||
|
|
||||||
rcsd /etc/factory.d
|
rcsd /etc/factory.d
|
||||||
@@ -929,7 +1218,7 @@ make sure to read the whole change log when upgrading.
|
|||||||
previously hard-coded in Finit, e.g., starting the bundled watchdogd,
|
previously hard-coded in Finit, e.g., starting the bundled watchdogd,
|
||||||
various distro packed udevd and other hotplugging tools
|
various distro packed udevd and other hotplugging tools
|
||||||
* A proper rescue mode has been added. It is started extremely early
|
* A proper rescue mode has been added. It is started extremely early
|
||||||
and is protected with a bundled `suslogin`. Exiting rescue mode now
|
and is protected with a bundled `sulogin`. Exiting rescue mode now
|
||||||
brings up the system as a normal boot, as one expects
|
brings up the system as a normal boot, as one expects
|
||||||
* Support for `sysv` start/stop scripts as well as monitoring forking
|
* Support for `sysv` start/stop scripts as well as monitoring forking
|
||||||
services, stared using `sysv` or `service` stanza
|
services, stared using `sysv` or `service` stanza
|
||||||
@@ -1760,44 +2049,52 @@ Major bug fix release.
|
|||||||
|
|
||||||
* Initial release
|
* Initial release
|
||||||
|
|
||||||
[UNRELEASED]: https://github.com/troglobit/finit/compare/4.9...HEAD
|
[UNRELEASED]: https://github.com/finit-project/finit/compare/4.17...HEAD
|
||||||
[4.9]: https://github.com/troglobit/finit/compare/4.8...4.9
|
[4.17]: https://github.com/finit-project/finit/compare/4.16...4.17
|
||||||
[4.8]: https://github.com/troglobit/finit/compare/4.7...4.8
|
[4.16]: https://github.com/finit-project/finit/compare/4.15...4.16
|
||||||
[4.7]: https://github.com/troglobit/finit/compare/4.6...4.7
|
[4.15]: https://github.com/finit-project/finit/compare/4.14...4.15
|
||||||
[4.6]: https://github.com/troglobit/finit/compare/4.5...4.6
|
[4.14]: https://github.com/finit-project/finit/compare/4.13...4.14
|
||||||
[4.5]: https://github.com/troglobit/finit/compare/4.4...4.5
|
[4.13]: https://github.com/troglobit/finit/compare/4.12...4.13
|
||||||
[4.4]: https://github.com/troglobit/finit/compare/4.3...4.4
|
[4.12]: https://github.com/troglobit/finit/compare/4.11...4.12
|
||||||
[4.3]: https://github.com/troglobit/finit/compare/4.2...4.3
|
[4.11]: https://github.com/troglobit/finit/compare/4.10...4.11
|
||||||
[4.2]: https://github.com/troglobit/finit/compare/4.1...4.2
|
[4.10]: https://github.com/troglobit/finit/compare/4.9...4.10
|
||||||
[4.1]: https://github.com/troglobit/finit/compare/4.0...4.1
|
[4.9]: https://github.com/troglobit/finit/compare/4.8...4.9
|
||||||
[4.0]: https://github.com/troglobit/finit/compare/3.1...4.0
|
[4.8]: https://github.com/troglobit/finit/compare/4.7...4.8
|
||||||
[3.1]: https://github.com/troglobit/finit/compare/3.0...3.1
|
[4.7]: https://github.com/troglobit/finit/compare/4.6...4.7
|
||||||
[3.0]: https://github.com/troglobit/finit/compare/2.4...3.0
|
[4.6]: https://github.com/troglobit/finit/compare/4.5...4.6
|
||||||
[2.4]: https://github.com/troglobit/finit/compare/2.3...2.4
|
[4.5]: https://github.com/troglobit/finit/compare/4.4...4.5
|
||||||
[2.3]: https://github.com/troglobit/finit/compare/2.2...2.3
|
[4.4]: https://github.com/troglobit/finit/compare/4.3...4.4
|
||||||
[2.2]: https://github.com/troglobit/finit/compare/2.1...2.2
|
[4.3]: https://github.com/troglobit/finit/compare/4.2...4.3
|
||||||
[2.1]: https://github.com/troglobit/finit/compare/2.0...2.1
|
[4.2]: https://github.com/troglobit/finit/compare/4.1...4.2
|
||||||
[2.0]: https://github.com/troglobit/finit/compare/1.12...2.0
|
[4.1]: https://github.com/troglobit/finit/compare/4.0...4.1
|
||||||
|
[4.0]: https://github.com/troglobit/finit/compare/3.1...4.0
|
||||||
|
[3.1]: https://github.com/troglobit/finit/compare/3.0...3.1
|
||||||
|
[3.0]: https://github.com/troglobit/finit/compare/2.4...3.0
|
||||||
|
[2.4]: https://github.com/troglobit/finit/compare/2.3...2.4
|
||||||
|
[2.3]: https://github.com/troglobit/finit/compare/2.2...2.3
|
||||||
|
[2.2]: https://github.com/troglobit/finit/compare/2.1...2.2
|
||||||
|
[2.1]: https://github.com/troglobit/finit/compare/2.0...2.1
|
||||||
|
[2.0]: https://github.com/troglobit/finit/compare/1.12...2.0
|
||||||
[1.12]: https://github.com/troglobit/finit/compare/1.11...1.12
|
[1.12]: https://github.com/troglobit/finit/compare/1.11...1.12
|
||||||
[1.11]: https://github.com/troglobit/finit/compare/1.10...1.11
|
[1.11]: https://github.com/troglobit/finit/compare/1.10...1.11
|
||||||
[1.10]: https://github.com/troglobit/finit/compare/1.9...1.10
|
[1.10]: https://github.com/troglobit/finit/compare/1.9...1.10
|
||||||
[1.9]: https://github.com/troglobit/finit/compare/1.8...1.9
|
[1.9]: https://github.com/troglobit/finit/compare/1.8...1.9
|
||||||
[1.8]: https://github.com/troglobit/finit/compare/1.7...1.8
|
[1.8]: https://github.com/troglobit/finit/compare/1.7...1.8
|
||||||
[1.7]: https://github.com/troglobit/finit/compare/1.6...1.7
|
[1.7]: https://github.com/troglobit/finit/compare/1.6...1.7
|
||||||
[1.6]: https://github.com/troglobit/finit/compare/1.5...1.6
|
[1.6]: https://github.com/troglobit/finit/compare/1.5...1.6
|
||||||
[1.5]: https://github.com/troglobit/finit/compare/1.4...1.5
|
[1.5]: https://github.com/troglobit/finit/compare/1.4...1.5
|
||||||
[1.4]: https://github.com/troglobit/finit/compare/1.3...1.4
|
[1.4]: https://github.com/troglobit/finit/compare/1.3...1.4
|
||||||
[1.3]: https://github.com/troglobit/finit/compare/1.2...1.3
|
[1.3]: https://github.com/troglobit/finit/compare/1.2...1.3
|
||||||
[1.2]: https://github.com/troglobit/finit/compare/1.1...1.2
|
[1.2]: https://github.com/troglobit/finit/compare/1.1...1.2
|
||||||
[1.1]: https://github.com/troglobit/finit/compare/1.0...1.1
|
[1.1]: https://github.com/troglobit/finit/compare/1.0...1.1
|
||||||
[1.0]: https://github.com/troglobit/finit/compare/0.9...1.0
|
[1.0]: https://github.com/troglobit/finit/compare/0.9...1.0
|
||||||
[0.9]: https://github.com/troglobit/finit/compare/0.8...0.9
|
[0.9]: https://github.com/troglobit/finit/compare/0.8...0.9
|
||||||
[0.8]: https://github.com/troglobit/finit/compare/0.7...0.8
|
[0.8]: https://github.com/troglobit/finit/compare/0.7...0.8
|
||||||
[0.7]: https://github.com/troglobit/finit/compare/0.6...0.7
|
[0.7]: https://github.com/troglobit/finit/compare/0.6...0.7
|
||||||
[0.6]: https://github.com/troglobit/finit/compare/0.5...0.6
|
[0.6]: https://github.com/troglobit/finit/compare/0.5...0.6
|
||||||
[0.5]: https://github.com/troglobit/finit/compare/0.4...0.5
|
[0.5]: https://github.com/troglobit/finit/compare/0.4...0.5
|
||||||
[0.4]: https://github.com/troglobit/finit/compare/0.3...0.4
|
[0.4]: https://github.com/troglobit/finit/compare/0.3...0.4
|
||||||
[0.3]: https://github.com/troglobit/finit/compare/0.2...0.3
|
[0.3]: https://github.com/troglobit/finit/compare/0.2...0.3
|
||||||
[0.2]: https://github.com/troglobit/finit/compare/0.1...0.2
|
[0.2]: https://github.com/troglobit/finit/compare/0.1...0.2
|
||||||
[libuEv]: https://github.com/troglobit/libuev
|
[libuEv]: https://github.com/troglobit/libuev
|
||||||
[dea3ae8]: https://github.com/troglobit/finit/commit/dea3ae8
|
[dea3ae8]: https://github.com/troglobit/finit/commit/dea3ae8
|
||||||
+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
|
||||||
+31
-36
@@ -1,15 +1,5 @@
|
|||||||
Building
|
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:
|
||||||
@@ -17,14 +7,15 @@ optional plugins to enable. It depends on two external libraries:
|
|||||||
- [libuEv][], the event loop
|
- [libuEv][], the event loop
|
||||||
- [libite][] (-lite), much needed frog DNA
|
- [libite][] (-lite), much needed frog DNA
|
||||||
|
|
||||||
**NOTE:** Most free/open source software that uses `configure` default
|
> [!IMPORTANT]
|
||||||
to install to `/usr/local`. However, some Linux distributions do no
|
> Most free/open source software packages that use `configure` default
|
||||||
longer search that path for installed software, e.g. Fedora and Alpine
|
> to install to `/usr/local`. However, some Linux distributions do no
|
||||||
Linux. To get finit's configure script to find its dependencies you
|
> longer search that path for installed software, e.g. Fedora and Alpine
|
||||||
have to help the `pkg-config` tool a bit if you do not change the
|
> Linux. To get finit's configure script to find its dependencies you
|
||||||
default prefix path:
|
> have to help the `pkg-config` tool a bit if you do not change the
|
||||||
|
> default prefix path:
|
||||||
PKG_CONFIG_LIBDIR=/usr/local/lib/pkgconfig ./configure
|
>
|
||||||
|
> PKG_CONFIG_LIBDIR=/usr/local/lib/pkgconfig ./configure
|
||||||
|
|
||||||
The configure script checks for all dependencies, including the correct
|
The configure script checks for all dependencies, including the correct
|
||||||
version of the above mentioned libraries. Currently required versions:
|
version of the above mentioned libraries. Currently required versions:
|
||||||
@@ -71,12 +62,13 @@ Below are a few of the main switches to configure:
|
|||||||
|
|
||||||
For more configure flags, see <kbd>./configure --help</kbd>
|
For more configure flags, see <kbd>./configure --help</kbd>
|
||||||
|
|
||||||
> **Note:** the configure script is not available in the GIT sources. It is
|
> [!NOTE]
|
||||||
> however included in (officially supported) released tarballs. The
|
> The configure script is not available in the GIT sources. It is
|
||||||
> idea is that you should not need GNU autotools to build, only the
|
> however included in (officially supported) released tarballs. The
|
||||||
> above mentioned dependencies, a POSIX shell, a C compiler and make.
|
> idea is that you should not need GNU autotools to build, only the
|
||||||
> Any contributing to Finit can generate it from `configure.ac` using
|
> above mentioned dependencies, a POSIX shell, a C compiler and make.
|
||||||
> the `autogen.sh` script.
|
> Any contributing to Finit can generate it from `configure.ac` using
|
||||||
|
> the `autogen.sh` script.
|
||||||
|
|
||||||
|
|
||||||
Example
|
Example
|
||||||
@@ -115,10 +107,11 @@ Linux config to:
|
|||||||
|
|
||||||
CONFIG_UEVENT_HELPER_PATH="/sbin/mdev"
|
CONFIG_UEVENT_HELPER_PATH="/sbin/mdev"
|
||||||
|
|
||||||
**Note:** If you run into problems starting Finit, take a look at
|
> [!TIP]
|
||||||
`finit.c`. One of the most common problems is a custom Linux kernel
|
> If you run into problems starting Finit, take a look at `finit.c`.
|
||||||
build that lack `CONFIG_DEVTMPFS`. Another is too much cruft in the
|
> One of the most common problems is a custom Linux kernel build that
|
||||||
system `/etc/fstab`.
|
> lack `CONFIG_DEVTMPFS`. Another is too much cruft in the system
|
||||||
|
> `/etc/fstab`.
|
||||||
|
|
||||||
|
|
||||||
Running
|
Running
|
||||||
@@ -157,8 +150,10 @@ enabled. The default Finit rescue mode configuration is installed into
|
|||||||
|
|
||||||
By default the a root shell, without login, is started.
|
By default the a root shell, without login, is started.
|
||||||
|
|
||||||
> **Note:** in this mode `initctl` will not work. Use the `-f` flag to
|
> [!IMPORTANT]
|
||||||
> force `reboot`, `shutdown`, or `poweroff`.
|
> In rescue mode `initctl` will not work, the same goes for `reboot`,
|
||||||
|
> `shutdown`, and `poweroff` commands, provided they are the Finit
|
||||||
|
> versions of these commands. Use the `-f` flag to force the action.
|
||||||
|
|
||||||
|
|
||||||
Debugging
|
Debugging
|
||||||
@@ -187,10 +182,10 @@ kernel usually reboots: `configure --enable-emergency-shell`. However,
|
|||||||
the behavior of Finit is severely limited when this is enabled, so use
|
the behavior of Finit is severely limited when this is enabled, so use
|
||||||
it only for debugging start up issues when Finit crashes.
|
it only for debugging start up issues when Finit crashes.
|
||||||
|
|
||||||
**NOTE:** Neither of these options should be enabled on production
|
> [!CAUTION]
|
||||||
systems since they can potentially give a user root access.
|
> None of these options should be enabled on production systems since
|
||||||
|
> they can potentially give a user root access.
|
||||||
|
|
||||||
|
[1]: https://github.com/finit-project/finit/releases/download/4.3/finit-4.3.tar.gz
|
||||||
[1]: ftp://troglobit.com/finit/finit-4.3.tar.gz
|
|
||||||
[libuEv]: https://github.com/troglobit/libuev
|
[libuEv]: https://github.com/troglobit/libuev
|
||||||
[libite]: https://github.com/troglobit/libite
|
[libite]: https://github.com/troglobit/libite
|
||||||
+17
-16
@@ -4,10 +4,11 @@ Tips & Tricks with the kernel cmdline
|
|||||||
This document summarizes the different boot parameters that can be
|
This document summarizes the different boot parameters that can be
|
||||||
passed on the Linux kernel command line. Not limited to Finit.
|
passed on the Linux kernel command line. Not limited to Finit.
|
||||||
|
|
||||||
The `bool` setting is one of `on, off, true false, 1, 0`.
|
> [!IMPORTANT]
|
||||||
|
> Remember to use `--` to separate kernel parameters from parameters to
|
||||||
|
> init. E.g., `init=/sbin/finit -- finit.debug rescue`
|
||||||
|
|
||||||
> **NOTE:** remember to use `--` to separate kernel parameters from
|
The `bool` setting is one of `on, off, true false, 1, 0`.
|
||||||
> parameters to init. E.g., `init=/sbin/finit -- finit.debug rescue`
|
|
||||||
|
|
||||||
* `debug`: Enable kernel debug. Debug messages are printed to the
|
* `debug`: Enable kernel debug. Debug messages are printed to the
|
||||||
console until Finit starts up, unless `loglevel=7` (below) is used.
|
console until Finit starts up, unless `loglevel=7` (below) is used.
|
||||||
@@ -28,19 +29,20 @@ 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: `<boot/...>` conditions cannot be cleared with `initctl`!
|
> [!NOTE]
|
||||||
|
> `<boot/...>` conditions cannot be cleared with `initctl`!
|
||||||
|
|
||||||
* `finit.config=/path/to/alternative/finit.conf`: override the
|
* `finit.config=/path/to/alternative/finit.conf`: override the
|
||||||
compile-time bootstrap config file, default:
|
compile-time bootstrap config file, default:
|
||||||
|
|
||||||
./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.
|
||||||
@@ -73,7 +75,7 @@ The `bool` setting is one of `on, off, true false, 1, 0`.
|
|||||||
* `init=/bin/sh`: Bypass system default init and tell kernel to start a
|
* `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*
|
||||||
@@ -88,12 +90,11 @@ The `bool` setting is one of `on, off, true false, 1, 0`.
|
|||||||
* `quiet`: Suppress kernel logging to console, except for warnings and
|
* `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`
|
||||||
|
|
||||||
@@ -114,5 +115,5 @@ The `bool` setting is one of `on, off, true false, 1, 0`.
|
|||||||
|
|
||||||
For more on kernel boot parameters, see the man page [bootparam(7)][].
|
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.
|
||||||
+64
-33
@@ -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"*
|
||||||
@@ -27,11 +14,11 @@ specified separated by comma. Multiple conditions are logically AND'ed
|
|||||||
during evaluation, i.e. all conditions must be satisfied in order for a
|
during evaluation, i.e. all conditions must be satisfied in order for a
|
||||||
service to run.
|
service to run.
|
||||||
|
|
||||||
A special syntax, using a leading `!` in run/task/service conditions,
|
Two special prefixes can be used inside the angle brackets:
|
||||||
denote if a:
|
|
||||||
|
|
||||||
- service does not support `SIGHUP`
|
- `!` -- service does not support `SIGHUP` (noreload), or run/task
|
||||||
- run/task should not block runlevel changes (i.e., bootstrap)
|
should not block runlevel changes (i.e., bootstrap)
|
||||||
|
- `~` -- propagate reload from this dependency, see below
|
||||||
|
|
||||||
Finit guarantees by default that all run/tasks run (at least) once
|
Finit guarantees by default that all run/tasks run (at least) once
|
||||||
per runlevel. For most tasks this is a good default, for example
|
per runlevel. For most tasks this is a good default, for example
|
||||||
@@ -47,9 +34,10 @@ both the `pid/setupd` *and* `pid/zebra` conditions are satisfied. A
|
|||||||
`pid/` condition is satisfied by the corresponding service's PID file
|
`pid/` condition is satisfied by the corresponding service's PID file
|
||||||
being created, i.e., the service's default readiness notification.
|
being created, i.e., the service's default readiness notification.
|
||||||
|
|
||||||
**NOTE:** Conditions also stop services when a condition is no longer
|
> [!IMPORTANT]
|
||||||
asserted. I.e., if the Zebra process above stops or restarts, netd
|
> Conditions also stop services when a condition is no longer asserted.
|
||||||
will also stop or restart.
|
> I.e., if the `zebra` process above stops or restarts, `netd` will also
|
||||||
|
> stop or restart.
|
||||||
|
|
||||||
Another example is `dropbear`, it does not support `SIGHUP`, but we can
|
Another example is `dropbear`, it does not support `SIGHUP`, but we can
|
||||||
also see optional sourcing of arguments from an environment file:
|
also see optional sourcing of arguments from an environment file:
|
||||||
@@ -65,6 +53,30 @@ moving to the next runlevel after bootstrap, so we set `<!>`:
|
|||||||
task [S0123456789] <!sys/pwr/fail> name:pwrfail initctl poweroff -- Power failure, shutting down
|
task [S0123456789] <!sys/pwr/fail> name:pwrfail initctl poweroff -- Power failure, shutting down
|
||||||
|
|
||||||
|
|
||||||
|
Propagating Reload in Dependencies
|
||||||
|
-----------------------------------
|
||||||
|
|
||||||
|
By default, when a service reloads during `initctl reload`, dependent
|
||||||
|
services are paused (`SIGSTOP`) and simply resumed (`SIGCONT`) when the
|
||||||
|
condition is reasserted. This is correct for barrier-style dependencies
|
||||||
|
like `<pid/syslogd>`, where dependents just need syslogd running and do
|
||||||
|
not care if it reloads its config.
|
||||||
|
|
||||||
|
For services that need to react when their upstream reloads, the `~`
|
||||||
|
prefix propagates the reload from the dependency:
|
||||||
|
|
||||||
|
service <pid/svc_a> name:svc_b /sbin/svc_b -- Needs A (barrier)
|
||||||
|
service <!~pid/svc_b> name:svc_c /sbin/svc_c -- Propagate reload from B
|
||||||
|
|
||||||
|
Here, `<~pid/svc_b>` means: propagate a reload of `svc_b` to `svc_c`.
|
||||||
|
When `svc_b` reloads, `svc_c` will be restarted (because of `!`,
|
||||||
|
noreload) instead of merely resumed. If `svc_c` supported `SIGHUP`
|
||||||
|
(no `!` prefix), it would be sent `SIGHUP` instead.
|
||||||
|
|
||||||
|
This is similar to systemd's `PropagatesReloadTo=` directive, but
|
||||||
|
declared on the consumer side rather than the provider side.
|
||||||
|
|
||||||
|
|
||||||
Triggering
|
Triggering
|
||||||
----------
|
----------
|
||||||
|
|
||||||
@@ -88,7 +100,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
|
||||||
|
|
||||||
@@ -106,11 +119,16 @@ on this, see [Internals](#internals).) Thus, after a reconfiguration it
|
|||||||
is up to the "owner" of the condition to convey the new (or possibly
|
is up to the "owner" of the condition to convey the new (or possibly
|
||||||
unchanged) state of it.
|
unchanged) state of it.
|
||||||
|
|
||||||
> **Note:** For `pid/` conditions it is expected that services "touch"
|
|
||||||
> or recreate their PID file on `SIGHUP`.
|
|
||||||
|
|
||||||
Static (one-shot) conditions, like `usr/`, never enter the `flux` state.
|
Static (one-shot) conditions, like `usr/`, never enter the `flux` state.
|
||||||
|
|
||||||
|
> [!IMPORTANT]
|
||||||
|
> For `pid/` conditions it is expected that the service reassert, i.e.,
|
||||||
|
> "touch" or recreate, their PID file on `SIGHUP`. This can be done by
|
||||||
|
> calling `utimensat()` on the PID file. Provided, of course, that the
|
||||||
|
> service supports reloading on `SIGHUP`, otherwise it will be restarted
|
||||||
|
> by Finit when they instead exit on the signal. For such services, use
|
||||||
|
> `<!>` to tell Finit the service does not support `SIGHUP`.
|
||||||
|
|
||||||
|
|
||||||
Built-in Conditions
|
Built-in Conditions
|
||||||
-------------------
|
-------------------
|
||||||
@@ -171,9 +189,10 @@ Built-in conditions:
|
|||||||
- `boot/arg`
|
- `boot/arg`
|
||||||
- `dev/node` and `dev/dir/node`
|
- `dev/node` and `dev/dir/node`
|
||||||
|
|
||||||
**Note:** `up` means administratively up, the interface flag `IFF_UP`.
|
> [!NOTE]
|
||||||
`running` is the `IFF_RUNNING` flag, meaning operatively up. The
|
> Here, `up` means administratively up, the interface flag `IFF_UP`.
|
||||||
difference is that `running` tells if the NIC has link.
|
> `running` is the `IFF_RUNNING` flag, meaning operatively up. The
|
||||||
|
> difference is that `running` tells if the NIC has link.
|
||||||
|
|
||||||
|
|
||||||
Composition
|
Composition
|
||||||
@@ -199,14 +218,19 @@ When Finit configuration files are changed and the `initctl reload`
|
|||||||
command is called, it is expected of services to touch their PID files
|
command is called, it is expected of services to touch their PID files
|
||||||
for Finit to reassert their conditions.
|
for Finit to reassert their conditions.
|
||||||
|
|
||||||
|
Similarly, when a single service is reloaded with `initctl reload NAME`,
|
||||||
|
its conditions are cleared and reasserted, ensuring dependent services
|
||||||
|
are properly updated.
|
||||||
|
|
||||||
Daemons that don't create PID files, or fail to touch them on reload,
|
Daemons that don't create PID files, or fail to touch them on reload,
|
||||||
can be worked around by using the `pid:/path/to/file.pid` syntax in
|
can be worked around by using the `pid:/path/to/file.pid` syntax in
|
||||||
the service stanza for the daemon. It is far from optimal since any
|
the service stanza for the daemon. It is far from optimal since any
|
||||||
synchronization of depending services may fail due to the daemon not
|
synchronization of depending services may fail due to the daemon not
|
||||||
having reinitialized/created their IPC sockets, or similar.
|
having reinitialized/created their IPC sockets, or similar.
|
||||||
|
|
||||||
> **Note:** in versions of Finit prior to v4, the PID conditions were
|
> [!NOTE]
|
||||||
> called 'svc' conditions, and they were far more complex.
|
> In versions of Finit prior to v4, the PID conditions were called 'svc'
|
||||||
|
> conditions, and they were far more complex.
|
||||||
|
|
||||||
|
|
||||||
Debugging
|
Debugging
|
||||||
@@ -269,6 +293,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
|
||||||
@@ -279,6 +305,11 @@ This STOP/CONT handling minimizes the number of unnecessary service
|
|||||||
restarts that would otherwise occur because a depending service was sent
|
restarts that would otherwise occur because a depending service was sent
|
||||||
`SIGHUP` for example.
|
`SIGHUP` for example.
|
||||||
|
|
||||||
|
Services with the `~` prefix are an exception to this rule: when their
|
||||||
|
conditions return to `on` after being in `flux`, the reload is propagated
|
||||||
|
-- the service is reloaded (SIGHUP) or restarted (noreload `!`) instead
|
||||||
|
of simply being resumed.
|
||||||
|
|
||||||
Therefore, any plugin that supplies Finit with conditions must ensure
|
Therefore, any plugin that supplies Finit with conditions must ensure
|
||||||
that their state is updated after each reconfiguration. This can be
|
that their state is updated after each reconfiguration. This can be
|
||||||
done by binding to the `HOOK_SVC_RECONF` hook. For an example of how
|
done by binding to the `HOOK_SVC_RECONF` hook. For an example of how
|
||||||
|
|||||||
-1428
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,186 @@
|
|||||||
|
Linux Capabilities
|
||||||
|
==================
|
||||||
|
|
||||||
|
Finit supports Linux capabilities, allowing services to run with minimal
|
||||||
|
required privileges instead of running as root. This significantly improves
|
||||||
|
system security by following the principle of least privilege.
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
Linux capabilities divide the traditional root privileges into distinct units
|
||||||
|
that can be independently granted to processes. For example, a web server only
|
||||||
|
needs the capability to bind to privileged ports (< 1024), not full root access.
|
||||||
|
|
||||||
|
Finit uses the modern IAB (Inheritable, Ambient, Bounding) API from libcap,
|
||||||
|
which is the same approach used by other modern service managers like dinit.
|
||||||
|
|
||||||
|
## Basic Usage
|
||||||
|
|
||||||
|
Capabilities are specified using the `caps:` directive in service configuration:
|
||||||
|
|
||||||
|
```conf
|
||||||
|
service [2345] name:nginx \
|
||||||
|
@www-data:www-data \
|
||||||
|
caps:^cap_net_bind_service \
|
||||||
|
/usr/sbin/nginx -g 'daemon off;' \
|
||||||
|
-- Web server
|
||||||
|
```
|
||||||
|
|
||||||
|
This example allows nginx to bind to privileged ports (like 80 and 443) while
|
||||||
|
running as the unprivileged `www-data` user.
|
||||||
|
|
||||||
|
## IAB Format
|
||||||
|
|
||||||
|
The capability string uses the IAB (Inheritable, Ambient, Bounding) format
|
||||||
|
with the following prefixes:
|
||||||
|
|
||||||
|
- `^` **Ambient** (and Inheritable) - **Recommended for most use cases**
|
||||||
|
- Capabilities survive across `exec()` calls
|
||||||
|
- Automatically raised to effective after exec
|
||||||
|
- Example: `^cap_net_bind_service`
|
||||||
|
|
||||||
|
- `%` **Inheritable** only
|
||||||
|
- Requires the executed binary to have matching file capabilities
|
||||||
|
- Less common, more complex setup
|
||||||
|
- Example: `%cap_net_admin`
|
||||||
|
|
||||||
|
- `!` **Bounding** - Block capability from bounding set
|
||||||
|
- Prevents the service from ever acquiring this capability
|
||||||
|
- Useful for security hardening
|
||||||
|
- Example: `!cap_sys_admin`
|
||||||
|
|
||||||
|
Multiple capabilities can be specified as a comma-separated list:
|
||||||
|
|
||||||
|
```conf
|
||||||
|
caps:^cap_net_raw,^cap_net_admin,^cap_net_bind_service
|
||||||
|
```
|
||||||
|
|
||||||
|
## Common Use Cases
|
||||||
|
|
||||||
|
### Web Server (Privileged Ports)
|
||||||
|
|
||||||
|
Allow a web server to bind to ports 80 and 443 without running as root:
|
||||||
|
|
||||||
|
```conf
|
||||||
|
service [2345] name:webserver \
|
||||||
|
@www-data:www-data \
|
||||||
|
caps:^cap_net_bind_service \
|
||||||
|
/usr/sbin/nginx -g 'daemon off;'
|
||||||
|
```
|
||||||
|
|
||||||
|
### Network Monitoring (Raw Sockets)
|
||||||
|
|
||||||
|
Allow packet capture without root privileges:
|
||||||
|
|
||||||
|
```conf
|
||||||
|
service [2345] name:tcpdump \
|
||||||
|
@tcpdump \
|
||||||
|
caps:^cap_net_raw,^cap_net_admin \
|
||||||
|
/usr/sbin/tcpdump -i eth0 -w /var/log/capture.pcap
|
||||||
|
```
|
||||||
|
|
||||||
|
### NTP Daemon (System Time)
|
||||||
|
|
||||||
|
Allow time synchronization without full root:
|
||||||
|
|
||||||
|
```conf
|
||||||
|
service [2345] name:ntpd \
|
||||||
|
@ntp \
|
||||||
|
caps:^cap_sys_time,^cap_sys_nice \
|
||||||
|
/usr/sbin/ntpd -n
|
||||||
|
```
|
||||||
|
|
||||||
|
## Available Capabilities
|
||||||
|
|
||||||
|
Common capabilities include (see `man 7 capabilities` for the complete list):
|
||||||
|
|
||||||
|
- `cap_chown` - Make arbitrary changes to file UIDs and GIDs
|
||||||
|
- `cap_dac_override` - Bypass file read, write, and execute permission checks
|
||||||
|
- `cap_dac_read_search` - Bypass file read permission checks
|
||||||
|
- `cap_fowner` - Bypass permission checks on operations that normally require filesystem UID
|
||||||
|
- `cap_kill` - Bypass permission checks for sending signals
|
||||||
|
- `cap_net_admin` - Perform various network-related operations
|
||||||
|
- `cap_net_bind_service` - Bind to privileged ports (< 1024)
|
||||||
|
- `cap_net_raw` - Use RAW and PACKET sockets
|
||||||
|
- `cap_setgid` - Make arbitrary manipulations of process GIDs
|
||||||
|
- `cap_setuid` - Make arbitrary manipulations of process UIDs
|
||||||
|
- `cap_sys_admin` - Perform system administration operations (very powerful!)
|
||||||
|
- `cap_sys_module` - Load and unload kernel modules
|
||||||
|
- `cap_sys_nice` - Raise process nice value and change scheduling
|
||||||
|
- `cap_sys_time` - Set system clock
|
||||||
|
|
||||||
|
## Security Best Practices
|
||||||
|
|
||||||
|
1. **Use the minimum required capabilities**
|
||||||
|
- Only grant what the service actually needs
|
||||||
|
- Don't grant `cap_sys_admin` unless absolutely necessary
|
||||||
|
|
||||||
|
2. **Specify a user (preferably non-root)**
|
||||||
|
- The `@user` directive is **required** for `caps:` to take effect
|
||||||
|
- For ambient capabilities (`^`), use a non-root user (not `@root`)
|
||||||
|
- Example: `@www-data`, `@nginx`, `@tcpdump`
|
||||||
|
|
||||||
|
3. **Use ambient capabilities (`^`)**
|
||||||
|
- The `^` prefix ensures capabilities survive exec()
|
||||||
|
- Simpler than setting file capabilities on binaries
|
||||||
|
|
||||||
|
4. **Block dangerous capabilities**
|
||||||
|
- Use `!` to explicitly block capabilities you don't want
|
||||||
|
- Example: `!cap_sys_admin,!cap_sys_module`
|
||||||
|
|
||||||
|
5. **Test with `getpcaps`**
|
||||||
|
- After starting a service, verify its capabilities:
|
||||||
|
```bash
|
||||||
|
getpcaps $(pidof nginx)
|
||||||
|
```
|
||||||
|
- Should show only the capabilities you granted
|
||||||
|
|
||||||
|
## Verification
|
||||||
|
|
||||||
|
After configuring a service with capabilities, verify it works correctly:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Start the service
|
||||||
|
initctl start webserver
|
||||||
|
|
||||||
|
# Check the process capabilities
|
||||||
|
getpcaps $(pidof nginx)
|
||||||
|
|
||||||
|
# Should show something like:
|
||||||
|
# 12345: cap_net_bind_service=eip
|
||||||
|
|
||||||
|
# Verify the user
|
||||||
|
ps -o user,pid,cmd -p $(pidof nginx)
|
||||||
|
|
||||||
|
# Should show the service running as the specified user
|
||||||
|
```
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
- Linux kernel 4.3+ (for ambient capabilities support)
|
||||||
|
- libcap library installed
|
||||||
|
- Finit built with `--enable-libcap`
|
||||||
|
|
||||||
|
## Limitations
|
||||||
|
|
||||||
|
- The `caps:` directive requires `@user` to be specified for it to take effect
|
||||||
|
- Without `@user`, the service runs as root with full capabilities and
|
||||||
|
the `caps:` configuration is silently ignored
|
||||||
|
- You can use `@root` with `caps:`, but see below about ambient capabilities
|
||||||
|
- For ambient capabilities (`^`, recommended), the user **must be non-root**
|
||||||
|
- Using `@root` with `caps:^...` will not work effectively, as ambient
|
||||||
|
capabilities are only added to the effective set when euid ≠ 0
|
||||||
|
- Use inheritable (`%`) or bounding (`!`) capabilities with `@root` if needed
|
||||||
|
- Services without `caps:` use standard privilege dropping:
|
||||||
|
- Services with `@user` (non-root) have no special capabilities
|
||||||
|
- Services without `@user` run as root with full capabilities
|
||||||
|
- Some very old binaries may not work correctly with ambient capabilities
|
||||||
|
- File system capabilities are not managed by Finit (use `setcap` for that)
|
||||||
|
|
||||||
|
## See Also
|
||||||
|
|
||||||
|
- [capabilities(7)](https://man7.org/linux/man-pages/man7/capabilities.7.html) - Linux capabilities overview
|
||||||
|
- [cap_iab(3)](https://man7.org/linux/man-pages/man3/cap_iab.3.html) - IAB capability API documentation
|
||||||
|
- [setcap(8)](https://man7.org/linux/man-pages/man8/setcap.8.html) - Set file capabilities
|
||||||
|
- [getcap(8)](https://man7.org/linux/man-pages/man8/getcap.8.html) - Query file capabilities
|
||||||
|
- [capsh(1)](https://man7.org/linux/man-pages/man1/capsh.1.html) - Capability shell wrapper
|
||||||
@@ -0,0 +1,215 @@
|
|||||||
|
Finit provides three different cgroup directives for controlling resource allocation:
|
||||||
|
|
||||||
|
1. **Top-level cgroup definition**: `cgroup NAME settings`
|
||||||
|
- Defines a top-level cgroup (e.g., `init`, `system`, `user`) with default settings
|
||||||
|
- Space-separated syntax
|
||||||
|
- Example: `cgroup system cpu.weight:9700`
|
||||||
|
|
||||||
|
2. **Global cgroup selector**: `cgroup.NAME[,options]` (standalone directive)
|
||||||
|
- Sets the default cgroup for subsequent services in a `.conf` file
|
||||||
|
- Dot-separated with optional comma-separated options
|
||||||
|
- Example: `cgroup.maint` or `cgroup.system,delegate`
|
||||||
|
|
||||||
|
3. **Per-service cgroup option**: `cgroup.NAME[,options]` or `cgroup:options`
|
||||||
|
- Overrides the cgroup for a specific service
|
||||||
|
- Part of the service directive line
|
||||||
|
- Example: `service [...] cgroup.maint,mem.max:1G /path/to/cmd`
|
||||||
|
|
||||||
|
> [!NOTE]
|
||||||
|
> Linux cgroups and details surrounding values are not explained in the
|
||||||
|
> Finit documentation. The Linux admin-guide covers this well:
|
||||||
|
> <https://www.kernel.org/doc/html/latest/admin-guide/cgroup-v2.html>
|
||||||
|
|
||||||
|
Top-level Cgroup Definition
|
||||||
|
----------------------------
|
||||||
|
|
||||||
|
**Syntax:** `cgroup NAME settings`
|
||||||
|
|
||||||
|
# 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.
|
||||||
|
|
||||||
|
Global Cgroup Selector
|
||||||
|
----------------------
|
||||||
|
|
||||||
|
**Syntax:** `cgroup.NAME[,options]` (standalone directive)
|
||||||
|
|
||||||
|
To select a different top-level cgroup, e.g. `maint/`, for a group of
|
||||||
|
run/task/service directives in a `.conf` file, use the `cgroup.NAME`
|
||||||
|
directive as a standalone line:
|
||||||
|
|
||||||
|
cgroup.maint
|
||||||
|
service [...] <...> /path/to/foo args -- description
|
||||||
|
service [...] <...> /path/to/bar args -- description
|
||||||
|
|
||||||
|
Both services will run in the `maint/` cgroup.
|
||||||
|
|
||||||
|
You can also include options with the global selector:
|
||||||
|
|
||||||
|
cgroup.system,delegate
|
||||||
|
service [...] <...> /path/to/foo args -- description
|
||||||
|
|
||||||
|
Per-Service Cgroup Option
|
||||||
|
--------------------------
|
||||||
|
|
||||||
|
**Syntax:** `cgroup.NAME[,options]` or `cgroup:options` (service option)
|
||||||
|
|
||||||
|
To override the cgroup for a specific service, use the `cgroup.NAME`
|
||||||
|
option within the service directive:
|
||||||
|
|
||||||
|
service [...] <...> cgroup.maint /path/to/foo args -- description
|
||||||
|
|
||||||
|
This form also allows per-service limits. Two syntaxes are supported:
|
||||||
|
|
||||||
|
**New comma-separated syntax (recommended):**
|
||||||
|
|
||||||
|
service [...] <...> cgroup.maint,cpu.max:10000,mem.max:655360 /path/to/foo args -- description
|
||||||
|
|
||||||
|
**Old colon-separated syntax (legacy):**
|
||||||
|
|
||||||
|
service [...] <...> cgroup.maint:cpu.max:10000,mem.max:655360 /path/to/foo args -- description
|
||||||
|
|
||||||
|
You can also apply options to the current default cgroup (without changing it)
|
||||||
|
using the `cgroup:options` syntax:
|
||||||
|
|
||||||
|
service [...] <...> cgroup:cpu.max:10000,mem.max:655360 /path/to/foo args -- description
|
||||||
|
|
||||||
|
Both syntaxes work identically. The new comma-separated syntax is recommended
|
||||||
|
as it's more consistent with other option parsing in Finit.
|
||||||
|
|
||||||
|
Note 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.
|
||||||
|
|
||||||
|
### Overriding Cgroup Leaf Names
|
||||||
|
|
||||||
|
By default, the cgroup leaf directory name is derived from the service
|
||||||
|
configuration filename (without the `.conf` extension). For example, a
|
||||||
|
service defined in `system/10-hotplug.conf` would create a cgroup at
|
||||||
|
`/sys/fs/cgroup/system/10-hotplug/` by default.
|
||||||
|
|
||||||
|
To use a more descriptive name (recommended for clarity), you can specify
|
||||||
|
`name:` in the cgroup directive:
|
||||||
|
|
||||||
|
service [...] <...> cgroup.system,name:udevd /lib/systemd/systemd-udevd -- Device event daemon
|
||||||
|
|
||||||
|
This creates the cgroup at `/sys/fs/cgroup/system/udevd/` instead.
|
||||||
|
|
||||||
|
The syntax supports combining the name override with other options:
|
||||||
|
|
||||||
|
service [...] <...> cgroup.system,name:udevd,cpu.max:10000 /lib/systemd/systemd-udevd -- Device event daemon
|
||||||
|
|
||||||
|
Or with delegation:
|
||||||
|
|
||||||
|
service [2345] @podman:podman \
|
||||||
|
cgroup.containers,name:podman,delegate,mem.max:4G \
|
||||||
|
/usr/bin/podman system service -- Podman API
|
||||||
|
|
||||||
|
A daemon using `SCHED_RR` currently needs to run outside the default cgroups.
|
||||||
|
|
||||||
|
service [...] <...> cgroup.root /path/to/daemon arg -- Real-Time process
|
||||||
|
|
||||||
|
Cgroup Delegation
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
For services that need to create their own child cgroups (container runtimes
|
||||||
|
like Docker, Podman, systemd-nspawn, LXC), use the `delegate` option:
|
||||||
|
|
||||||
|
service [2345] @dockerd:dockerd \
|
||||||
|
cgroup.system,delegate /usr/bin/dockerd -- Docker daemon
|
||||||
|
|
||||||
|
Or with the old colon syntax:
|
||||||
|
|
||||||
|
service [2345] @dockerd:dockerd \
|
||||||
|
cgroup.system:delegate /usr/bin/dockerd -- Docker daemon
|
||||||
|
|
||||||
|
This allows the container runtime to:
|
||||||
|
|
||||||
|
- Create child cgroups for containers
|
||||||
|
- Manage controller settings for containers
|
||||||
|
- Move processes between cgroups
|
||||||
|
|
||||||
|
When delegation is enabled, Finit:
|
||||||
|
|
||||||
|
1. Creates the service cgroup as a **domain group** (not a leaf)
|
||||||
|
2. Enables all available controllers in `cgroup.subtree_control`
|
||||||
|
3. Changes ownership of delegation files to the service user
|
||||||
|
4. Moves the service process to the cgroup root
|
||||||
|
5. Lets the container runtime manage its own subdirectories
|
||||||
|
|
||||||
|
**Requirements:**
|
||||||
|
|
||||||
|
- The service should specify `@user:group` for proper ownership
|
||||||
|
- Controllers are delegated from the parent cgroup
|
||||||
|
|
||||||
|
**Example with additional config (new syntax):**
|
||||||
|
|
||||||
|
service [2345] @podman:podman \
|
||||||
|
cgroup.containers,delegate,mem.max:4G \
|
||||||
|
/usr/bin/podman system service -- Podman API
|
||||||
|
|
||||||
|
**Or with old syntax:**
|
||||||
|
|
||||||
|
service [2345] @podman:podman \
|
||||||
|
cgroup.containers:delegate,mem.max:4G \
|
||||||
|
/usr/bin/podman system service -- Podman API
|
||||||
|
|
||||||
|
Both examples delegate the cgroup while also setting a 4GB memory limit.
|
||||||
|
|
||||||
|
**Container template example:**
|
||||||
|
|
||||||
|
Here's a real-world example from [Infix OS](https://github.com/kernelkit/infix)
|
||||||
|
for running rootful podman container instances using delegation:
|
||||||
|
|
||||||
|
sysv log:prio:local1,tag:%i kill:30 pid:!/run/container:%i.pid \
|
||||||
|
pre:0,/usr/sbin/container cleanup:0,/usr/sbin/container \
|
||||||
|
cgroup.system,delegate \
|
||||||
|
[2345] <!> :%i container -n %i -- container %i
|
||||||
|
|
||||||
|
This template uses `sysv` type with delegation, demonstrating that cgroup
|
||||||
|
delegation works with different service types, not just `service`.
|
||||||
|
|
||||||
|
**Cgroup structure with delegation:**
|
||||||
|
|
||||||
|
Initially, the service process runs directly in the cgroup root:
|
||||||
|
|
||||||
|
/sys/fs/cgroup/system/container@web/
|
||||||
|
├── cgroup.procs (service PID - owned by service user)
|
||||||
|
├── cgroup.subtree_control (+cpu +memory +io - owned by service user)
|
||||||
|
└── (container children will be created here)
|
||||||
|
|
||||||
|
Once the container runtime creates child cgroups (e.g., `libpod-*/`), cgroups v2
|
||||||
|
enforces the "no internal processes" rule. When Finit detects this (`EBUSY` error),
|
||||||
|
it automatically creates an `supervisor/` subdirectory and moves service-related
|
||||||
|
processes there:
|
||||||
|
|
||||||
|
/sys/fs/cgroup/system/container@web/
|
||||||
|
├── cgroup.procs (empty)
|
||||||
|
├── cgroup.subtree_control (+cpu +memory +io)
|
||||||
|
├── supervisor/ (service processes)
|
||||||
|
│ └── cgroup.procs (conmon PIDs, etc.)
|
||||||
|
└── libpod-$HASH/ (container processes)
|
||||||
|
└── cgroup.procs (container PIDs)
|
||||||
|
|
||||||
|
This happens automatically - no configuration needed. Without delegation, the
|
||||||
|
cgroup would be a leaf and the container runtime could not create child cgroups.
|
||||||
@@ -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/finit-project/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,187 @@
|
|||||||
|
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
|
||||||
|
[setrlimit(2)](https://man7.org/linux/man-pages/man2/setrlimit.2.html),
|
||||||
|
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,141 @@
|
|||||||
|
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:
|
||||||
|
|
||||||
|
* `caps:...` -- see the [Linux Capabilities](capabilities.md) section
|
||||||
|
* `cgroup.NAME[,opts]` or `cgroup:opts` -- 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)
|
||||||
|
* `tty:<dev>` -- see [Controlling TTY](tty.md#controlling-tty)
|
||||||
|
* `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
|
||||||
|
* `remain:yes` -- for `run` and `task` only. Prevents the task from
|
||||||
|
re-running on runlevel re-entry and ensures the `post:` script runs
|
||||||
|
when the task is explicitly stopped or leaves its valid runlevels.
|
||||||
|
Similar to systemd's `RemainAfterExit=yes`. See [Task and Run](task-and-run.md)
|
||||||
|
for more details
|
||||||
|
* `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,232 @@
|
|||||||
|
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`.
|
||||||
|
|
||||||
|
With `pid:!/path`, the file belongs to the service: Finit reads it
|
||||||
|
but does not create or remove it. The one exception is *stale*
|
||||||
|
cleanup — if the service dies without removing its own pidfile
|
||||||
|
(SIGKILL, OOM, segfault), and the file still names the just-reaped
|
||||||
|
PID, Finit removes it before the next retry. This prevents daemons
|
||||||
|
that refuse to start on an existing pidfile (e.g. `dbus-daemon`)
|
||||||
|
from getting stuck in a crash-restart loop.
|
||||||
|
|
||||||
|
**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.
|
||||||
|
|
||||||
|
The condition can be prefixed with `!` and/or `~`:
|
||||||
|
|
||||||
|
- `<!pid/zebra>` -- `ospfd` does not support `SIGHUP` (noreload)
|
||||||
|
- `<~pid/zebra>` -- propagate reload from `zebra` to `ospfd`
|
||||||
|
- `<!~pid/zebra>` -- both: noreload and propagate reload
|
||||||
|
|
||||||
|
For details, see the [Finit Conditions](../conditions.md) document.
|
||||||
|
|
||||||
|
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[,SUPP,...]]`, where group and supplementary groups are
|
||||||
|
optional, like this:
|
||||||
|
|
||||||
|
run [2345] @joe:users logger "Hello world"
|
||||||
|
|
||||||
|
Finit reads the user's supplementary group membership from `/etc/group`
|
||||||
|
automatically. Any groups the user belongs to will be inherited by
|
||||||
|
the service.
|
||||||
|
|
||||||
|
To specify additional supplementary groups beyond those in `/etc/group`,
|
||||||
|
append them after the primary group, separated by commas:
|
||||||
|
|
||||||
|
service @caddy:caddy,ssl-cert /usr/bin/caddy run
|
||||||
|
|
||||||
|
This runs the `caddy` service as user `caddy`, with primary group
|
||||||
|
`caddy`, inheriting any groups `caddy` is a member of in `/etc/group`,
|
||||||
|
plus the additional `ssl-cert` group. This is useful when a service
|
||||||
|
needs access to resources owned by groups not listed in `/etc/group`.
|
||||||
|
|
||||||
|
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,87 @@
|
|||||||
|
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.
|
||||||
|
|
||||||
|
|
||||||
|
remain:yes
|
||||||
|
----------
|
||||||
|
|
||||||
|
By default, a `run` or `task` will re-run each time its runlevel is
|
||||||
|
entered, and its `post:` script does not run on completion.
|
||||||
|
|
||||||
|
With `remain:yes`, the task runs once and does not re-run on runlevel
|
||||||
|
re-entry:
|
||||||
|
|
||||||
|
task [2345] remain:yes /usr/sbin/setup-firewall -- Firewall setup
|
||||||
|
|
||||||
|
This has the following effects:
|
||||||
|
|
||||||
|
* The task does not re-run on runlevel re-entry
|
||||||
|
* The `post:` script runs when:
|
||||||
|
- The task is explicitly stopped (`initctl stop NAME`)
|
||||||
|
- The task leaves its valid runlevels (e.g., runlevel change)
|
||||||
|
|
||||||
|
This is useful for tasks that set up persistent state where:
|
||||||
|
|
||||||
|
* Cleanup should only happen on explicit stop or when leaving valid runlevels
|
||||||
|
* The setup should not be re-run on every runlevel entry
|
||||||
|
|
||||||
|
**Example:** Setting up firewall rules with cleanup on shutdown:
|
||||||
|
|
||||||
|
```
|
||||||
|
task [2345] remain:yes \
|
||||||
|
post:/usr/sbin/teardown-firewall \
|
||||||
|
/usr/sbin/setup-firewall -- Firewall setup
|
||||||
|
```
|
||||||
|
|
||||||
|
The firewall rules are created once. The `post:` script runs when
|
||||||
|
entering runlevel 0 (halt) or 6 (reboot), or on explicit stop.
|
||||||
|
|
||||||
|
> [!NOTE]
|
||||||
|
> The `remain:yes` option is not supported for bootstrap-only tasks
|
||||||
|
> (tasks with only runlevel S). Bootstrap tasks are deleted immediately
|
||||||
|
> after completion, and their `post:` scripts never run. A warning is
|
||||||
|
> logged if `remain:yes` is used on such tasks.
|
||||||
@@ -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,113 @@
|
|||||||
|
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
|
||||||
|
|
||||||
|
Controlling TTY for Services
|
||||||
|
----------------------------
|
||||||
|
|
||||||
|
The `tty:<dev>` option gives a `run`, `task`, or `service` a controlling
|
||||||
|
terminal on the given device. The device is opened, set as the
|
||||||
|
controlling terminal for the session (after `setsid()`), and connected to
|
||||||
|
the process's stdin, stdout, and stderr. A default `TERM` environment
|
||||||
|
variable is set based on the device type: `vt102` for serial lines and
|
||||||
|
`linux` for virtual terminals.
|
||||||
|
|
||||||
|
`<dev>` may be a device node like `/dev/ttyS0`, or the special keyword
|
||||||
|
`@console` (see above). Note that `@console` expands only to the
|
||||||
|
first console, not all.
|
||||||
|
|
||||||
|
When `tty:` is combined with `log:`, stdout and stderr are redirected
|
||||||
|
to the log sink instead of the TTY, but stdin remains connected to the
|
||||||
|
TTY device.
|
||||||
|
|
||||||
|
> The `tty:<dev>` option is for `run`, `task`, and `service` stanzas only.
|
||||||
|
> The `tty` directive itself (for getty/login) has its own syntax, see
|
||||||
|
> above.
|
||||||
|
|
||||||
|
**Example:**
|
||||||
|
|
||||||
|
service [2345] tty:/dev/ttyS0 /usr/sbin/foo -- Foo on serial console
|
||||||
|
task [S] tty:@console my-setup-script -- Board bringup on console
|
||||||
+105
-45
@@ -1,79 +1,139 @@
|
|||||||
Distro Recommendations
|
Distro Recommendations
|
||||||
======================
|
======================
|
||||||
|
|
||||||
By default Finit uses the following directories for configuration files:
|
Finit supports two directory layouts for managing service configurations:
|
||||||
|
|
||||||
|
1. **Simple layout** - all configuration files directly in `/etc/finit.d/`
|
||||||
|
2. **Distro layout** - separate `available/` and `enabled/` directories
|
||||||
|
|
||||||
|
The distro layout is recommended for distributions that need clear
|
||||||
|
separation between installed and enabled services, and want to use the
|
||||||
|
`initctl enable/disable` commands for service management.
|
||||||
|
|
||||||
|
## Simple Layout
|
||||||
|
|
||||||
|
Finit supports using a flat directory structure:
|
||||||
|
|
||||||
```
|
```
|
||||||
/etc/
|
/etc/
|
||||||
|-- finit.d/ -- Regular (enabled) services
|
|-- finit.d/ -- All enabled services
|
||||||
| |-- lighttpd.conf
|
| |-- lighttpd.conf
|
||||||
| `- *.conf
|
| `- *.conf
|
||||||
|-- finit.conf -- Bootstrap tasks and services
|
|-- finit.conf -- Bootstrap tasks and services
|
||||||
:
|
:
|
||||||
```
|
```
|
||||||
|
|
||||||
To enable a service one simply drops a small configuration file in the
|
In this layout, you enable a service by placing its `.conf` file in
|
||||||
`/etc/finit.d/` directory. This practice works with systems that
|
`/etc/finit.d/` and disable it by removing the file. This works well for
|
||||||
keep disabled services elsewhere, or generates them as needed from some
|
embedded systems or custom setups where services are managed by other tools
|
||||||
other tool.
|
or generated dynamically.
|
||||||
|
|
||||||
Distributions, however, may want a clearer separation of enabled and
|
> [!NOTE] No tooling support
|
||||||
available (installed but not enabled) services. They may even want to
|
> The `initctl enable/disable` commands **do not work** with this layout.
|
||||||
customize the directories used, for brand labeling or uniformity.
|
> You must manually manage files in `/etc/finit.d/`.
|
||||||
|
|
||||||
To that end Finit allows for a sub-directory `/etc/finit.d/available/`
|
## Distro Layout
|
||||||
where installed but disabled services can reside. Adding a symlink to a
|
|
||||||
configuration in this sub-directory enables the service, but it will not
|
|
||||||
be started.
|
|
||||||
|
|
||||||
To change the default configuration directory and configuration file
|
Distributions typically want clearer separation between available (installed)
|
||||||
names the Finit `configure` script offers the following two options at
|
and enabled services. Finit supports this through the `available/` and
|
||||||
build time:
|
`enabled/` subdirectories:
|
||||||
|
|
||||||
|
```
|
||||||
|
/etc/
|
||||||
|
|-- finit.d/
|
||||||
|
| |-- available/ -- Installed but disabled services
|
||||||
|
| | |-- httpd.conf
|
||||||
|
| | |-- ntpd.conf
|
||||||
|
| | `-- sshd.conf
|
||||||
|
| |-- enabled/ -- Enabled services (symlinks)
|
||||||
|
| | `- sshd.conf -- Symlink to ../available/sshd.conf
|
||||||
|
|-- finit.conf -- Bootstrap tasks and services
|
||||||
|
:
|
||||||
|
```
|
||||||
|
|
||||||
|
In this layout:
|
||||||
|
- **available/** contains all installed service configurations
|
||||||
|
- **enabled/** contains symlinks to configurations that should start at boot
|
||||||
|
- Services are enabled/disabled by creating/removing symlinks
|
||||||
|
|
||||||
|
> [!IMPORTANT] Recommended
|
||||||
|
> This is the recommended layout. In fact, the `initctl enable/disable`
|
||||||
|
> commands **require** this layout with both `available/` and `enabled/`
|
||||||
|
> directories and will not work without it.
|
||||||
|
|
||||||
|
## Managing Services with initctl
|
||||||
|
|
||||||
|
When using the distro layout, the `initctl` tool provides convenient commands
|
||||||
|
for managing service configurations:
|
||||||
|
|
||||||
|
```
|
||||||
|
list List all .conf in /etc/finit.d/
|
||||||
|
enable <CONF> Enable .conf by creating symlink in enabled/
|
||||||
|
disable <CONF> Disable .conf by removing symlink from enabled/
|
||||||
|
reload Reload *.conf in /etc/finit.d/ (activate changes)
|
||||||
|
```
|
||||||
|
|
||||||
|
Example usage:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Enable sshd (creates enabled/sshd.conf -> ../available/sshd.conf)
|
||||||
|
initctl enable sshd
|
||||||
|
|
||||||
|
# Disable httpd (removes enabled/httpd.conf symlink)
|
||||||
|
initctl disable httpd
|
||||||
|
|
||||||
|
# Apply changes (reload configuration and start/stop services)
|
||||||
|
initctl reload
|
||||||
|
```
|
||||||
|
|
||||||
|
The `.conf` suffix is optional - `initctl` adds it automatically if missing.
|
||||||
|
|
||||||
|
> [!NOTE] Remember `initctl reload`
|
||||||
|
> Changes made with `enable`/`disable` take effect only after running
|
||||||
|
> `initctl reload`, unless Finit was built with `--enable-auto-reload`
|
||||||
|
> which automatically detects and applies configuration changes.
|
||||||
|
|
||||||
|
### Service Overrides
|
||||||
|
|
||||||
|
The `initctl` tool only operates on symlinks in the `enabled/` directory.
|
||||||
|
If you place a regular (non-symlink) `.conf` file directly in the parent
|
||||||
|
directory (e.g., `/etc/finit.d/`), `initctl` will ignore it. This allows
|
||||||
|
you to create system-level overrides that cannot be accidentally disabled
|
||||||
|
by package management tools.
|
||||||
|
|
||||||
|
## Customizing Directory Paths
|
||||||
|
|
||||||
|
Distributions can customize the directory names and locations at build time
|
||||||
|
using the Finit `configure` script:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
./configure --with-rcsd=/etc/init.d --with-config=/etc/init.d/init.conf
|
./configure --with-rcsd=/etc/init.d --with-config=/etc/init.d/init.conf
|
||||||
```
|
```
|
||||||
|
|
||||||
> **Note:** remember `--prefix` et al as well, the default is likely
|
This changes the default `/etc/finit.d/` to `/etc/init.d/` and moves the
|
||||||
> *not* what you want. See the [build docs][1] for details.
|
bootstrap configuration file accordingly.
|
||||||
|
|
||||||
The resulting directory structure is depicted below. Please notice how
|
> [!IMPORTANT] Remember to set `--prefix`
|
||||||
`/etc/finit.conf` now resides in the same sub-directory as a non-symlink
|
> Remember to set `--prefix` and related options appropriately. The default
|
||||||
`/etc/init.d/init.conf`:
|
> prefix is `/usr/local`, which is likely not what you want for a system
|
||||||
|
> init. See the [build documentation][1] for details.
|
||||||
|
|
||||||
|
Example with custom paths:
|
||||||
|
|
||||||
```
|
```
|
||||||
/etc/
|
/etc/
|
||||||
|-- init.d/
|
|-- init.d/
|
||||||
| |-- available/ -- Regular (disabled) services
|
| |-- available/ -- Installed services
|
||||||
| | |-- httpd.conf
|
| | |-- httpd.conf
|
||||||
| | |-- ntpd.conf
|
| | |-- ntpd.conf
|
||||||
| | `-- sshd.conf
|
| | `-- sshd.conf
|
||||||
| |-- sshd.conf -- Symlink to available/sshd.conf
|
| |-- enabled/ -- Enabled services (symlinks)
|
||||||
|
| | `- sshd.conf -- Symlink to ../available/sshd.conf
|
||||||
| `- init.conf -- Bootstrap tasks and services
|
| `- init.conf -- Bootstrap tasks and services
|
||||||
:
|
:
|
||||||
```
|
```
|
||||||
|
|
||||||
To facilitate the task of managing configurations, be it a service,
|
Notice how both the service directory and bootstrap configuration file now
|
||||||
task, run, or other stanza, the `initctl` tool has a a few built-in
|
use the custom `/etc/init.d/` path specified at build time.
|
||||||
commands:
|
|
||||||
|
|
||||||
```
|
|
||||||
list List all .conf in /etc/finit.d/
|
|
||||||
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/ (activates changes)
|
|
||||||
```
|
|
||||||
|
|
||||||
To enable a service like `sshd.conf`, above, use
|
|
||||||
|
|
||||||
initctl enable sshd
|
|
||||||
|
|
||||||
The `.conf` suffix is not needed, `initctl` adds it implicitly if it is
|
|
||||||
missing. The `disable` command works in a similar fashion.
|
|
||||||
|
|
||||||
Note, however, that `initctl` only operates on symlinks and it always
|
|
||||||
requires the `available/` sub-directory. Any non-symlink in the parent
|
|
||||||
directory, here `/etc/init.d/`, will be considered a system override by
|
|
||||||
`initctl`.
|
|
||||||
|
|
||||||
[1]: build.md#configure
|
[1]: build.md#configure
|
||||||
+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/finit-project/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;
|
||||||
|
}
|
||||||
+314
@@ -0,0 +1,314 @@
|
|||||||
|
Finit Features
|
||||||
|
==============
|
||||||
|
|
||||||
|
This page highlights some of Finit's key features with examples and usage
|
||||||
|
scenarios. For complete documentation, configuration syntax, and advanced
|
||||||
|
options, see the [Configuration](config/index.md) section.
|
||||||
|
|
||||||
|
**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
|
||||||
|
|
||||||
|
|
||||||
|
**Linux Capabilities**
|
||||||
|
|
||||||
|
Finit supports Linux capabilities, allowing services to run with minimal
|
||||||
|
required privileges instead of running as root. This improves security by
|
||||||
|
following the principle of least privilege.
|
||||||
|
|
||||||
|
```conf
|
||||||
|
service [2345] name:nginx \
|
||||||
|
www-data:www-data \
|
||||||
|
caps:^cap_net_bind_service \
|
||||||
|
/usr/sbin/nginx -g 'daemon off;'
|
||||||
|
```
|
||||||
|
|
||||||
|
In this example, nginx runs as the unprivileged `www-data` user but retains
|
||||||
|
the ability to bind to privileged ports (80, 443) through the
|
||||||
|
`cap_net_bind_service` capability.
|
||||||
|
|
||||||
|
The `caps:` directive uses the IAB (Inheritable, Ambient, Bounding) format:
|
||||||
|
- `^` = Ambient (recommended) - capabilities survive exec()
|
||||||
|
- `%` = Inheritable only - requires file capabilities
|
||||||
|
- `!` = Bounding - block from acquiring capability
|
||||||
|
|
||||||
|
Multiple capabilities can be specified as comma-separated:
|
||||||
|
|
||||||
|
```conf
|
||||||
|
caps:^cap_net_raw,^cap_net_admin,!cap_sys_admin
|
||||||
|
```
|
||||||
|
|
||||||
|
See the [Linux Capabilities](config/capabilities.md) section for detailed
|
||||||
|
information, examples, and security best practices.
|
||||||
|
|
||||||
|
|
||||||
|
**Supplementary Groups**
|
||||||
|
|
||||||
|
Finit supports supplementary groups for services, allowing them to access
|
||||||
|
resources owned by multiple groups without running as root. This complements
|
||||||
|
capabilities for fine-grained privilege control.
|
||||||
|
|
||||||
|
```conf
|
||||||
|
service @caddy:caddy,ssl-cert /usr/bin/caddy run
|
||||||
|
```
|
||||||
|
|
||||||
|
In this example, the Caddy web server runs as user `caddy` with primary group
|
||||||
|
`caddy`, but also has access to resources owned by the `ssl-cert` group (such
|
||||||
|
as TLS certificates).
|
||||||
|
|
||||||
|
Finit automatically reads the user's supplementary group membership from
|
||||||
|
`/etc/group`. Additional groups can be specified explicitly using the syntax
|
||||||
|
`@user:group,sup1,sup2,...`.
|
||||||
|
|
||||||
|
See the [Non-privileged Services](config/services.md#non-privileged-services)
|
||||||
|
section for more information.
|
||||||
|
|
||||||
|
|
||||||
|
**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.
|
||||||
|
|
||||||
|
|
||||||
|
**Service Management**
|
||||||
|
|
||||||
|
Finit includes the `initctl` tool for managing services and system state at
|
||||||
|
runtime. Key capabilities include:
|
||||||
|
|
||||||
|
- **Enable/Disable services**: Manage which services start at boot by moving
|
||||||
|
configuration files between `/etc/finit.d/available` and
|
||||||
|
`/etc/finit.d/enabled`
|
||||||
|
- **Start/Stop/Restart**: Control individual services without requiring a
|
||||||
|
full system reboot
|
||||||
|
- **Status monitoring**: View service state, PID, uptime, and resource usage
|
||||||
|
- **Condition management**: Set and clear user-defined conditions to control
|
||||||
|
service dependencies
|
||||||
|
- **Cgroup monitoring**: Real-time process and resource monitoring with
|
||||||
|
`initctl top`, similar to the traditional `top` command but cgroup-aware
|
||||||
|
|
||||||
|
Example commands:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
initctl enable myservice # Enable service for next boot
|
||||||
|
initctl start myservice # Start service now
|
||||||
|
initctl status # Show all services
|
||||||
|
initctl top # Interactive resource monitor
|
||||||
|
initctl cond set usr/custom # Set custom condition
|
||||||
|
```
|
||||||
|
|
||||||
|
See the [Commands & Status](initctl.md) section for complete documentation.
|
||||||
|
|
||||||
|
|
||||||
|
**Rescue Mode**
|
||||||
|
|
||||||
|
Finit provides a built-in rescue mode for system recovery and maintenance.
|
||||||
|
When booting with the `rescue` kernel parameter, the system enters a
|
||||||
|
protected maintenance shell.
|
||||||
|
|
||||||
|
If the bundled `sulogin` program is available (from Finit, util-linux, or
|
||||||
|
BusyBox), you'll be prompted for the root password before accessing the
|
||||||
|
maintenance shell. This provides secure access for system recovery.
|
||||||
|
|
||||||
|
If `sulogin` is not available, Finit falls back to reading
|
||||||
|
`/lib/finit/rescue.conf` and boots the system in a limited maintenance mode.
|
||||||
|
|
||||||
|
```
|
||||||
|
# Kernel command line
|
||||||
|
linux /vmlinuz root=/dev/sda1 rescue
|
||||||
|
```
|
||||||
|
|
||||||
|
In rescue mode, `initctl` will not work. After fixing the problem, use
|
||||||
|
`reboot -f` to force reboot.
|
||||||
|
|
||||||
|
Rescue mode can be disabled at build time with `configure --without-rescue`.
|
||||||
|
|
||||||
|
See the [Rescue Mode](config/rescue.md) section for more information.
|
||||||
|
|
||||||
|
|
||||||
|
**Switch Root**
|
||||||
|
|
||||||
|
Finit supports switching from an initramfs to a real root filesystem using
|
||||||
|
the built-in `initctl switch-root` command. This allows Finit to serve as
|
||||||
|
the init system in an initramfs for early boot tasks (LUKS unlock, LVM
|
||||||
|
activation, network boot) before transitioning to the real root.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# In initramfs, after mounting the real root:
|
||||||
|
initctl switch-root /mnt/root
|
||||||
|
```
|
||||||
|
|
||||||
|
The switch-root operation:
|
||||||
|
|
||||||
|
1. Runs the `HOOK_SWITCH_ROOT` hook for cleanup
|
||||||
|
2. Stops all services gracefully
|
||||||
|
3. Moves virtual filesystems (`/dev`, `/proc`, `/sys`, `/run`) to the new root
|
||||||
|
4. Deletes initramfs contents to free memory
|
||||||
|
5. Pivots to the new root and execs the new init
|
||||||
|
|
||||||
|
See the [Switch Root](switchroot.md) section for complete documentation.
|
||||||
|
|
||||||
|
|
||||||
|
[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,82 @@
|
|||||||
|
Introduction
|
||||||
|
============
|
||||||
|
|
||||||
|
{ align=right width=40% }
|
||||||
|
|
||||||
|
> 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](config/runlevels.md), defined per service
|
||||||
|
* [One-shot tasks](config/task-and-run.md), [services](config/services.md) (daemons), or [SysV init][4] start/stop scripts
|
||||||
|
* [Runparts](config/runparts.md) and `/etc/rc.local` support
|
||||||
|
* Process supervision similar to [systemd][]
|
||||||
|
* Fine-grained privilege control:
|
||||||
|
- [Linux capabilities](config/capabilities.md) for minimal required privileges
|
||||||
|
- [Supplementary groups](config/services.md#non-privileged-services) for multi-group resource access
|
||||||
|
* [Sourcing environment files](config/service-env.md)
|
||||||
|
* [Conditions](conditions.md) for network/process/custom dependencies
|
||||||
|
* [Readiness notification](config/service-sync.md); 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](config/service-wrappers.md)
|
||||||
|
* Rudimentary [templating support](config/templating.md)
|
||||||
|
* [Tooling](initctl.md) to enable/disable services
|
||||||
|
* [Automatic reload](features.md#automatic-reload) of modified configuration files (optional)
|
||||||
|
* [Built-in getty](config/tty.md)
|
||||||
|
* Built-in watchdog, with support for hand-over to [watchdogd][]
|
||||||
|
* Built-in support for Debian/BusyBox [`/etc/network/interfaces`][3]
|
||||||
|
* [Cgroups v2](config/cgroups.md), both configuration and monitoring in [`initctl top`](initctl.md)
|
||||||
|
* [Plugin support](plugins.md) for customization
|
||||||
|
* Proper [rescue mode](config/rescue.md) with bundled `sulogin` for protected maintenance shell
|
||||||
|
* [Switch root](switchroot.md) support for initramfs-to-real-root transitions
|
||||||
|
* Integration with [watchdogd][] for full system supervision
|
||||||
|
* [Logging](config/logging.md) 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/finit-project/finit
|
||||||
|
[dinit]: https://davmac.org/projects/dinit/
|
||||||
|
[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/
|
||||||
+167
@@ -0,0 +1,167 @@
|
|||||||
|
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
|
||||||
|
switch-root NEWROOT [INIT] Switch to new root filesystem (initramfs only)
|
||||||
|
|
||||||
|
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
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
Switch Root
|
||||||
|
-----------
|
||||||
|
|
||||||
|
The `switch-root` command is used when running Finit in an initramfs to
|
||||||
|
transition to the real root filesystem. This is similar to the standalone
|
||||||
|
`switch_root(8)` utility but integrated into Finit.
|
||||||
|
|
||||||
|
```
|
||||||
|
initctl switch-root /mnt/root [/sbin/init]
|
||||||
|
```
|
||||||
|
|
||||||
|
Requirements:
|
||||||
|
|
||||||
|
- Must be run during runlevel S (bootstrap) or runlevel 1
|
||||||
|
- The new root must be a mount point (different device than /)
|
||||||
|
- Can only be used when Finit is running as PID 1 in an initramfs
|
||||||
|
|
||||||
|
For complete documentation and usage examples, see the dedicated
|
||||||
|
[Switch Root](switchroot.md) section.
|
||||||
@@ -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.
|
||||||
+32
-23
@@ -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.
|
||||||
@@ -35,9 +29,10 @@ For your convenience a set of *optional* plugins are available:
|
|||||||
files distributed with Finit. It is read first but can be overridden
|
files distributed with Finit. It is read first but can be overridden
|
||||||
by any of the standard tmpfiles.d directories, e.g. `/etc/tmpfiles.d`.
|
by any of the standard tmpfiles.d directories, e.g. `/etc/tmpfiles.d`.
|
||||||
|
|
||||||
> **Note:** On an embedded system both `/var` and `/run` can be `tmpfs`
|
> [!NOTE]
|
||||||
> RAM disks and `/dev` is usually a `devtmpfs`. This must be defined
|
> On an embedded system both `/var` and `/run` can be `tmpfs` RAM
|
||||||
> in the `/etc/fstab` file and in the Linux kernel config.
|
> disks and `/dev` is usually a `devtmpfs`. This must be defined in
|
||||||
|
> the `/etc/fstab` file and in the Linux kernel config.
|
||||||
|
|
||||||
* *dbus.so*: Setup and start system message bus, D-Bus, at boot.
|
* *dbus.so*: Setup and start system message bus, D-Bus, at boot.
|
||||||
_Optional plugin._
|
_Optional plugin._
|
||||||
@@ -63,8 +58,9 @@ For your convenience a set of *optional* plugins are available:
|
|||||||
|
|
||||||
Enabled by default.
|
Enabled by default.
|
||||||
|
|
||||||
> See the [Services](config.md#services) section in the configuration
|
> [!TIP]
|
||||||
> guide for an example how to run `mdevd`, alternative to plain mdev.
|
> See the [Services](config/services.md) section in the configuration
|
||||||
|
> guide for an example how to run `mdevd`, alternative to plain mdev.
|
||||||
|
|
||||||
* *rtc.so*: Restore and save system clock from/to RTC on boot/halt.
|
* *rtc.so*: Restore and save system clock from/to RTC on boot/halt.
|
||||||
Enabled by default.
|
Enabled by default.
|
||||||
@@ -89,16 +85,17 @@ For your convenience a set of *optional* plugins are available:
|
|||||||
|
|
||||||
set index 1234
|
set index 1234
|
||||||
|
|
||||||
**Note:** unlike the traditional .conf `module` directive, which load
|
Since these tasks run in the background, they return `[ OK ]` at boot,
|
||||||
any listed module immediately, this plugin creates a background `task`
|
unless the modprobe tool does not exist. Check syslog for warnings
|
||||||
which load the module(s) in the background. The program is modprobe,
|
and the actual status of the operation using `initctl`.
|
||||||
`/sbin/modprobe`, which you can override per .conf file:
|
|
||||||
|
|
||||||
set modprobe /path/to/maybe-a-modprobe-wrapper
|
> [!IMPORTANT]
|
||||||
|
> Unlike the traditional .conf `module` directive, which load any listed
|
||||||
Since these tasks run in the background, they usually return `[ OK ]`
|
> module immediately, this plugin creates a background `task` which load
|
||||||
at boot, unless the modprobe tool does not exist. Check syslog for
|
> the module(s) in the background. The program is modprobe,
|
||||||
warnings and the actual status of the operation using `initctl`.
|
> `/sbin/modprobe`, which you can override per .conf file:
|
||||||
|
>
|
||||||
|
> set modprobe /path/to/maybe-a-modprobe-wrapper
|
||||||
|
|
||||||
* *netlink.so*: Listens to Linux kernel Netlink events for gateway and
|
* *netlink.so*: Listens to Linux kernel Netlink events for gateway and
|
||||||
interfaces. These events are then sent to the Finit service monitor
|
interfaces. These events are then sent to the Finit service monitor
|
||||||
@@ -132,7 +129,7 @@ the second is the condition name and hook script path. A hook script is
|
|||||||
a plain shell script, or program, that does a very small dedicated job
|
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,
|
||||||
@@ -158,8 +155,10 @@ hook points:
|
|||||||
EOF
|
EOF
|
||||||
$ chmod +x /libexec/finit/hook/sys/down/foo.sh
|
$ chmod +x /libexec/finit/hook/sys/down/foo.sh
|
||||||
|
|
||||||
> **Note:** to use hook scripts, even for pre-bootstrap and pre-shutdown
|
> [!IMPORTANT]
|
||||||
> tasks, you must build with `configure --enable-hook-scripts-plugin`.
|
> To use hook scripts, even for pre-bootstrap and pre-shutdown tasks,
|
||||||
|
> you must build with `configure --enable-hook-scripts-plugin`.
|
||||||
|
|
||||||
|
|
||||||
### Bootstrap Hooks
|
### Bootstrap Hooks
|
||||||
|
|
||||||
@@ -206,6 +205,16 @@ hook points:
|
|||||||
new runlevel have been been stopped. When the hook has completed,
|
new runlevel have been been stopped. When the hook has completed,
|
||||||
Finit continues to start all services in the new runlevel.
|
Finit continues to start all services in the new runlevel.
|
||||||
|
|
||||||
|
### Switch Root Hooks
|
||||||
|
|
||||||
|
* `HOOK_SWITCH_ROOT`, `hook/sys/switchroot`: Called when
|
||||||
|
`initctl switch-root` is issued, before the transition begins. Use
|
||||||
|
this hook to save state, unmount initramfs-only filesystems, or perform
|
||||||
|
cleanup before switching to the new root. Only runs when Finit is
|
||||||
|
operating as PID 1 in an initramfs.
|
||||||
|
|
||||||
|
See the [Switch Root](switchroot.md) section for more information.
|
||||||
|
|
||||||
### Shutdown Hooks
|
### Shutdown Hooks
|
||||||
|
|
||||||
* `HOOK_NETWORK_DN`, `hook/net/down`: Called right after having changed
|
* `HOOK_NETWORK_DN`, `hook/net/down`: Called right after having changed
|
||||||
|
|||||||
@@ -0,0 +1,25 @@
|
|||||||
|
Requirements
|
||||||
|
============
|
||||||
|
|
||||||
|
Finit is capable of running on both desktop/server systems with udev and
|
||||||
|
embedded systems that usually come with BusyBox mdev. Some systems have
|
||||||
|
systemd-udev or eudev today instead of the original udev, Finit probes
|
||||||
|
for all of them at runtime and expects `/dev/` to be a writable file
|
||||||
|
system using `devtmpfs`. It is also possible to run on a statically set
|
||||||
|
up `/dev` if needed. It is however not a good idea to have both udev
|
||||||
|
and mdev installed at the same time, this will lead to unpredictable
|
||||||
|
results.
|
||||||
|
|
||||||
|
At boot Finit calls either `mdev` or `udevd` to populate `/dev`, this is
|
||||||
|
done slightly differently and on systems with udev you might want to add
|
||||||
|
the following one-shot task early in your `/etc/finit.conf`:
|
||||||
|
|
||||||
|
```conf
|
||||||
|
run [S] udevadm settle --timeout=120 -- Waiting for udev
|
||||||
|
```
|
||||||
|
|
||||||
|
Finit has a built-in Getty for TTYs, but requires a working `/bin/login`
|
||||||
|
or `/bin/sh`, if no TTYs are configured in `/etc/finit.conf`.
|
||||||
|
|
||||||
|
For a fully operational system `/var`, `/run` and `/tmp` must be set up
|
||||||
|
properly in `/etc/fstab` -- which is iterated over at boot.
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
Runlevel Support
|
||||||
|
================
|
||||||
|
|
||||||
|
Basic support for [runlevels][5] is included in Finit from v1.8. By
|
||||||
|
default all services, tasks, run commands and TTYs listed without a set
|
||||||
|
of runlevels get a default set `[234]` assigned. The default runlevel
|
||||||
|
after boot is 2.
|
||||||
|
|
||||||
|
Finit supports runlevels 0-9, and S, with 0 reserved for halt, 6 reboot
|
||||||
|
and S for services that only run at bootstrap. Runlevel 1 is the single
|
||||||
|
user level, where usually no networking is enabled. In Finit this is
|
||||||
|
more of a policy for the user to define. Normally only runlevels 1-6
|
||||||
|
are used, and even more commonly, only the default runlevel is used.
|
||||||
|
|
||||||
|
To specify an allowed set of runlevels for a `service`, `run` command,
|
||||||
|
`task`, or `tty`, add `[NNN]` to your `/etc/finit.conf`, like this:
|
||||||
|
|
||||||
|
```
|
||||||
|
service [S12345] syslogd -n -x -- System log daemon
|
||||||
|
run [S] /etc/init.d/acpid start -- Starting ACPI Daemon
|
||||||
|
task [S] /etc/init.d/kbd start -- Preparing console
|
||||||
|
service [S12345] <pid/syslogd> klogd -n -x -- Kernel log daemon
|
||||||
|
|
||||||
|
tty [12345] /dev/tty1
|
||||||
|
tty [2] /dev/tty2
|
||||||
|
tty [2] /dev/tty3
|
||||||
|
tty [2] /dev/tty4
|
||||||
|
tty [2] /dev/tty5
|
||||||
|
tty [2] /dev/tty6
|
||||||
|
```
|
||||||
|
|
||||||
|
In this example syslogd is first started, in parallel, and then acpid is
|
||||||
|
called using a conventional SysV init script. It is called with the run
|
||||||
|
command, meaning the following task command to start the kbd script is
|
||||||
|
not called until the acpid init script has fully completed. Then the
|
||||||
|
keyboard setup script is called in parallel with klogd as a monitored
|
||||||
|
service.
|
||||||
|
|
||||||
|
Again, tasks and services are started in parallel, while run commands
|
||||||
|
are called in the order listed and subsequent commands are not started
|
||||||
|
until a run command has completed. Also, task and run commands are run
|
||||||
|
in a shell, so pipes and redirects can be used.
|
||||||
|
|
||||||
|
The following examples illustrate this. Bootstrap task and run commands
|
||||||
|
are also removed when they have completed, `initctl show` will not list
|
||||||
|
them.
|
||||||
|
|
||||||
|
```
|
||||||
|
task [S] echo "foo" | cat >/tmp/bar
|
||||||
|
run [S] echo "$HOME" >/tmp/secret
|
||||||
|
```
|
||||||
|
|
||||||
|
Switching between runlevels can be done by calling init with a single
|
||||||
|
argument, e.g. <kbd>init 5</kbd>, or using `initctl runlevel 5`, both
|
||||||
|
switch to runlevel 5. When changing runlevels Finit also automatically
|
||||||
|
reloads all `.conf` files in the `/etc/finit.d/` directory. So if you
|
||||||
|
want to set a new system config, switch to runlevel 1, change all config
|
||||||
|
files in the system, and touch all `.conf` files in `/etc/finit.d`
|
||||||
|
before switching back to the previous runlevel again — that way Finit
|
||||||
|
can both stop old services and start any new ones for you, without
|
||||||
|
rebooting the system.
|
||||||
|
|
||||||
|
|
||||||
|
[5]: https://en.wikipedia.org/wiki/Runlevel
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
Runparts & `/etc/rc.local`
|
||||||
|
==========================
|
||||||
|
|
||||||
|
At the end of the boot, when all bootstrap (`S`) tasks and services have
|
||||||
|
started, but not networking, Finit calls its built-in [run-parts(8)][]
|
||||||
|
command on any configured `runparts <DIR>` directory. This happens just
|
||||||
|
before changing to the configured runlevel (default 2). (Networking is
|
||||||
|
enabled just prior to changing from single user mode.)
|
||||||
|
|
||||||
|
```shell
|
||||||
|
runparts /etc/rc.d/
|
||||||
|
```
|
||||||
|
|
||||||
|
Right after the runlevel change when all services have started properly,
|
||||||
|
`/etc/rc.local` is called.
|
||||||
|
|
||||||
|
No configuration stanza in `/etc/finit.conf` is required for `rc.local`.
|
||||||
|
If it exists and is an executable shell script Finit calls it at the very
|
||||||
|
end of the boot, before calling the `HOOK_SYSTEM_UP`. See more in the
|
||||||
|
[Hook Scripts](plugins.md#hooks) section.
|
||||||
|
|
||||||
|
|
||||||
|
### Limitations
|
||||||
|
|
||||||
|
It is not possible to call Finit via signals or use `initctl` in any
|
||||||
|
runparts or `/etc/rc.local` script. This because Finit is single
|
||||||
|
threaded and is calling these scripts in a blocking fashion at the end
|
||||||
|
of runlevel S, at which point the event loop has not yet been started.
|
||||||
|
|
||||||
|
The event loop is the whole thing which Finit is built around, except
|
||||||
|
for runlevel S, which remains a slow procession through a lot of set up,
|
||||||
|
with a few hooks and blocking call outs to external scripts.
|
||||||
|
|
||||||
|
However, not all `initctl` commands are prohibited. Supported commands:
|
||||||
|
|
||||||
|
- `initctl cond`: only operate on files in `/run/finit/cond`
|
||||||
|
- `initctl enable/disable`: enabled run/task/service is activated on
|
||||||
|
the runlevel change from S to 2
|
||||||
|
- `initctl touch/show/create/delete/list`: `create`, provided the
|
||||||
|
non-interactive mode is used, again changes take effect in the
|
||||||
|
runlevel change directly after bootstrap
|
||||||
|
- `initctl -f reboot/poweroff/halt`: provided the `-f` flag is used to
|
||||||
|
force direct kernel commands
|
||||||
|
|
||||||
|
> [!TIP]
|
||||||
|
> you can set a `usr/` condition in `/etc/rc.local` and have a
|
||||||
|
> service/task in runlevel 2 depend on it to execute.
|
||||||
|
|
||||||
|
[run-parts(8)]: https://manpages.debian.org/cgi-bin/man.cgi?query=run-parts
|
||||||
+13
-43
@@ -1,15 +1,13 @@
|
|||||||
Finit Services
|
|
||||||
==============
|
|
||||||
|
|
||||||
Starting & Monitoring
|
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:
|
||||||
|
|
||||||
@@ -22,10 +20,12 @@ Finit can *not* start and monitor a daemon that:
|
|||||||
| ✔ | No | No | Yes, optionally |
|
| ✔ | No | No | Yes, optionally |
|
||||||
| ✘ | Yes | No | No |
|
| ✘ | Yes | No | No |
|
||||||
|
|
||||||
> **Note:** PID files is one mechanism used to assert conditions to
|
> [!NOTE]
|
||||||
> synchronize the start and stop of other, dependent, services.
|
> PID files is one mechanism used to assert conditions to synchronize
|
||||||
|
> the start and stop of other, dependent, services. 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
|
||||||
@@ -39,49 +39,19 @@ In this example the resulting files to watch for are `/run/serv.pid` and
|
|||||||
`/var/run/serv.pid`, respectively. On most modern Linux systems this is
|
`/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,149 @@
|
|||||||
|
Switch Root
|
||||||
|
===========
|
||||||
|
|
||||||
|
Finit supports switching from an initramfs to a real root filesystem
|
||||||
|
using the `initctl switch-root` command. This is useful for systems
|
||||||
|
that use an initramfs for early boot (LUKS, LVM, network boot, etc.)
|
||||||
|
and need to transition to the real root before starting services.
|
||||||
|
|
||||||
|
|
||||||
|
Usage
|
||||||
|
-----
|
||||||
|
|
||||||
|
```sh
|
||||||
|
initctl switch-root NEWROOT [INIT]
|
||||||
|
```
|
||||||
|
|
||||||
|
- `NEWROOT`: Path to the mounted new root filesystem (e.g., `/mnt/root`)
|
||||||
|
- `INIT`: Optional path to init on the new root (default: `/sbin/init`)
|
||||||
|
|
||||||
|
|
||||||
|
Requirements
|
||||||
|
------------
|
||||||
|
|
||||||
|
1. Must be run during runlevel S (bootstrap) or runlevel 1
|
||||||
|
2. `NEWROOT` must be a mount point (different device than /)
|
||||||
|
3. `INIT` must exist and be executable on the new root
|
||||||
|
4. Finit must be running as PID 1 (in initramfs)
|
||||||
|
|
||||||
|
|
||||||
|
How It Works
|
||||||
|
------------
|
||||||
|
|
||||||
|
1. Runs `HOOK_SWITCH_ROOT` for any cleanup scripts/plugins
|
||||||
|
2. Runs `HOOK_SHUTDOWN` to notify plugins
|
||||||
|
3. Stops all services and kills remaining processes
|
||||||
|
4. Exits all plugins gracefully
|
||||||
|
5. Moves `/dev`, `/proc`, `/sys`, `/run` to new root
|
||||||
|
6. Deletes initramfs contents (if on tmpfs/ramfs) to free memory
|
||||||
|
7. Moves new root mount to `/`
|
||||||
|
8. Chroots to new root
|
||||||
|
9. Reopens `/dev/console` for stdin/stdout/stderr
|
||||||
|
10. Execs new init as PID 1
|
||||||
|
|
||||||
|
|
||||||
|
Example: Initramfs finit.conf
|
||||||
|
-----------------------------
|
||||||
|
|
||||||
|
Configuration file `/etc/finit.conf` in the initramfs:
|
||||||
|
|
||||||
|
```
|
||||||
|
# /etc/finit.conf in initramfs
|
||||||
|
|
||||||
|
# Mount the real root filesystem
|
||||||
|
run [S] name:mount-root /bin/mount /dev/sda1 /mnt/root -- Mounting root filesystem
|
||||||
|
|
||||||
|
# Switch to real root after mount completes
|
||||||
|
run [S] name:switch-root /sbin/initctl switch-root /mnt/root -- Switching to real root
|
||||||
|
```
|
||||||
|
|
||||||
|
For more complex setups (LUKS, LVM, etc.):
|
||||||
|
|
||||||
|
```
|
||||||
|
# Unlock LUKS volume
|
||||||
|
# The tty:@console stanza is required so cryptsetup can prompt for a passphrase
|
||||||
|
run [S] name:cryptsetup tty:@console /sbin/cryptsetup open /dev/sda2 cryptroot -- Unlocking encrypted root
|
||||||
|
|
||||||
|
# Activate LVM
|
||||||
|
run [S] name:lvm /sbin/lvm vgchange -ay -- Activating LVM volumes
|
||||||
|
|
||||||
|
# Mount root
|
||||||
|
run [S] name:mount-root /bin/mount /dev/vg0/root /mnt/root -- Mounting root
|
||||||
|
|
||||||
|
# Switch root
|
||||||
|
run [S] name:switch-root /sbin/initctl switch-root /mnt/root -- Switching to real root
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
Example: Using Runlevel 1 for Switch Root
|
||||||
|
-----------------------------------------
|
||||||
|
|
||||||
|
For more complex initramfs setups where ordering of tasks becomes
|
||||||
|
difficult in runlevel S, you can perform the switch-root in runlevel 1:
|
||||||
|
|
||||||
|
```
|
||||||
|
# /etc/finit.conf in initramfs
|
||||||
|
|
||||||
|
# Start mdevd for device handling
|
||||||
|
service [S] name:mdevd notify:s6 /sbin/mdevd -D %n -- Device event daemon
|
||||||
|
run [S] name:coldplug <service/mdevd/ready> /sbin/mdevd-coldplug -- Coldplug devices
|
||||||
|
|
||||||
|
# Mount the real root filesystem (after devices are ready)
|
||||||
|
run [S] name:mount-root <run/coldplug/success> /bin/mount /dev/sda1 /mnt/root -- Mounting root
|
||||||
|
|
||||||
|
# Transition to runlevel 1 after all S tasks complete
|
||||||
|
# The switch-root runs cleanly in runlevel 1
|
||||||
|
run [1] name:switch-root /sbin/initctl switch-root /mnt/root -- Switching to real root
|
||||||
|
```
|
||||||
|
|
||||||
|
This approach separates the initramfs setup (runlevel S) from the
|
||||||
|
switch-root operation (runlevel 1), making task ordering simpler.
|
||||||
|
|
||||||
|
|
||||||
|
Hooks
|
||||||
|
-----
|
||||||
|
|
||||||
|
The `HOOK_SWITCH_ROOT` hook runs before the switch begins. Use it for:
|
||||||
|
|
||||||
|
- Saving state to the new root
|
||||||
|
- Unmounting initramfs-only mounts
|
||||||
|
- Cleanup tasks
|
||||||
|
|
||||||
|
Plugins can register for `HOOK_SWITCH_ROOT` just like other hooks:
|
||||||
|
|
||||||
|
```c
|
||||||
|
static void my_switch_root_hook(void *arg)
|
||||||
|
{
|
||||||
|
/* Cleanup before switch_root */
|
||||||
|
}
|
||||||
|
|
||||||
|
static plugin_t plugin = {
|
||||||
|
.name = "my-plugin",
|
||||||
|
.hook[HOOK_SWITCH_ROOT] = {
|
||||||
|
.cb = my_switch_root_hook
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
PLUGIN_INIT(plugin_init)
|
||||||
|
{
|
||||||
|
plugin_register(&plugin);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
Conditions
|
||||||
|
----------
|
||||||
|
|
||||||
|
After switch_root, the new finit instance starts fresh. No conditions
|
||||||
|
or state are preserved across the switch. The new finit will:
|
||||||
|
|
||||||
|
1. Re-read `/etc/finit.conf` from the new root
|
||||||
|
2. Re-initialize all conditions
|
||||||
|
3. Start services according to the new configuration
|
||||||
|
|
||||||
|
|
||||||
|
See Also
|
||||||
|
--------
|
||||||
|
|
||||||
|
- [switch_root(8)](https://man7.org/linux/man-pages/man8/switch_root.8.html) - util-linux switch_root utility
|
||||||
|
- [Kernel initramfs documentation](https://docs.kernel.org/filesystems/ramfs-rootfs-initramfs.html)
|
||||||
@@ -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>
|
||||||
|
|||||||
+173
-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
|
||||||
@@ -398,6 +398,20 @@ mechanism completely, allows endless restarts. Useful in many
|
|||||||
use-cases, but not what
|
use-cases, but not what
|
||||||
.Cm service
|
.Cm service
|
||||||
was originally designed for so not the default behavior.
|
was originally designed for so not the default behavior.
|
||||||
|
.It Cm remain:yes
|
||||||
|
for
|
||||||
|
.Cm run
|
||||||
|
and
|
||||||
|
.Cm task
|
||||||
|
only. Prevents the task from re-running on runlevel re-entry and
|
||||||
|
ensures the
|
||||||
|
.Cm post:
|
||||||
|
script runs when the task is explicitly stopped or leaves its valid
|
||||||
|
runlevels. Similar to systemd's
|
||||||
|
.Cm RemainAfterExit=yes .
|
||||||
|
.Pp
|
||||||
|
.Sy Note:
|
||||||
|
not supported for bootstrap-only tasks (runlevels [S] only).
|
||||||
.It Cm oncrash:reboot
|
.It Cm oncrash:reboot
|
||||||
when all retries have failed, and the service
|
when all retries have failed, and the service
|
||||||
has
|
has
|
||||||
@@ -416,7 +430,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 +572,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 +582,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 +592,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 +662,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 +687,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
|
||||||
@@ -707,6 +744,37 @@ is
|
|||||||
and the default
|
and the default
|
||||||
.Cm tag
|
.Cm tag
|
||||||
identity is the basename of the service or run/task command.
|
identity is the basename of the service or run/task command.
|
||||||
|
.It Cm tty:\&<dev>
|
||||||
|
Give the
|
||||||
|
.Cm run , task ,
|
||||||
|
or
|
||||||
|
.Cm service
|
||||||
|
a controlling terminal on
|
||||||
|
.Cm <dev> .
|
||||||
|
The device is opened, set as the controlling terminal for the session
|
||||||
|
(after
|
||||||
|
.Fn setsid ) ,
|
||||||
|
and connected to stdin, stdout, and stderr.
|
||||||
|
A default
|
||||||
|
.Ev TERM
|
||||||
|
variable is set based on the device type:
|
||||||
|
.Cm vt102
|
||||||
|
for serial lines and
|
||||||
|
.Cm linux
|
||||||
|
for virtual terminals.
|
||||||
|
.Cm <dev>
|
||||||
|
may be a device node like
|
||||||
|
.Pa /dev/ttyS0 ,
|
||||||
|
or the special keyword
|
||||||
|
.Cm @console
|
||||||
|
(see TTYs and Consoles above).
|
||||||
|
When combined with
|
||||||
|
.Cm log: ,
|
||||||
|
stdout and stderr are redirected to the log sink instead, but stdin
|
||||||
|
remains connected to the TTY device.
|
||||||
|
.Bd -unfilled -offset indent
|
||||||
|
service [2345] tty:/dev/ttyS0 /usr/sbin/foo -- Foo on serial console
|
||||||
|
.Ed
|
||||||
.El
|
.El
|
||||||
.Sh RESCUE MODE
|
.Sh RESCUE MODE
|
||||||
Finit supports a rescue mode which is activated by the
|
Finit supports a rescue mode which is activated by the
|
||||||
@@ -946,9 +1014,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 +1037,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
|
||||||
|
|||||||
+153
@@ -0,0 +1,153 @@
|
|||||||
|
site_name: User's Guide
|
||||||
|
site_description: Fast Init for Linux Systems
|
||||||
|
site_url: https://finit-project.github.io
|
||||||
|
repo_url: https://github.com/finit-project/finit
|
||||||
|
repo_name: Finit Project
|
||||||
|
copyright: Copyright © 2008-2026 Joachim Wiberg
|
||||||
|
docs_dir: doc/
|
||||||
|
edit_uri: edit/master/doc/
|
||||||
|
extra_css:
|
||||||
|
- extra.css
|
||||||
|
|
||||||
|
exclude_docs: |
|
||||||
|
TODO.md
|
||||||
|
ChangeLog.md
|
||||||
|
|
||||||
|
nav:
|
||||||
|
- Getting Started:
|
||||||
|
- Introduction: index.md
|
||||||
|
- Features: features.md
|
||||||
|
- Quick Example: example.md
|
||||||
|
- Building: build.md
|
||||||
|
- Configuration:
|
||||||
|
- Overview: config/index.md
|
||||||
|
- Files & Layout: config/files.md
|
||||||
|
- Conditions: conditions.md
|
||||||
|
- Runlevels: config/runlevels.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
|
||||||
|
- TTY & Console: config/tty.md
|
||||||
|
- Environment Variables: config/env.md
|
||||||
|
- Logging: config/logging.md
|
||||||
|
- Cgroups: config/cgroups.md
|
||||||
|
- Capabilities: config/capabilities.md
|
||||||
|
- Templating: config/templating.md
|
||||||
|
- SysV Compatibility: config/sysv.md
|
||||||
|
- Rescue Mode: config/rescue.md
|
||||||
|
- Limitations: config/limitations.md
|
||||||
|
- Usage:
|
||||||
|
- Commands & Status: initctl.md
|
||||||
|
- Switch Root: switchroot.md
|
||||||
|
- Rebooting & Halting: commands.md
|
||||||
|
- Command Line Options: cmdline.md
|
||||||
|
- Managing Services: service.md
|
||||||
|
- Signals: signals.md
|
||||||
|
- Reference:
|
||||||
|
- Runlevels Overview: runlevels.md
|
||||||
|
- Runparts & rc.local: runparts.md
|
||||||
|
- Plugins: plugins.md
|
||||||
|
- Watchdog: watchdog.md
|
||||||
|
- keventd: keventd.md
|
||||||
|
- Service State Machine: state-machine.md
|
||||||
|
- Distributions: distro.md
|
||||||
|
- Requirements: requirements.md
|
||||||
|
|
||||||
|
theme:
|
||||||
|
logo: img/logo.png
|
||||||
|
name: material
|
||||||
|
features:
|
||||||
|
- toc.follow
|
||||||
|
# - toc.integrate
|
||||||
|
- navigation.path
|
||||||
|
- navigation.instant
|
||||||
|
- navigation.instant.progress
|
||||||
|
- navigation.tracking
|
||||||
|
- navigation.indexes
|
||||||
|
# - navigation.tabs
|
||||||
|
# - navigation.sections
|
||||||
|
# - navigation.expand
|
||||||
|
# - navigation.top
|
||||||
|
# - navigation.footer
|
||||||
|
- search.highlight
|
||||||
|
- search.share
|
||||||
|
# - content.action.edit
|
||||||
|
- content.code.copy
|
||||||
|
- content.code.annotate
|
||||||
|
- content.footnote.tooltips
|
||||||
|
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
|
||||||
|
|
||||||
|
markdown_extensions:
|
||||||
|
- admonition
|
||||||
|
- attr_list
|
||||||
|
- footnotes
|
||||||
|
- pymdownx.blocks.caption
|
||||||
|
- pymdownx.critic
|
||||||
|
- pymdownx.caret
|
||||||
|
- pymdownx.keys
|
||||||
|
- pymdownx.mark
|
||||||
|
- pymdownx.tilde
|
||||||
|
- pymdownx.details
|
||||||
|
- pymdownx.superfences
|
||||||
|
- pymdownx.highlight:
|
||||||
|
anchor_linenums: true
|
||||||
|
- pymdownx.inlinehilite
|
||||||
|
- pymdownx.emoji:
|
||||||
|
emoji_index: !!python/name:material.extensions.emoji.twemoji
|
||||||
|
emoji_generator: !!python/name:material.extensions.emoji.to_svg
|
||||||
|
- pymdownx.snippets
|
||||||
|
- pymdownx.tabbed:
|
||||||
|
alternate_style: true
|
||||||
|
- tables
|
||||||
|
- toc:
|
||||||
|
permalink: true
|
||||||
|
|
||||||
|
plugins:
|
||||||
|
- search
|
||||||
|
- callouts
|
||||||
|
- glightbox:
|
||||||
|
touchNavigation: true
|
||||||
|
loop: false
|
||||||
|
effect: zoom
|
||||||
|
slide_effect: slide
|
||||||
|
width: 100%
|
||||||
|
height: auto
|
||||||
|
zoomable: true
|
||||||
|
draggable: true
|
||||||
|
skip_classes:
|
||||||
|
- custom-skip-class-name
|
||||||
|
auto_themed: true
|
||||||
|
auto_caption: false
|
||||||
|
caption_position: bottom
|
||||||
|
background: black
|
||||||
|
shadow: false
|
||||||
|
manual: false
|
||||||
|
|
||||||
|
extra:
|
||||||
|
generator: false
|
||||||
|
homepage: https://finit-project.github.io/
|
||||||
|
version:
|
||||||
|
provider: mike
|
||||||
|
social:
|
||||||
|
- icon: fontawesome/brands/github
|
||||||
|
link: https://github.com/finit-project/finit
|
||||||
|
name: Finit on GitHub
|
||||||
@@ -29,6 +29,10 @@ if BUILD_NETLINK_PLUGIN
|
|||||||
libplug_la_SOURCES += netlink.c
|
libplug_la_SOURCES += netlink.c
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
if BUILD_PLYMOUTH_PLUGIN
|
||||||
|
libplug_la_SOURCES += plymouth.c
|
||||||
|
endif
|
||||||
|
|
||||||
if BUILD_RESOLVCONF_PLUGIN
|
if BUILD_RESOLVCONF_PLUGIN
|
||||||
libplug_la_SOURCES += resolvconf.c
|
libplug_la_SOURCES += resolvconf.c
|
||||||
endif
|
endif
|
||||||
@@ -76,6 +80,10 @@ if BUILD_NETLINK_PLUGIN
|
|||||||
pkglib_LTLIBRARIES += netlink.la
|
pkglib_LTLIBRARIES += netlink.la
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
if BUILD_PLYMOUTH_PLUGIN
|
||||||
|
pkglib_LTLIBRARIES += plymouth.la
|
||||||
|
endif
|
||||||
|
|
||||||
if BUILD_RESOLVCONF_PLUGIN
|
if BUILD_RESOLVCONF_PLUGIN
|
||||||
pkglib_LTLIBRARIES += resolvconf.la
|
pkglib_LTLIBRARIES += resolvconf.la
|
||||||
endif
|
endif
|
||||||
|
|||||||
@@ -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,16 +27,18 @@
|
|||||||
# 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"
|
||||||
|
|
||||||
static void save(void *arg)
|
static void save(void *arg)
|
||||||
{
|
{
|
||||||
if (rescue) {
|
if (rescue) {
|
||||||
dbg("Skipping %s plugin in rescue mode.", __FILE__);
|
dbg("Skipping %s plugin in rescue mode.", "alsa-utils");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -49,7 +51,7 @@ static void save(void *arg)
|
|||||||
static void restore(void *arg)
|
static void restore(void *arg)
|
||||||
{
|
{
|
||||||
if (rescue) {
|
if (rescue) {
|
||||||
dbg("Skipping %s plugin in rescue mode.", __FILE__);
|
dbg("Skipping %s plugin in rescue mode.", "alsa-utils");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -60,17 +62,17 @@ static void restore(void *arg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static plugin_t plugin = {
|
static plugin_t plugin = {
|
||||||
.name = __FILE__,
|
.name = "alsa-utils",
|
||||||
.hook[HOOK_BASEFS_UP] = { .cb = restore },
|
.hook[HOOK_BASEFS_UP] = { .cb = restore },
|
||||||
.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);
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-6
@@ -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();
|
||||||
@@ -172,18 +172,18 @@ static void setup(void *arg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static plugin_t plugin = {
|
static plugin_t plugin = {
|
||||||
.name = __FILE__,
|
.name = "bootmisc",
|
||||||
.hook[HOOK_MOUNT_POST] = { .cb = clean },
|
.hook[HOOK_MOUNT_POST] = { .cb = clean },
|
||||||
.hook[HOOK_BASEFS_UP] = { .cb = setup },
|
.hook[HOOK_BASEFS_UP] = { .cb = setup },
|
||||||
.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);
|
||||||
}
|
}
|
||||||
|
|||||||
+7
-5
@@ -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"
|
||||||
@@ -104,7 +106,7 @@ static void setup(void *arg)
|
|||||||
char *cmd;
|
char *cmd;
|
||||||
|
|
||||||
if (rescue) {
|
if (rescue) {
|
||||||
dbg("Skipping %s plugin in rescue mode.", __FILE__);
|
dbg("Skipping %s plugin in rescue mode.", "dbus");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -162,16 +164,16 @@ static void setup(void *arg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static plugin_t plugin = {
|
static plugin_t plugin = {
|
||||||
.name = __FILE__,
|
.name = "dbus",
|
||||||
.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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ static void hscript_shutdown(void *arg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static plugin_t plugin = {
|
static plugin_t plugin = {
|
||||||
.name = __FILE__,
|
.name = "hook-scripts",
|
||||||
.hook[HOOK_BANNER] = { .cb = hscript_banner },
|
.hook[HOOK_BANNER] = { .cb = hscript_banner },
|
||||||
.hook[HOOK_ROOTFS_UP] = { .cb = hscript_rootfs_up },
|
.hook[HOOK_ROOTFS_UP] = { .cb = hscript_rootfs_up },
|
||||||
.hook[HOOK_MOUNT_ERROR] = { .cb = hscript_mount_error },
|
.hook[HOOK_MOUNT_ERROR] = { .cb = hscript_mount_error },
|
||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-4
@@ -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;
|
||||||
@@ -227,17 +228,17 @@ static void coldplug(void *arg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static plugin_t plugin = {
|
static plugin_t plugin = {
|
||||||
.name = __FILE__,
|
.name = "modprobe",
|
||||||
.hook[HOOK_BASEFS_UP] = { .cb = coldplug },
|
.hook[HOOK_BASEFS_UP] = { .cb = coldplug },
|
||||||
.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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,7 +41,7 @@
|
|||||||
*
|
*
|
||||||
* Please note, the :ID is there for your benefit, it ensures that tasks
|
* Please note, the :ID is there for your benefit, it ensures that tasks
|
||||||
* in Finit are unique. If you have two tasks with the same name and ID
|
* in Finit are unique. If you have two tasks with the same name and ID
|
||||||
* (or no ID), the last one read replaces any preceeding one!
|
* (or no ID), the last one read replaces any preceding one!
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
@@ -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"
|
||||||
@@ -212,16 +213,16 @@ static void load(void *arg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static plugin_t plugin = {
|
static plugin_t plugin = {
|
||||||
.name = __FILE__,
|
.name = "modules-load",
|
||||||
.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);
|
||||||
}
|
}
|
||||||
|
|||||||
+26
-5
@@ -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"
|
||||||
@@ -405,16 +406,36 @@ static void nl_reconf(void *arg)
|
|||||||
cond_reassert("net/");
|
cond_reassert("net/");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initial enumeration of existing interfaces and routes. Called from
|
||||||
|
* HOOK_SVC_PLUGIN which runs after the condition system is initialized.
|
||||||
|
* Interfaces that exist before finit starts (e.g., virtio-net in QEMU)
|
||||||
|
* won't generate RTM_NEWLINK events, so we must query for them.
|
||||||
|
*/
|
||||||
|
static void nl_enumerate(void *arg)
|
||||||
|
{
|
||||||
|
int sd;
|
||||||
|
|
||||||
|
sd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE);
|
||||||
|
if (sd < 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
nl_resync_ifaces(sd, 0);
|
||||||
|
nl_resync_routes(sd, 1);
|
||||||
|
close(sd);
|
||||||
|
}
|
||||||
|
|
||||||
static plugin_t plugin = {
|
static plugin_t plugin = {
|
||||||
.name = __FILE__,
|
.name = "netlink",
|
||||||
.hook[HOOK_SVC_RECONF] = { .cb = nl_reconf },
|
.hook[HOOK_SVC_RECONF] = { .cb = nl_reconf },
|
||||||
|
.hook[HOOK_SVC_PLUGIN] = { .cb = nl_enumerate },
|
||||||
.io = {
|
.io = {
|
||||||
.cb = nl_callback,
|
.cb = nl_callback,
|
||||||
.flags = PLUGIN_IO_READ,
|
.flags = PLUGIN_IO_READ,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
PLUGIN_INIT(plugin_init)
|
PLUGIN_INIT(__init)
|
||||||
{
|
{
|
||||||
struct sockaddr_nl sa;
|
struct sockaddr_nl sa;
|
||||||
int sd;
|
int sd;
|
||||||
@@ -447,7 +468,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);
|
||||||
|
|||||||
+25
-5
@@ -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;
|
||||||
|
|
||||||
@@ -58,7 +59,7 @@ static int pidfile_add_path(struct iwatch *iw, char *path)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return iwatch_add(iw, path, IN_ONLYDIR | IN_CLOSE_WRITE);
|
return iwatch_add(iw, path, IN_ONLYDIR | IN_CLOSE_WRITE | IN_ATTRIB);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pidfile_update_conds(char *dir, char *name, uint32_t mask)
|
static void pidfile_update_conds(char *dir, char *name, uint32_t mask)
|
||||||
@@ -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));
|
||||||
|
|
||||||
@@ -125,6 +143,7 @@ static void pidfile_update_conds(char *dir, char *name, uint32_t mask)
|
|||||||
|
|
||||||
/* Complement log in service.c for non-forking services */
|
/* Complement log in service.c for non-forking services */
|
||||||
logit(LOG_CONSOLE | LOG_NOTICE, "Started %s[%d]", svc_ident(svc, NULL, 0), pid);
|
logit(LOG_CONSOLE | LOG_NOTICE, "Started %s[%d]", svc_ident(svc, NULL, 0), pid);
|
||||||
|
cgroup_move_svc(svc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -257,6 +276,7 @@ static void pidfile_reconf(void *arg)
|
|||||||
if (cond_get(cond) == COND_ON)
|
if (cond_get(cond) == COND_ON)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
dbg("Reassert condition %s", cond);
|
||||||
cond_set_path(cond_path(cond), COND_ON);
|
cond_set_path(cond_path(cond), COND_ON);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -315,13 +335,13 @@ static void pidfile_init(void *arg)
|
|||||||
* SIGSTP:ed (in state PAUSED) waiting for <net/iface/lo>.
|
* SIGSTP:ed (in state PAUSED) waiting for <net/iface/lo>.
|
||||||
*/
|
*/
|
||||||
static plugin_t plugin = {
|
static plugin_t plugin = {
|
||||||
.name = __FILE__,
|
.name = "pidfile",
|
||||||
.hook[HOOK_BASEFS_UP] = { .cb = pidfile_init },
|
.hook[HOOK_BASEFS_UP] = { .cb = pidfile_init },
|
||||||
.hook[HOOK_SVC_RECONF] = { .cb = pidfile_reconf },
|
.hook[HOOK_SVC_RECONF] = { .cb = pidfile_reconf },
|
||||||
.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 +356,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);
|
||||||
|
|||||||
@@ -0,0 +1,293 @@
|
|||||||
|
/* Plymouth boot splash plugin for Finit
|
||||||
|
*
|
||||||
|
* Copyright (c) 2012-2026 Aaron Andersen <aaron@fosslib.net>
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This plugin integrates the Plymouth boot splash screen with Finit.
|
||||||
|
* It manages the plymouthd lifecycle across the full boot process:
|
||||||
|
*
|
||||||
|
* - HOOK_BANNER: Start plymouthd early, before console output.
|
||||||
|
* In initramfs, starts fresh. In stage 2, reuses
|
||||||
|
* the daemon carried over from initramfs if alive.
|
||||||
|
* - HOOK_ROOTFS_UP .. HOOK_SYSTEM_UP: Display status messages.
|
||||||
|
* - HOOK_SVC_UP: Tear down plymouth once boot is complete.
|
||||||
|
* - HOOK_SWITCH_ROOT: Notify plymouth of root filesystem change so
|
||||||
|
* the daemon survives the initramfs -> rootfs
|
||||||
|
* transition.
|
||||||
|
* - HOOK_SHUTDOWN: Restart plymouthd in shutdown mode for a
|
||||||
|
* splash during poweroff/reboot.
|
||||||
|
*
|
||||||
|
* The plugin is only activated when "splash" is present on the kernel
|
||||||
|
* command line. Plymouth requires devpts for VT takeover; fs_init()
|
||||||
|
* mounts it early enough for HOOK_BANNER.
|
||||||
|
*
|
||||||
|
* NOTE: The initramfs must include /etc/initrd-release. Plymouth
|
||||||
|
* checks for this file and, when present, prefixes its argv[0] with
|
||||||
|
* '@' so that the process is not killed during switch_root. Without
|
||||||
|
* it, plymouthd will not survive the initramfs-to-rootfs transition.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
#include "finit.h"
|
||||||
|
#include "helpers.h"
|
||||||
|
#include "conf.h"
|
||||||
|
#include "pid.h"
|
||||||
|
#include "plugin.h"
|
||||||
|
#include "sig.h"
|
||||||
|
#include "util.h"
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
|
#ifndef PLYMOUTH_PATH
|
||||||
|
#define PLYMOUTH_PATH "/sbin/plymouth"
|
||||||
|
#endif
|
||||||
|
#ifndef PLYMOUTHD_PATH
|
||||||
|
#define PLYMOUTHD_PATH "/sbin/plymouthd"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define PLYMOUTH_PIDFILE "/run/plymouthd.pid"
|
||||||
|
|
||||||
|
static pid_t daemon_pid;
|
||||||
|
static int switching_root;
|
||||||
|
static int in_initramfs;
|
||||||
|
|
||||||
|
static int plymouth_cmd(const char *action)
|
||||||
|
{
|
||||||
|
char cmd[256];
|
||||||
|
|
||||||
|
snprintf(cmd, sizeof(cmd), PLYMOUTH_PATH " %s", action);
|
||||||
|
return run(cmd, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void plymouth_message(const char *msg)
|
||||||
|
{
|
||||||
|
pid_t pid;
|
||||||
|
|
||||||
|
pid = fork();
|
||||||
|
if (pid == 0) {
|
||||||
|
sig_unblock();
|
||||||
|
execl(PLYMOUTH_PATH, PLYMOUTH_PATH,
|
||||||
|
"display-message", "--text", msg, NULL);
|
||||||
|
_exit(EX_OSERR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int plymouth_alive(void)
|
||||||
|
{
|
||||||
|
return daemon_pid > 0 && pid_alive(daemon_pid);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Start plymouthd in the given mode ("boot" or "shutdown"). */
|
||||||
|
static void plymouth_start(const char *mode)
|
||||||
|
{
|
||||||
|
char cmd[256];
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
if (plymouth_alive())
|
||||||
|
return;
|
||||||
|
|
||||||
|
snprintf(cmd, sizeof(cmd),
|
||||||
|
PLYMOUTHD_PATH " --attach-to-session --mode %s --pid-file %s",
|
||||||
|
mode, PLYMOUTH_PIDFILE);
|
||||||
|
rc = run(cmd, NULL);
|
||||||
|
if (rc) {
|
||||||
|
warnx("plymouthd failed to start (exit %d)", rc);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
daemon_pid = pid_file_read(PLYMOUTH_PIDFILE);
|
||||||
|
if (daemon_pid <= 0) {
|
||||||
|
warnx("plymouthd started but no PID in %s", PLYMOUTH_PIDFILE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = plymouth_cmd("show-splash");
|
||||||
|
if (rc)
|
||||||
|
warnx("plymouth show-splash failed (exit %d)", rc);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void plymouth_stop(void)
|
||||||
|
{
|
||||||
|
if (!plymouth_alive())
|
||||||
|
return;
|
||||||
|
|
||||||
|
plymouth_cmd("quit");
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Don't poll -- we're in a finit hook, so finit's event loop
|
||||||
|
* is blocked and can't reap children. Trust that plymouthd
|
||||||
|
* exits after receiving the quit command.
|
||||||
|
*/
|
||||||
|
daemon_pid = 0;
|
||||||
|
unlink(PLYMOUTH_PIDFILE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* HOOK_BANNER - earliest possible hook, before any console output.
|
||||||
|
*
|
||||||
|
* In initramfs: start plymouthd fresh.
|
||||||
|
* In stage 2: reuse plymouthd from initramfs if still alive,
|
||||||
|
* otherwise start a new instance.
|
||||||
|
*/
|
||||||
|
static void plymouth_boot(void *arg)
|
||||||
|
{
|
||||||
|
in_initramfs = fexist("/etc/initrd-release");
|
||||||
|
|
||||||
|
if (rescue)
|
||||||
|
return;
|
||||||
|
|
||||||
|
enable_progress(0);
|
||||||
|
|
||||||
|
if (!in_initramfs) {
|
||||||
|
if (plymouth_cmd("--ping") == 0) {
|
||||||
|
daemon_pid = pid_file_read(PLYMOUTH_PIDFILE);
|
||||||
|
if (daemon_pid <= 0)
|
||||||
|
daemon_pid = 1; /* alive but unknown pid */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
plymouth_start("boot");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* HOOK_SVC_UP - all services launched.
|
||||||
|
*
|
||||||
|
* In initramfs: keep splash alive for switch_root.
|
||||||
|
* In stage 2: boot is done, tear down plymouth.
|
||||||
|
*/
|
||||||
|
static void plymouth_boot_done(void *arg)
|
||||||
|
{
|
||||||
|
if (in_initramfs)
|
||||||
|
return;
|
||||||
|
|
||||||
|
plymouth_stop();
|
||||||
|
enable_progress(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* HOOK_SWITCH_ROOT - initramfs transitioning to real root. */
|
||||||
|
static void plymouth_switchroot(void *arg)
|
||||||
|
{
|
||||||
|
switching_root = 1;
|
||||||
|
|
||||||
|
plymouth_message("Switching to root filesystem...");
|
||||||
|
|
||||||
|
if (plymouth_alive())
|
||||||
|
run(PLYMOUTH_PATH " update-root-fs --new-root-dir=/sysroot", NULL);
|
||||||
|
|
||||||
|
enable_progress(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* HOOK_SHUTDOWN - entering runlevel 0 or 6. */
|
||||||
|
static void plymouth_shutdown(void *arg)
|
||||||
|
{
|
||||||
|
if (rescue || switching_root)
|
||||||
|
return;
|
||||||
|
|
||||||
|
enable_progress(0);
|
||||||
|
plymouth_start("shutdown");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void on_rootfs_up(void *arg)
|
||||||
|
{
|
||||||
|
plymouth_message("Root filesystem mounted");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void on_mount_post(void *arg)
|
||||||
|
{
|
||||||
|
plymouth_message("Mounting filesystems...");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void on_basefs_up(void *arg)
|
||||||
|
{
|
||||||
|
plymouth_message("All filesystems mounted");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void on_network_up(void *arg)
|
||||||
|
{
|
||||||
|
plymouth_message("Network is up");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void on_system_up(void *arg)
|
||||||
|
{
|
||||||
|
plymouth_message("System ready");
|
||||||
|
}
|
||||||
|
|
||||||
|
static plugin_t plugin = {
|
||||||
|
.name = "plymouth",
|
||||||
|
.hook[HOOK_BANNER] = { .cb = plymouth_boot },
|
||||||
|
.hook[HOOK_ROOTFS_UP] = { .cb = on_rootfs_up },
|
||||||
|
.hook[HOOK_MOUNT_POST] = { .cb = on_mount_post },
|
||||||
|
.hook[HOOK_BASEFS_UP] = { .cb = on_basefs_up },
|
||||||
|
.hook[HOOK_NETWORK_UP] = { .cb = on_network_up },
|
||||||
|
.hook[HOOK_SYSTEM_UP] = { .cb = on_system_up },
|
||||||
|
.hook[HOOK_SVC_UP] = { .cb = plymouth_boot_done },
|
||||||
|
.hook[HOOK_SWITCH_ROOT] = { .cb = plymouth_switchroot },
|
||||||
|
.hook[HOOK_SHUTDOWN] = { .cb = plymouth_shutdown },
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check kernel command line for "splash" argument. Plymouth should
|
||||||
|
* only be activated when the user explicitly requests it.
|
||||||
|
*/
|
||||||
|
static int has_splash_arg(void)
|
||||||
|
{
|
||||||
|
char line[LINE_SIZE], *tok, *saveptr;
|
||||||
|
FILE *fp;
|
||||||
|
|
||||||
|
fp = fopen("/proc/cmdline", "r");
|
||||||
|
if (!fp)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (!fgets(line, sizeof(line), fp)) {
|
||||||
|
fclose(fp);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
fclose(fp);
|
||||||
|
|
||||||
|
for (tok = strtok_r(line, " \t\n", &saveptr); tok;
|
||||||
|
tok = strtok_r(NULL, " \t\n", &saveptr)) {
|
||||||
|
if (!strcmp(tok, "splash"))
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
PLUGIN_INIT(__init)
|
||||||
|
{
|
||||||
|
if (!has_splash_arg())
|
||||||
|
return;
|
||||||
|
|
||||||
|
plugin_register(&plugin);
|
||||||
|
}
|
||||||
|
|
||||||
|
PLUGIN_EXIT(__exit)
|
||||||
|
{
|
||||||
|
plugin_unregister(&plugin);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Local Variables:
|
||||||
|
* indent-tabs-mode: t
|
||||||
|
* c-file-style: "linux"
|
||||||
|
* End:
|
||||||
|
*/
|
||||||
+7
-5
@@ -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"
|
||||||
@@ -41,7 +43,7 @@ static void setup(void *arg)
|
|||||||
glob_t gl;
|
glob_t gl;
|
||||||
|
|
||||||
if (rescue) {
|
if (rescue) {
|
||||||
dbg("Skipping %s plugin in rescue mode.", __FILE__);
|
dbg("Skipping %s plugin in rescue mode.", "procps");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -67,19 +69,19 @@ static void setup(void *arg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static plugin_t plugin = {
|
static plugin_t plugin = {
|
||||||
.name = __FILE__,
|
.name = "procps",
|
||||||
.hook[HOOK_BASEFS_UP] = {
|
.hook[HOOK_BASEFS_UP] = {
|
||||||
.cb = setup
|
.cb = setup
|
||||||
},
|
},
|
||||||
.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/
|
||||||
@@ -50,19 +51,19 @@ static void setup(void *arg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static plugin_t plugin = {
|
static plugin_t plugin = {
|
||||||
.name = __FILE__,
|
.name = "resolvconf",
|
||||||
.hook[HOOK_BASEFS_UP] = {
|
.hook[HOOK_BASEFS_UP] = {
|
||||||
.cb = setup
|
.cb = setup
|
||||||
},
|
},
|
||||||
.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);
|
||||||
}
|
}
|
||||||
|
|||||||
+29
-19
@@ -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,35 +170,43 @@ 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;
|
char msg[120];
|
||||||
|
int rc = 0;
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
|
|
||||||
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];
|
||||||
|
|
||||||
if (fgets(buf, sizeof(buf), fp)) {
|
if (fgets(buf, sizeof(buf), fp)) {
|
||||||
chomp(buf);
|
chomp(buf);
|
||||||
strptime(buf, RTC_FMT, &tm);
|
if (!strptime(buf, RTC_FMT, &tm))
|
||||||
rc = time_set(&tm);
|
rc = 1;
|
||||||
}
|
}
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
} else
|
} 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)
|
||||||
@@ -225,7 +236,7 @@ static void rtc_save(void *arg)
|
|||||||
int fd, rc = 0;
|
int fd, rc = 0;
|
||||||
|
|
||||||
if (rescue) {
|
if (rescue) {
|
||||||
dbg("Skipping %s plugin in rescue mode.", __FILE__);
|
dbg("Skipping %s plugin in rescue mode.", "rtc");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -255,7 +266,7 @@ static void rtc_restore(void *arg)
|
|||||||
int fd, rc = 0;
|
int fd, rc = 0;
|
||||||
|
|
||||||
if (rescue) {
|
if (rescue) {
|
||||||
dbg("Skipping %s plugin in rescue mode.", __FILE__);
|
dbg("Skipping %s plugin in rescue mode.", "rtc");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -289,8 +300,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);
|
||||||
|
|
||||||
@@ -311,7 +321,7 @@ static void update(uev_t *w, void *arg, int events)
|
|||||||
|
|
||||||
|
|
||||||
static plugin_t plugin = {
|
static plugin_t plugin = {
|
||||||
.name = __FILE__,
|
.name = "rtc",
|
||||||
.hook[HOOK_BASEFS_UP] = {
|
.hook[HOOK_BASEFS_UP] = {
|
||||||
.cb = rtc_restore
|
.cb = rtc_restore
|
||||||
},
|
},
|
||||||
@@ -320,7 +330,7 @@ static plugin_t plugin = {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
PLUGIN_INIT(plugin_init)
|
PLUGIN_INIT(__init)
|
||||||
{
|
{
|
||||||
struct tm tm = { 0 };
|
struct tm tm = { 0 };
|
||||||
|
|
||||||
@@ -336,7 +346,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);
|
||||||
|
|||||||
+5
-4
@@ -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;
|
||||||
|
|
||||||
@@ -179,12 +180,12 @@ static void sys_init(void *arg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static plugin_t plugin = {
|
static plugin_t plugin = {
|
||||||
.name = __FILE__,
|
.name = "sys",
|
||||||
.hook[HOOK_BASEFS_UP] = { .cb = sys_init },
|
.hook[HOOK_BASEFS_UP] = { .cb = sys_init },
|
||||||
.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);
|
||||||
|
|||||||
+5
-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,10 +38,12 @@
|
|||||||
#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);
|
||||||
|
|
||||||
static plugin_t plugin = {
|
static plugin_t plugin = {
|
||||||
|
.name = "tty",
|
||||||
.io = {
|
.io = {
|
||||||
.cb = tty_watcher,
|
.cb = tty_watcher,
|
||||||
.flags = PLUGIN_IO_READ,
|
.flags = PLUGIN_IO_READ,
|
||||||
@@ -108,13 +110,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)
|
||||||
|
|||||||
+16
-11
@@ -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,13 +80,14 @@ 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;
|
||||||
int fd, err;
|
int fd, err;
|
||||||
|
|
||||||
if (rescue) {
|
if (rescue) {
|
||||||
dbg("Skipping %s plugin in rescue mode.", __FILE__);
|
dbg("Skipping %s plugin in rescue mode.", "urandom");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -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;
|
||||||
@@ -183,7 +188,7 @@ static void save(void *arg)
|
|||||||
mode_t prev;
|
mode_t prev;
|
||||||
|
|
||||||
if (rescue) {
|
if (rescue) {
|
||||||
dbg("Skipping %s plugin in rescue mode.", __FILE__);
|
dbg("Skipping %s plugin in rescue mode.", "urandom");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -197,18 +202,18 @@ static void save(void *arg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static plugin_t plugin = {
|
static plugin_t plugin = {
|
||||||
.name = __FILE__,
|
.name = "urandom",
|
||||||
.hook[HOOK_BASEFS_UP] = { .cb = setup },
|
.hook[HOOK_BASEFS_UP] = { .cb = setup },
|
||||||
.hook[HOOK_SHUTDOWN] = { .cb = save },
|
.hook[HOOK_SHUTDOWN] = { .cb = save },
|
||||||
.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);
|
||||||
}
|
}
|
||||||
|
|||||||
Loaded 100 of 218 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user