mirror of
https://github.com/troglobit/finit.git
synced 2026-10-12 10:12:32 +00:00
Compare commits
11
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
58e31dbd22 | ||
|
|
85058b54a8 | ||
|
|
f16df142d7 | ||
|
|
f9f52a46a6 | ||
|
|
ef1bfb869f | ||
|
|
5002c74876 | ||
|
|
a0bc23c48f | ||
|
|
350cf6e578 | ||
|
|
b96a8d8766 | ||
|
|
a419828dea | ||
|
|
702b22d4a3 |
+31
-35
@@ -9,9 +9,9 @@ For email questions/requests/alerts there is always the risk of memory
|
|||||||
exhaustion on the part of the maintainer(s).
|
exhaustion on the part of the maintainer(s).
|
||||||
|
|
||||||
If you are unsure of what to do, or how to implement an idea or bugfix,
|
If you are unsure of what to do, or how to implement an idea or bugfix,
|
||||||
open an issue with `"[RFC: Unsure if this is a bug ... ?"`, or use the
|
open an issue with `"[RFC: Unsure if this is a bug ... ?"`, or similar,
|
||||||
GitHub discussions forum, so we can discuss it. Talking about the code
|
so we can discuss it. Talking about the code first is the best way to
|
||||||
first is the best way to get started before submitting a pull request.
|
get started before submitting a pull request.
|
||||||
|
|
||||||
Either way, when sending an email, patch, or pull request, start by
|
Either way, when sending an email, patch, or pull request, start by
|
||||||
stating the version the change is made against, what it does, and why.
|
stating the version the change is made against, what it does, and why.
|
||||||
@@ -20,17 +20,18 @@ Please take care to ensure you follow the project coding style and the
|
|||||||
commit message format. If you follow these recommendations you help
|
commit message format. If you follow these recommendations you help
|
||||||
the maintainer(s) and make it easier for them to include your code.
|
the maintainer(s) and make it easier for them to include your code.
|
||||||
|
|
||||||
|
|
||||||
Coding Style
|
Coding Style
|
||||||
------------
|
------------
|
||||||
|
|
||||||
> [!TIP]
|
> **Tip:** Always submit code that follows the style of surrounding code!
|
||||||
> 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
|
||||||
100 chars is OK.
|
100 chars is OK.
|
||||||
|
|
||||||
The coding style itself is strictly [Linux coding style][KNF].
|
The coding style itself is strictly Linux [KNF][].
|
||||||
|
|
||||||
|
|
||||||
Commit Messages
|
Commit Messages
|
||||||
---------------
|
---------------
|
||||||
@@ -39,38 +40,31 @@ Commit messages exist to track *why* a change was made. Try to be as
|
|||||||
clear and concise as possible in your commit messages, and always, be
|
clear and concise as possible in your commit messages, and always, be
|
||||||
proud of your work and set up a proper GIT identity for your commits:
|
proud of your work and set up a proper GIT identity for your commits:
|
||||||
|
|
||||||
```bash
|
git config --global user.name "Jane Doe"
|
||||||
$ git config --global user.name "Jane Doe"
|
git config --global user.email jane.doe@example.com
|
||||||
$ git config --global user.email jane.doe@example.com
|
|
||||||
```
|
|
||||||
|
|
||||||
Example commit message from the [Pro Git][gitbook] online book, notice
|
Example commit message from the [Pro Git][gitbook] online book, notice
|
||||||
how `git commit -s` is used to automatically add a `Signed-off-by`:
|
how `git commit -s` is used to automatically add a `Signed-off-by`:
|
||||||
|
|
||||||
```
|
Brief, but clear and concise summary of changes
|
||||||
Brief, but clear and concise summary of changes
|
|
||||||
|
More detailed explanatory text, if necessary. Wrap it to about 72
|
||||||
|
characters or so. In some contexts, the first line is treated as
|
||||||
|
the subject of an email and the rest of the text as the body. The
|
||||||
|
blank line separating the ummary from the body is critical (unless
|
||||||
|
you omit the body entirely); tools like rebase can get confused if
|
||||||
|
you run the two together.
|
||||||
|
|
||||||
|
Further paragraphs come after blank lines.
|
||||||
|
|
||||||
|
- Bullet points are okay, too
|
||||||
|
|
||||||
|
- Typically a hyphen or asterisk is used for the bullet, preceded
|
||||||
|
by a single space, with blank lines in between, but conventions
|
||||||
|
vary here
|
||||||
|
|
||||||
|
Signed-off-by: Jane Doe <jane.doe@example.com>
|
||||||
|
|
||||||
More detailed explanatory text, if necessary. Remember, a future
|
|
||||||
reader has the diff and can see what it does, the commit message in
|
|
||||||
itself should usually talk about the *why* of a change and/or any
|
|
||||||
technical limitations and future work.
|
|
||||||
|
|
||||||
Wrap the text to about 72 characters or so. In some contexts, the
|
|
||||||
first line is treated as the subject of an email and the rest of the
|
|
||||||
text as the body. The blank line separating the summary from the body
|
|
||||||
is critical (unless you omit the body entirely); tools like rebase can
|
|
||||||
get confused if you run the two together.
|
|
||||||
|
|
||||||
Further paragraphs come after blank lines.
|
|
||||||
|
|
||||||
- Bullet points are okay, too
|
|
||||||
|
|
||||||
- Typically a hyphen or asterisk is used for the bullet, preceded
|
|
||||||
by a single space, with blank lines in between, but conventions
|
|
||||||
vary here
|
|
||||||
|
|
||||||
Signed-off-by: Jane Doe <jane.doe@example.com>
|
|
||||||
```
|
|
||||||
|
|
||||||
Code of Conduct
|
Code of Conduct
|
||||||
---------------
|
---------------
|
||||||
@@ -78,6 +72,8 @@ Code of Conduct
|
|||||||
It is expected of everyone engaging in the project to, in the words of
|
It is expected of everyone engaging in the project to, in the words of
|
||||||
Bill & Ted; [be excellent to each other][conduct].
|
Bill & Ted; [be excellent to each other][conduct].
|
||||||
|
|
||||||
[KNF]: https://www.kernel.org/doc/html/v5.8/process/coding-style.html
|
|
||||||
[gitbook]: https://git-scm.com/book/en/v2/Distributed-Git-Contributing-to-a-Project#_commit_guidelines
|
[github]: https://github.com/troglobit/finit/
|
||||||
|
[KNF]: https://en.wikipedia.org/wiki/Kernel_Normal_Form
|
||||||
|
[gitbook]: https://git-scm.com/book/ch5-2.html
|
||||||
[conduct]: CODE-OF-CONDUCT.md
|
[conduct]: CODE-OF-CONDUCT.md
|
||||||
|
|||||||
+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/finit-project/finit/releases>
|
<https://github.com/troglobit/finit/releases>
|
||||||
|
|
||||||
## Reporting a Vulnerability
|
## Reporting a Vulnerability
|
||||||
|
|
||||||
|
|||||||
+25
-144
@@ -8,182 +8,63 @@ on:
|
|||||||
- '**'
|
- '**'
|
||||||
- '!dev'
|
- '!dev'
|
||||||
pull_request:
|
pull_request:
|
||||||
types: [opened, synchronize, reopened, labeled]
|
branches:
|
||||||
|
- '**'
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
|
|
||||||
concurrency:
|
|
||||||
group: ${{ github.workflow }}-${{ github.head_ref || github.ref }}
|
|
||||||
cancel-in-progress: true
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
fuzz:
|
|
||||||
name: fuzz
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
if: github.event_name != 'push' || github.ref == 'refs/heads/master'
|
|
||||||
steps:
|
|
||||||
- name: Install dependencies
|
|
||||||
run: |
|
|
||||||
sudo apt-get -y update
|
|
||||||
sudo apt-get -y install pkg-config libconfuse-dev clang libblkid-dev
|
|
||||||
# clang picks the newest gcc tree it finds and needs the
|
|
||||||
# matching libstdc++ headers to link the fuzzer runtime
|
|
||||||
sudo apt-get -y install libstdc++-14-dev || true
|
|
||||||
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: Configure
|
|
||||||
run: |
|
|
||||||
./autogen.sh
|
|
||||||
./configure --prefix=/usr --exec-prefix= --sysconfdir=/etc --localstatedir=/var
|
|
||||||
- name: Build fuzz target
|
|
||||||
run: |
|
|
||||||
clang -fsanitize=fuzzer,address -DLINK_FUZZ_LIBFUZZER -D_GNU_SOURCE \
|
|
||||||
-I libink -I . -o fuzz-msg-parse \
|
|
||||||
test/src/fuzz-msg-parse.c libink/*.c
|
|
||||||
# Restores the newest corpus and saves a fresh one, since a cache
|
|
||||||
# entry is immutable once written. Caches made on a branch are
|
|
||||||
# private to it, so the corpus that accumulates on master is what
|
|
||||||
# pull requests start from, rather than nothing.
|
|
||||||
- name: Restore corpus
|
|
||||||
uses: actions/cache@v6
|
|
||||||
with:
|
|
||||||
path: .fuzz-corpus
|
|
||||||
key: fuzz-corpus-${{ github.run_id }}
|
|
||||||
restore-keys: fuzz-corpus-
|
|
||||||
- name: Fuzz
|
|
||||||
run: |
|
|
||||||
mkdir -p .fuzz-corpus
|
|
||||||
./fuzz-msg-parse .fuzz-corpus -max_total_time=120 -max_len=4096 \
|
|
||||||
-print_final_stats=1
|
|
||||||
# Without this the corpus only ever grows, and most of what it
|
|
||||||
# accumulates reaches code some earlier input already reached.
|
|
||||||
- name: Minimise corpus
|
|
||||||
if: always()
|
|
||||||
run: |
|
|
||||||
mkdir -p .fuzz-corpus-min
|
|
||||||
./fuzz-msg-parse -merge=1 .fuzz-corpus-min .fuzz-corpus
|
|
||||||
rm -rf .fuzz-corpus
|
|
||||||
mv .fuzz-corpus-min .fuzz-corpus
|
|
||||||
echo "corpus: $(ls .fuzz-corpus | wc -l) inputs"
|
|
||||||
- name: Upload crashers
|
|
||||||
if: failure()
|
|
||||||
uses: actions/upload-artifact@v7
|
|
||||||
with:
|
|
||||||
name: fuzz-crashers
|
|
||||||
path: |
|
|
||||||
crash-*
|
|
||||||
leak-*
|
|
||||||
timeout-*
|
|
||||||
if-no-files-found: ignore
|
|
||||||
|
|
||||||
build:
|
build:
|
||||||
# Verify we can build on latest Ubuntu with both gcc and clang
|
# Verify we can build on latest Ubuntu with both gcc and clang
|
||||||
name: ${{ matrix.compiler }}
|
name: ${{ matrix.compiler }}
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-18.04
|
||||||
# Skip redundant builds for PRs - prefer PR builds over push builds
|
|
||||||
if: github.event_name != 'push' || github.ref == 'refs/heads/master'
|
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
compiler: [gcc, clang]
|
compiler: [gcc, clang]
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
env:
|
env:
|
||||||
|
MAKEFLAGS: -j3
|
||||||
CC: ${{ matrix.compiler }}
|
CC: ${{ matrix.compiler }}
|
||||||
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 tree jq libcap-dev libconfuse-dev libblkid-dev
|
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/libuev/releases/download/v2.3.2/libuev-2.3.2.tar.xz
|
||||||
wget https://github.com/troglobit/libite/releases/download/v2.6.2/libite-2.6.2.tar.gz
|
wget https://github.com/troglobit/libite/releases/download/v2.3.1/libite-2.3.1.tar.gz
|
||||||
tar xf libuev-2.4.1.tar.xz
|
tar xf libuev-2.3.2.tar.xz
|
||||||
tar xf libite-2.6.2.tar.gz
|
tar xf libite-2.3.1.tar.gz
|
||||||
(cd libuev-2.4.1 && ./configure && make -j9 && sudo make install-strip)
|
(cd libuev-2.3.2 && ./configure --prefix=/usr && make && sudo make install-strip)
|
||||||
(cd libite-2.6.2 && ./configure && make -j9 && sudo make install-strip)
|
(cd libite-2.3.1 && ./configure --prefix=/usr && make && sudo make install-strip)
|
||||||
sudo ldconfig
|
sudo ldconfig
|
||||||
- uses: actions/checkout@v7
|
- uses: actions/checkout@v2
|
||||||
- name: Static Finit
|
- name: Static Finit
|
||||||
run: |
|
run: |
|
||||||
./autogen.sh
|
./autogen.sh
|
||||||
./configure --prefix= --enable-static
|
./configure --prefix= --enable-static
|
||||||
make -j9 V=1
|
make V=1
|
||||||
- name: Regular Finit
|
- name: Regular Finit
|
||||||
run: |
|
run: |
|
||||||
./configure --prefix=/usr --exec-prefix= --sysconfdir=/etc --localstatedir=/var \
|
./configure --prefix= --enable-x11-common-plugin --with-watchdog --with-keventd
|
||||||
--enable-x11-common-plugin --enable-testserv-plugin \
|
make clean
|
||||||
CFLAGS="-fsanitize=address -ggdb"
|
make V=1
|
||||||
make -j9 clean
|
- name: Install to ~/tmp and Inspect
|
||||||
make -j9 V=1
|
|
||||||
- name: Install to /tmp
|
|
||||||
run: |
|
run: |
|
||||||
DESTDIR=/tmp make install-strip
|
DESTDIR=/tmp make install-strip
|
||||||
tree /tmp || true
|
tree /tmp
|
||||||
- name: Check dependencies
|
|
||||||
run: |
|
|
||||||
ldd /tmp/sbin/finit
|
ldd /tmp/sbin/finit
|
||||||
size /tmp/sbin/finit
|
size /tmp/sbin/finit
|
||||||
ldd /tmp/sbin/initctl
|
ldd /tmp/sbin/initctl
|
||||||
size /tmp/sbin/initctl
|
size /tmp/sbin/initctl
|
||||||
ldd /tmp/sbin/reboot
|
ldd /tmp/sbin/reboot
|
||||||
size /tmp/sbin/reboot
|
size /tmp/sbin/reboot
|
||||||
- name: Verify starting and showing usage text
|
/tmp/sbin/finit -h
|
||||||
run: |
|
/tmp/sbin/initctl -h
|
||||||
sudo /tmp/sbin/finit -h
|
|
||||||
sudo /tmp/sbin/initctl -h
|
|
||||||
- name: Enable unprivileged userns (unshare)
|
|
||||||
run: |
|
|
||||||
sudo sysctl kernel.apparmor_restrict_unprivileged_userns=0
|
|
||||||
- name: Run Unit Tests
|
- name: Run Unit Tests
|
||||||
run: |
|
run: |
|
||||||
make -j1 check || (cat test/test-suite.log; false)
|
ver=$(/tmp/sbin/initctl -V | awk '/Finit.*/ {print $2;}')
|
||||||
|
dir=finit-$ver/_build/sub
|
||||||
|
make -j1 distcheck || (cat $dir/test/setup-root.log; cat $dir/test/test-suite.log; false)
|
||||||
- name: Upload Test Results
|
- name: Upload Test Results
|
||||||
if: always()
|
uses: actions/upload-artifact@v2
|
||||||
uses: actions/upload-artifact@v7
|
|
||||||
with:
|
with:
|
||||||
name: finit-test-${{ matrix.compiler }}
|
name: finit-test-${{ matrix.compiler }}
|
||||||
path: test/*.log
|
path: test/*
|
||||||
|
|
||||||
no-dbus:
|
|
||||||
# The D-Bus support is default-enabled, so the HAVE_DBUS paths in
|
|
||||||
# initctl and finit only bit-rot silently without this leg.
|
|
||||||
name: no-dbus
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
if: github.event_name != 'push' || github.ref == 'refs/heads/master'
|
|
||||||
steps:
|
|
||||||
- name: Install dependencies
|
|
||||||
run: |
|
|
||||||
sudo apt-get -y update
|
|
||||||
sudo apt-get -y install pkg-config tree jq libcap-dev libconfuse-dev libblkid-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
|
|
||||||
- uses: actions/checkout@v7
|
|
||||||
- name: Build without D-Bus
|
|
||||||
run: |
|
|
||||||
./autogen.sh
|
|
||||||
./configure --prefix=/usr --exec-prefix= --sysconfdir=/etc --localstatedir=/var \
|
|
||||||
--disable-dbus --enable-testserv-plugin
|
|
||||||
make -j9 V=1
|
|
||||||
- name: Verify no bus artifacts
|
|
||||||
run: |
|
|
||||||
DESTDIR=/tmp make install-strip
|
|
||||||
! strings /tmp/sbin/initctl | grep -q finit/bus
|
|
||||||
! strings /tmp/sbin/finit | grep -q org.finit
|
|
||||||
- name: Enable unprivileged userns (unshare)
|
|
||||||
run: |
|
|
||||||
sudo sysctl kernel.apparmor_restrict_unprivileged_userns=0
|
|
||||||
- name: Smoke test
|
|
||||||
run: |
|
|
||||||
make -C test setup-chroot
|
|
||||||
make -j1 -C test check TESTS='start-stop-serv.sh' \
|
|
||||||
|| (cat test/test-suite.log; false)
|
|
||||||
|
|||||||
@@ -4,10 +4,6 @@ on:
|
|||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- 'dev'
|
- 'dev'
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
|
|
||||||
env:
|
env:
|
||||||
PROJECT_NAME: finit
|
PROJECT_NAME: finit
|
||||||
@@ -19,59 +15,40 @@ jobs:
|
|||||||
coverity:
|
coverity:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v7
|
- uses: actions/checkout@v2
|
||||||
- name: Fetch latest Coverity Scan MD5
|
- uses: actions/cache@v2
|
||||||
id: var
|
id: coverity-toolchain-cache
|
||||||
env:
|
|
||||||
TOKEN: ${{ secrets.COVERITY_SCAN_TOKEN }}
|
|
||||||
run: |
|
|
||||||
wget -q https://scan.coverity.com/download/cxx/linux64 \
|
|
||||||
--post-data "token=$TOKEN&project=${COVERITY_PROJ}&md5=1" \
|
|
||||||
-O coverity-latest.tar.gz.md5
|
|
||||||
echo "md5=$(cat coverity-latest.tar.gz.md5)" | tee -a $GITHUB_OUTPUT
|
|
||||||
- uses: actions/cache@v6
|
|
||||||
id: cache
|
|
||||||
with:
|
with:
|
||||||
path: coverity-latest.tar.gz
|
path: cov-analysis-linux64
|
||||||
key: ${{ runner.os }}-coverity-${{ steps.var.outputs.md5 }}
|
key: ${{ runner.os }}-coverity
|
||||||
restore-keys: |
|
|
||||||
${{ runner.os }}-coverity-${{ steps.var.outputs.md5 }}
|
|
||||||
${{ runner.os }}-coverity-
|
|
||||||
${{ runner.os }}-coverity
|
|
||||||
- name: Download Coverity Scan
|
- name: Download Coverity Scan
|
||||||
|
if: steps.coverity-toolchain-cache.outputs.cache-hit != 'true'
|
||||||
env:
|
env:
|
||||||
TOKEN: ${{ secrets.COVERITY_SCAN_TOKEN }}
|
TOKEN: ${{ secrets.COVERITY_SCAN_TOKEN }}
|
||||||
run: |
|
run: |
|
||||||
if [ ! -f coverity-latest.tar.gz ]; then
|
wget -q https://scan.coverity.com/download/cxx/linux64 \
|
||||||
wget -q https://scan.coverity.com/download/cxx/linux64 \
|
--post-data "token=$TOKEN&project=${COVERITY_PROJ}" \
|
||||||
--post-data "token=$TOKEN&project=${COVERITY_PROJ}" \
|
-O cov-analysis-linux64.tar.gz
|
||||||
-O coverity-latest.tar.gz
|
mkdir cov-analysis-linux64
|
||||||
else
|
tar xzf cov-analysis-linux64.tar.gz --strip 1 -C cov-analysis-linux64
|
||||||
echo "Latest Coverity Scan available from cache :-)"
|
|
||||||
md5sum coverity-latest.tar.gz
|
|
||||||
fi
|
|
||||||
mkdir coverity
|
|
||||||
tar xzf coverity-latest.tar.gz --strip 1 -C coverity
|
|
||||||
- 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 libcap-dev libconfuse-dev libblkid-dev
|
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/libuev/releases/download/v2.3.2/libuev-2.3.2.tar.xz
|
||||||
wget https://github.com/troglobit/libite/releases/download/v2.6.2/libite-2.6.2.tar.gz
|
wget https://github.com/troglobit/libite/releases/download/v2.3.1/libite-2.3.1.tar.gz
|
||||||
tar xf libuev-2.4.1.tar.xz
|
tar xf libuev-2.3.2.tar.xz
|
||||||
tar xf libite-2.6.2.tar.gz
|
tar xf libite-2.3.1.tar.gz
|
||||||
(cd libuev-2.4.1 && ./configure && make -j9 && sudo make install-strip)
|
(cd libuev-2.3.2 && ./configure --prefix=/usr && make && sudo make install-strip)
|
||||||
(cd libite-2.6.2 && ./configure && make -j9 && sudo make install-strip)
|
(cd libite-2.3.1 && ./configure --prefix=/usr && make && sudo make install-strip)
|
||||||
sudo ldconfig
|
sudo ldconfig
|
||||||
- name: Configure
|
|
||||||
run: |
|
|
||||||
./autogen.sh
|
|
||||||
./configure --prefix= --enable-x11-common-plugin
|
|
||||||
- name: Build
|
- name: Build
|
||||||
run: |
|
run: |
|
||||||
export PATH=`pwd`/coverity/bin:$PATH
|
./autogen.sh
|
||||||
|
./configure --prefix= --enable-x11-common-plugin --with-watchdog --with-keventd
|
||||||
|
export PATH=`pwd`/cov-analysis-linux64/bin:$PATH
|
||||||
cov-build --dir cov-int make
|
cov-build --dir cov-int make
|
||||||
- name: Submit results to Coverity Scan
|
- name: Submit result to Coverity Scan
|
||||||
env:
|
env:
|
||||||
TOKEN: ${{ secrets.COVERITY_SCAN_TOKEN }}
|
TOKEN: ${{ secrets.COVERITY_SCAN_TOKEN }}
|
||||||
run: |
|
run: |
|
||||||
@@ -84,8 +61,3 @@ jobs:
|
|||||||
--form version=trunk \
|
--form version=trunk \
|
||||||
--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
|
|
||||||
uses: actions/upload-artifact@v7
|
|
||||||
with:
|
|
||||||
name: coverity-build.log
|
|
||||||
path: cov-int/build-log.txt
|
|
||||||
|
|||||||
@@ -1,163 +0,0 @@
|
|||||||
name: Dotty the Documenteer
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- master
|
|
||||||
- 4.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
|
|
||||||
@@ -3,79 +3,67 @@ name: Release General
|
|||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
tags:
|
tags:
|
||||||
- '[0-9]+.[0-9]+*'
|
- '[0-9]+.[0-9]+'
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: write
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
release:
|
release:
|
||||||
|
name: Create GitHub release
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
if: startsWith(github.ref, 'refs/tags/')
|
||||||
|
outputs:
|
||||||
|
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||||
|
release_id: ${{ steps.create_release.outputs.id }}
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- name: Extract ChangeLog entry ...
|
||||||
|
# Hack to extract latest entry for body_path below
|
||||||
|
run: |
|
||||||
|
awk '/-----*/{if (x == 1) exit; x=1;next}x' ChangeLog.md \
|
||||||
|
|head -n -1 > release.md
|
||||||
|
cat release.md
|
||||||
|
- name: Create release ...
|
||||||
|
id: create_release
|
||||||
|
uses: actions/create-release@v1
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
with:
|
||||||
|
tag_name: ${{ github.ref }}
|
||||||
|
release_name: Finit v${{ github.ref }}
|
||||||
|
body_path: release.md
|
||||||
|
draft: false
|
||||||
|
prerelease: false
|
||||||
|
tarball:
|
||||||
name: Build and upload release tarball
|
name: Build and upload release tarball
|
||||||
|
needs: release
|
||||||
if: startsWith(github.ref, 'refs/tags/')
|
if: startsWith(github.ref, 'refs/tags/')
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v7
|
- uses: actions/checkout@v2
|
||||||
- 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 libcap-dev libconfuse-dev libblkid-dev
|
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/libuev/releases/download/v2.3.2/libuev-2.3.2.tar.xz
|
||||||
wget https://github.com/troglobit/libite/releases/download/v2.6.2/libite-2.6.2.tar.gz
|
wget https://github.com/troglobit/libite/releases/download/v2.3.1/libite-2.3.1.tar.gz
|
||||||
tar xf libuev-2.4.1.tar.xz
|
tar xf libuev-2.3.2.tar.xz
|
||||||
tar xf libite-2.6.2.tar.gz
|
tar xf libite-2.3.1.tar.gz
|
||||||
(cd libuev-2.4.1 && ./configure && make -j9 && sudo make install-strip)
|
(cd libuev-2.3.2 && ./configure --prefix=/usr && make && sudo make install-strip)
|
||||||
(cd libite-2.6.2 && ./configure && make -j9 && sudo make install-strip)
|
(cd libite-2.3.1 && ./configure --prefix=/usr && make && sudo make install-strip)
|
||||||
sudo ldconfig
|
sudo ldconfig
|
||||||
- name: Setting release variables ...
|
- name: Creating Makefiles
|
||||||
id: build
|
|
||||||
run: |
|
|
||||||
ver=${GITHUB_REF#refs/tags/}
|
|
||||||
echo "ver=${ver}" >> $GITHUB_OUTPUT
|
|
||||||
if echo $ver | grep -qE '^[0-9]+\.[0-9]+(\.[0-9]+)?(-alpha|-beta|-rc)[0-9]*$'; then
|
|
||||||
echo "pre=true" >> $GITHUB_OUTPUT
|
|
||||||
else
|
|
||||||
echo "pre=false" >> $GITHUB_OUTPUT
|
|
||||||
fi
|
|
||||||
if echo $ver | grep -qE '^[0-9.]+\.[0-9.]+(\.[0-9]+)?$'; then
|
|
||||||
echo "latest=true" >> $GITHUB_OUTPUT
|
|
||||||
else
|
|
||||||
echo "latest=false" >> $GITHUB_OUTPUT
|
|
||||||
fi
|
|
||||||
- name: Creating Makefiles ...
|
|
||||||
run: |
|
run: |
|
||||||
./autogen.sh
|
./autogen.sh
|
||||||
./configure --prefix=/usr --exec-prefix= --sysconfdir=/etc \
|
./configure --prefix= --enable-x11-common-plugin --with-watchdog --with-keventd
|
||||||
--localstatedir=/var --enable-x11-common-plugin \
|
- name: Building release
|
||||||
--enable-testserv-plugin
|
|
||||||
- name: Enable unprivileged userns (unshare)
|
|
||||||
run: |
|
run: |
|
||||||
sudo sysctl kernel.apparmor_restrict_unprivileged_userns=0
|
make release
|
||||||
- name: Build release ...
|
|
||||||
run: |
|
|
||||||
# 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
|
- name: Uploading release artifacts
|
||||||
if: always()
|
uses: skx/github-action-publish-binaries@release-0.15
|
||||||
uses: actions/upload-artifact@v7
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
with:
|
with:
|
||||||
name: finit-release-test-logs
|
releaseId: ${{ needs.release.outputs.release_id }}
|
||||||
path: finit-*/_build/sub/test/*.log
|
args: artifacts/*
|
||||||
- name: Extract ChangeLog entry ...
|
|
||||||
run: |
|
|
||||||
awk '/-----*/{if (x == 1) exit; x=1;next}x' doc/ChangeLog.md \
|
|
||||||
|head -n -1 > release.md
|
|
||||||
cat release.md
|
|
||||||
- uses: ncipollo/release-action@v1
|
|
||||||
with:
|
|
||||||
name: Finit v${{ github.ref_name }}
|
|
||||||
prerelease: ${{ steps.build.outputs.pre }}
|
|
||||||
makeLatest: ${{ steps.build.outputs.latest }}
|
|
||||||
bodyFile: "release.md"
|
|
||||||
artifacts: "artifacts/*"
|
|
||||||
|
|||||||
@@ -1,67 +0,0 @@
|
|||||||
name: Weekly Distcheck
|
|
||||||
|
|
||||||
# Verify that `make distcheck` works as intended: all tests pass, and
|
|
||||||
# any new files are distributed in the tarballs
|
|
||||||
on:
|
|
||||||
schedule:
|
|
||||||
- cron: '0 0 * * 0'
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
schedule:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
outputs:
|
|
||||||
run: ${{ steps.schedule.outputs.run }}
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v7
|
|
||||||
- name: Check for any commits since last week
|
|
||||||
id: schedule
|
|
||||||
run: |
|
|
||||||
commits="$(git log --format=%H --since='1 week ago')"
|
|
||||||
if [ -z "$commits" ]; then
|
|
||||||
echo "run=true" >> $GITHUB_OUTPUT
|
|
||||||
else
|
|
||||||
echo "run=false" >> $GITHUB_OUTPUT
|
|
||||||
fi
|
|
||||||
distcheck:
|
|
||||||
needs: schedule
|
|
||||||
if: ${{ needs.schedule.outputs.run == 'true' }}
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Install dependencies
|
|
||||||
run: |
|
|
||||||
sudo apt-get -y update
|
|
||||||
sudo apt-get -y install pkg-config jq libcap-dev libconfuse-dev libblkid-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
|
|
||||||
- uses: actions/checkout@v7
|
|
||||||
- name: Base run
|
|
||||||
run: |
|
|
||||||
./autogen.sh
|
|
||||||
./configure --prefix=/usr --exec-prefix= --sysconfdir=/etc --localstatedir=/var
|
|
||||||
make -j9 V=1
|
|
||||||
- name: Install to /tmp
|
|
||||||
run: |
|
|
||||||
DESTDIR=/tmp make install-strip
|
|
||||||
- name: Enable unprivileged userns (unshare)
|
|
||||||
run: |
|
|
||||||
sudo sysctl kernel.apparmor_restrict_unprivileged_userns=0
|
|
||||||
- name: Check dist tarball
|
|
||||||
run: |
|
|
||||||
ver=$(/tmp/sbin/initctl -V | awk '/Finit.*/ {print $2;}')
|
|
||||||
dir=finit-$ver/_build/sub
|
|
||||||
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
|
|
||||||
path: finit-*/_build/sub/test/*.log
|
|
||||||
@@ -14,7 +14,6 @@ GTAGS
|
|||||||
/autom4te.cache
|
/autom4te.cache
|
||||||
/aclocal.m4
|
/aclocal.m4
|
||||||
/ar-lib
|
/ar-lib
|
||||||
/backup/
|
|
||||||
/compile
|
/compile
|
||||||
/config.cache
|
/config.cache
|
||||||
/config.h
|
/config.h
|
||||||
@@ -37,9 +36,6 @@ GTAGS
|
|||||||
/test-driver
|
/test-driver
|
||||||
/test-suite.log
|
/test-suite.log
|
||||||
|
|
||||||
# Misc
|
|
||||||
/.gdb_history
|
|
||||||
|
|
||||||
# TroglOS build system
|
# TroglOS build system
|
||||||
/.config
|
/.config
|
||||||
/.stamp
|
/.stamp
|
||||||
@@ -52,8 +48,3 @@ GTAGS
|
|||||||
|
|
||||||
# VS Code user settings
|
# VS Code user settings
|
||||||
.vscode
|
.vscode
|
||||||
|
|
||||||
# Fuzzing: the target is built by hand with clang, see doc/build.md,
|
|
||||||
# and the corpus it grows is a local artefact, not something to ship
|
|
||||||
/fuzz-msg-parse
|
|
||||||
/.fuzz-corpus/
|
|
||||||
|
|||||||
@@ -1,15 +0,0 @@
|
|||||||
# GNU Global .conf file, see /etc/gtags/gtags.conf for details.
|
|
||||||
# This configuration is optimized for the Finit project structure.
|
|
||||||
|
|
||||||
default:\
|
|
||||||
:tc=default@/etc/gtags/gtags.conf:\
|
|
||||||
:tc=common:
|
|
||||||
|
|
||||||
common:\
|
|
||||||
:skip=tags,TAGS,ID,y.tab.c,y.tab.h,gtags.files,cscope.files,cscope.out,cscope.po.out,cscope.in.out,\
|
|
||||||
{arch}/,autom4te.cache/,\
|
|
||||||
*.orig,*.rej,*.bak,*~,#*#,*.swp,*.tmp,*_flymake.*,*_flymake,\
|
|
||||||
*.o,*.a,*.so,*.lo,*.la,\
|
|
||||||
*.zip,*.gz,*.bz2,*.xz,*.lzh,*.Z,*.tgz,\
|
|
||||||
*.log,*.trs,test-suite.log,stamp-*,\
|
|
||||||
sysroot/:
|
|
||||||
+1100
File diff suppressed because it is too large
Load Diff
@@ -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-2025 Joachim Wiberg <troglobit@gmail.com>
|
Copyright (c) 2008-2021 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
|
||||||
|
|||||||
+3
-41
@@ -1,22 +1,7 @@
|
|||||||
ACLOCAL_AMFLAGS = -I m4
|
ACLOCAL_AMFLAGS = -I m4
|
||||||
|
SUBDIRS = man plugins src test
|
||||||
# libink must precede src in SUBDIRS because finit links against
|
doc_DATA = README.md LICENSE contrib/finit.conf
|
||||||
# libink at build time. Automake recurses subdirs strictly in
|
EXTRA_DIST = README.md LICENSE ChangeLog.md contrib/finit.conf
|
||||||
# declaration order, so the typical "explicit dependency" pattern
|
|
||||||
# (foo: bar) doesn't help here — ordering is the only thing that
|
|
||||||
# does. libsystemd is consumed by test/serv only, so its position
|
|
||||||
# after src is fine.
|
|
||||||
SUBDIRS = man plugins
|
|
||||||
if DBUS
|
|
||||||
SUBDIRS += libink dbus-1
|
|
||||||
endif
|
|
||||||
SUBDIRS += src system tmpfiles.d
|
|
||||||
|
|
||||||
if KEVENTD
|
|
||||||
SUBDIRS += keventd
|
|
||||||
endif
|
|
||||||
|
|
||||||
dist_doc_DATA = README.md LICENSE contrib/finit.conf
|
|
||||||
|
|
||||||
if CONTRIB
|
if CONTRIB
|
||||||
SUBDIRS += contrib
|
SUBDIRS += contrib
|
||||||
@@ -24,29 +9,11 @@ endif
|
|||||||
if DOC
|
if DOC
|
||||||
SUBDIRS += doc
|
SUBDIRS += doc
|
||||||
endif
|
endif
|
||||||
if LIBSYSTEMD
|
|
||||||
SUBDIRS += libsystemd
|
|
||||||
endif
|
|
||||||
|
|
||||||
if LIBSYSTEMD
|
|
||||||
SUBDIRS += test
|
|
||||||
# Explicit dependency to ensure libsystemd is built before test
|
|
||||||
test: libsystemd
|
|
||||||
else
|
|
||||||
SUBDIRS += test
|
|
||||||
endif
|
|
||||||
|
|
||||||
# Compat hook
|
# Compat hook
|
||||||
install-dev:
|
install-dev:
|
||||||
@make -C src install-pkgincludeHEADERS
|
@make -C src install-pkgincludeHEADERS
|
||||||
|
|
||||||
# The fuzz target is built by hand with clang (doc/build.md), so it is
|
|
||||||
# not in any _PROGRAMS and nothing else would clear it or the corpus
|
|
||||||
# it grows.
|
|
||||||
distclean-local:
|
|
||||||
-rm -f $(top_builddir)/fuzz-msg-parse
|
|
||||||
-rm -rf $(top_builddir)/.fuzz-corpus
|
|
||||||
|
|
||||||
# Target to run when building a release
|
# Target to run when building a release
|
||||||
release: distcheck
|
release: distcheck
|
||||||
@for file in $(DIST_ARCHIVES); do \
|
@for file in $(DIST_ARCHIVES); do \
|
||||||
@@ -62,8 +29,3 @@ release: distcheck
|
|||||||
printf "$$file.md5\t"; cat ../$$file.md5 | cut -f1 -d' '; \
|
printf "$$file.md5\t"; cat ../$$file.md5 | cut -f1 -d' '; \
|
||||||
printf "$$file.sha256\t"; cat ../$$file.sha256 | cut -f1 -d' '; \
|
printf "$$file.sha256\t"; cat ../$$file.sha256 | cut -f1 -d' '; \
|
||||||
done
|
done
|
||||||
|
|
||||||
DISTCHECK_CONFIGURE_FLAGS = --prefix=/usr --sysconfdir=/etc --localstatedir=/var \
|
|
||||||
--enable-testserv-plugin --enable-x11-common-plugin \
|
|
||||||
--with-fstab=/etc/fstab --with-libsystemd \
|
|
||||||
--with-bash-completion-dir=no
|
|
||||||
|
|||||||
@@ -1,50 +1,604 @@
|
|||||||
[![License Badge][]][License] [![Release Badge][]][Release] [![GitHub Status][]][GitHub] [![Coverity Status][]][Coverity Scan]
|
[![License Badge][]][License] [![GitHub Status][]][GitHub] [![Coverity Status][]][Coverity Scan]
|
||||||
<img align="right" src="doc/img/finit3.png" alt="Finit: Fast Init">
|
<img align="right" src="img/finit3.png" alt="Finit: Fast Init">
|
||||||
|
|
||||||
Finit is a fast, simple alternative to [SysV init](https://en.wikipedia.org/wiki/Init)
|
* [Introduction](#introduction)
|
||||||
and [systemd](https://systemd.io), designed for small and embedded Linux systems.
|
* [Features](#features)
|
||||||
It can also run on desktop and server systems, like [finix][].
|
* [Bootstrap](doc/bootstrap.md#bootstrap)
|
||||||
|
* [Runlevels](#runlevels)
|
||||||
|
* [Syntax](doc/config.md#syntax)
|
||||||
|
* [Runparts & /etc/rc.local](#runparts--etcrclocal)
|
||||||
|
* [Hooks, Callbacks & Plugins](doc/plugins.md#hooks-callbacks--plugins)
|
||||||
|
* [Rebooting & Halting](#rebooting--halting)
|
||||||
|
* [Commands & Status](#commands--status)
|
||||||
|
* [Tips & Tricks with the kernel cmdline](doc/cmdline.md)
|
||||||
|
* [Building](doc/build.md#building)
|
||||||
|
* [Running](doc/build.md#running)
|
||||||
|
* [Recovery](doc/build.md#recovery)
|
||||||
|
* [Debugging](doc/build.md#debugging)
|
||||||
|
* [Requirements](#requirements)
|
||||||
|
* [Origin & References](#origin--references)
|
||||||
|
|
||||||
> Reverse engineered from the [EeePC fastinit][]
|
|
||||||
> "gaps filled with frog DNA …"
|
|
||||||
> — [Claudio Matsuoka][]
|
|
||||||
|
|
||||||
For detailed information, explore our extensive documentation
|
Introduction
|
||||||
:books: **<http://finit-project.github.io>**
|
------------
|
||||||
|
|
||||||
<div align="center">
|
Fast init for Linux systems. Reverse engineered from the [EeePC
|
||||||
<img src="doc/img/alpine-screenshot2.png" alt="Alpine screenshot"><br/>
|
fastinit][] over ten years ago by [Claudio Matsuoka][] — "gaps filled
|
||||||
</div>
|
with frog DNA …"
|
||||||
|
|
||||||
For working examples, see the :rocket: [contrib/](contrib/) section or these
|

|
||||||
tutorials:
|
*Figure 1: Screenshot showing Finit booting [Alpine Linux](https://www.alpinelinux.org/).*
|
||||||
|
|
||||||
* :hammer_and_wrench: [Buildroot embedded Linux][br2demo],
|
Features include:
|
||||||
* :package: [Debian GNU/Linux](contrib/debian/),
|
|
||||||
* :mountain: [Alpine Linux](contrib/alpine/), and
|
|
||||||
* :milky_way: [Void Linux](contrib/void/)
|
|
||||||
|
|
||||||
> [!NOTE]
|
* Runlevels, defined per service
|
||||||
> Finit can run on various Linux distributions, but the bundled install
|
* One-shot tasks, services (daemons), or [SysV init][4] start/stop scripts
|
||||||
> scripts are examples only. They have been tested on amd64 (x86_64) systems
|
* Runparts and `/etc/rc.local` support
|
||||||
> with standard configurations.
|
* Process supervision similar to [systemd][]
|
||||||
>
|
* Sourcing environment files
|
||||||
> For embedded systems, see these [Buildroot][]-based examples:
|
* Conditions for network/process/custom dependencies
|
||||||
> [myLinux][], [Infix][], or [br2-finit-demo][].
|
* Pre/Post script actions
|
||||||
|
* 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
|
||||||
|
|
||||||
[finix]: https://github.com/finix-community/finix
|
Focus is on small and embedded systems, although Finit is fully usable
|
||||||
[Buildroot]: https://buildroot.org
|
on server and desktop systems as well. For working examples, see the
|
||||||
[Infix]: https://kernelkit.github.io
|
[contrib/](contrib/) section with tutorials for:
|
||||||
[myLinux]: https://github.com/troglobit/myLinux/
|
|
||||||
[br2demo]: https://troglobit.com/post/2022-12-26-buildroot-demo-of-fastinit-finit/
|
* [Void Linux](contrib/void/),
|
||||||
|
* [Alpine Linux](contrib/alpine/), and
|
||||||
|
* [Debian GNU/Linux](contrib/debian/)
|
||||||
|
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
```ApacheConf
|
||||||
|
# Fallback if /etc/hostname is missing
|
||||||
|
host default
|
||||||
|
|
||||||
|
# Runlevel to start after bootstrap, 'S', default: 2
|
||||||
|
runlevel 2
|
||||||
|
|
||||||
|
# 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
|
||||||
|
|
||||||
|
# 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(0) 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.
|
||||||
|
|
||||||
|
|
||||||
|
**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.
|
||||||
|
|
||||||
|
|
||||||
|
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), and about the system bootstrap
|
||||||
|
in [doc/bootstrap.md](doc/bootstrap.md).
|
||||||
|
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
```
|
||||||
|
alpine:~# initctl help
|
||||||
|
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
|
||||||
|
-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
|
||||||
|
-h, --help This help text
|
||||||
|
|
||||||
|
Commands:
|
||||||
|
debug Toggle Finit (daemon) debug
|
||||||
|
help This help text
|
||||||
|
version Show Finit 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 condition +usr/COND
|
||||||
|
cond clear <COND> Clear (deassert) user-defined condition -usr/COND
|
||||||
|
cond status Show condition status, default cond command
|
||||||
|
cond dump Dump all 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 by name (SIGHUP or restart)
|
||||||
|
restart <NAME>[:ID] Restart (stop/start) service by name
|
||||||
|
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
|
||||||
|
|
||||||
|
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
|
||||||
|
```
|
||||||
|
|
||||||
|
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 [S12345----] Kernel log daemon
|
||||||
|
1512 ntpd running [--2345----] NTP daemon
|
||||||
|
1473 syslogd running [S12345----] 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 [S12345----] klogd -n $KLOGD_OPTS
|
||||||
|
1512 ntpd running [--2345----] ntpd -n $NTPD_OPTS
|
||||||
|
1473 syslogd running [S12345----] 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/
|
||||||
|
[run-parts(8)]: https://manpages.debian.org/cgi-bin/man.cgi?query=run-parts
|
||||||
|
[original finit]: http://helllabs.org/finit/
|
||||||
[EeePC fastinit]: https://web.archive.org/web/20071208212450/http://wiki.eeeuser.com/boot_process:the_boot_process
|
[EeePC fastinit]: https://web.archive.org/web/20071208212450/http://wiki.eeeuser.com/boot_process:the_boot_process
|
||||||
[Claudio Matsuoka]: https://github.com/cmatsuoka
|
[Claudio Matsuoka]: https://github.com/cmatsuoka
|
||||||
|
[Joachim Wiberg]: https://troglobit.com
|
||||||
[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
|
||||||
[Release]: https://github.com/finit-project/finit/releases
|
[GitHub]: https://github.com/troglobit/finit/actions/workflows/build.yml/
|
||||||
[Release Badge]: https://img.shields.io/github/v/release/finit-project/finit
|
[GitHub Status]: https://github.com/troglobit/finit/actions/workflows/build.yml/badge.svg
|
||||||
[GitHub]: https://github.com/finit-project/finit/actions/workflows/build.yml/
|
|
||||||
[GitHub Status]: https://github.com/finit-project/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
|
|
||||||
|
|||||||
+39
-223
@@ -1,28 +1,21 @@
|
|||||||
AC_INIT([Finit], [5.0-rc1], [https://github.com/finit-project/finit/issues],
|
AC_INIT(Finit, 4.3-dev, https://github.com/troglobit/finit/issues, finit, https://troglobit.com/finit.html)
|
||||||
[finit], [https://http://finit-project.github.io/])
|
|
||||||
AC_CONFIG_AUX_DIR(aux)
|
AC_CONFIG_AUX_DIR(aux)
|
||||||
AM_INIT_AUTOMAKE([1.11 foreign subdir-objects])
|
AM_INIT_AUTOMAKE([1.11 foreign dist-xz subdir-objects])
|
||||||
AM_SILENT_RULES([yes])
|
AM_SILENT_RULES([yes])
|
||||||
|
|
||||||
AC_CONFIG_SRCDIR([src/finit.c])
|
AC_CONFIG_SRCDIR([src/finit.c])
|
||||||
AC_CONFIG_HEADERS([config.h])
|
AC_CONFIG_HEADER([config.h])
|
||||||
AC_CONFIG_FILES([Makefile
|
AC_CONFIG_FILES([Makefile
|
||||||
contrib/Makefile
|
contrib/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/config/Makefile
|
doc/Makefile
|
||||||
dbus-1/Makefile
|
|
||||||
libink/Makefile
|
|
||||||
libsystemd/Makefile libsystemd/libsystemd.pc
|
|
||||||
man/Makefile
|
man/Makefile
|
||||||
plugins/Makefile
|
plugins/Makefile
|
||||||
src/Makefile
|
src/Makefile
|
||||||
keventd/Makefile
|
|
||||||
system/Makefile system/10-hotplug.conf
|
|
||||||
test/test.env test/Makefile
|
test/test.env test/Makefile
|
||||||
test/lib/Makefile test/src/Makefile
|
test/tenv/Makefile test/common/Makefile])
|
||||||
tmpfiles.d/Makefile])
|
|
||||||
|
|
||||||
# Older versions of autoconf (<2.58) do not have AC_CONFIG_MACRO_DIR()
|
# Older versions of autoconf (<2.58) do not have AC_CONFIG_MACRO_DIR()
|
||||||
#m4_include([m4/plugin.m4])
|
#m4_include([m4/plugin.m4])
|
||||||
@@ -39,8 +32,9 @@ AC_PROG_INSTALL
|
|||||||
AC_PROG_MKDIR_P
|
AC_PROG_MKDIR_P
|
||||||
|
|
||||||
# Configuration.
|
# Configuration.
|
||||||
AC_CHECK_HEADERS([termios.h sys/ioctl.h mntent.h sys/sysmacros.h])
|
AC_HEADER_STDC
|
||||||
AC_CHECK_FUNCS([strstr getopt getmntent getmntent_r])
|
AC_CHECK_HEADERS([fstaby.h termios.h sys/ioctl.h])
|
||||||
|
AC_CHECK_FUNCS([strstr getopt getfsenty])
|
||||||
|
|
||||||
# Check for uint[8,16,32]_t
|
# Check for uint[8,16,32]_t
|
||||||
AC_TYPE_UINT8_T
|
AC_TYPE_UINT8_T
|
||||||
@@ -51,14 +45,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.4.1])
|
PKG_CHECK_MODULES([uev], [libuev >= 2.2.0])
|
||||||
PKG_CHECK_MODULES([lite], [libite >= 2.6.1])
|
PKG_CHECK_MODULES([lite], [libite >= 2.2.0])
|
||||||
# 3.3 is the floor: CFGF_KEYSTRVAL, which environment {} and the
|
|
||||||
# free-form cgroup keys are built on, does not exist before it. 3.3
|
|
||||||
# parses both correctly. Two workarounds hang off this number, the
|
|
||||||
# spurious KEYSTRVAL warning and cfg_parse_buf() losing the file name
|
|
||||||
# of a template; grep the XXX notes in src/conf.c before raising it.
|
|
||||||
PKG_CHECK_MODULES([confuse], [libconfuse >= 3.3])
|
|
||||||
|
|
||||||
# Check for configured Finit features
|
# Check for configured Finit features
|
||||||
AC_ARG_ENABLE(auto_reload,
|
AC_ARG_ENABLE(auto_reload,
|
||||||
@@ -77,30 +65,14 @@ AC_ARG_ENABLE(fsckfix,
|
|||||||
AS_HELP_STRING([--enable-fsckfix], [Run fsck fix mode (options: -yf) on filesystems listed in /etc/fstab]),,[
|
AS_HELP_STRING([--enable-fsckfix], [Run fsck fix mode (options: -yf) on filesystems listed in /etc/fstab]),,[
|
||||||
enable_fsckfix=no])
|
enable_fsckfix=no])
|
||||||
|
|
||||||
AC_ARG_ENABLE(cgroup,
|
|
||||||
AS_HELP_STRING([--disable-cgroup], [Disable cgroup v2 support, default: autodetect from /sys/fs/cgroup]),,[
|
|
||||||
enable_cgroup=yes])
|
|
||||||
|
|
||||||
AC_ARG_ENABLE(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])
|
||||||
|
|
||||||
AC_ARG_ENABLE(kernel_logging,
|
|
||||||
AS_HELP_STRING([--disable-kernel-logging], [Disable kernel logging to console (use 'quiet' instead!]),,[
|
|
||||||
enable_kernel_logging=yes])
|
|
||||||
|
|
||||||
AC_ARG_ENABLE(logrotate,
|
AC_ARG_ENABLE(logrotate,
|
||||||
AS_HELP_STRING([--disable-logrotate], [Disable built-in rotation of /var/log/wtmp]),,[
|
AS_HELP_STRING([--disable-logrotate], [Disable built-in rotation of /var/log/wtmp, default enabled]),,[
|
||||||
enable_logrotate=yes])
|
enable_logrotate=yes])
|
||||||
|
|
||||||
AC_ARG_ENABLE(dbus,
|
|
||||||
AS_HELP_STRING([--disable-dbus], [Disable D-Bus support (libink + Finit object tree)]),,[
|
|
||||||
enable_dbus=yes])
|
|
||||||
|
|
||||||
AC_ARG_ENABLE(doc,
|
AC_ARG_ENABLE(doc,
|
||||||
AS_HELP_STRING([--disable-doc], [Disable build and install of doc/ section]),,[
|
AS_HELP_STRING([--disable-doc], [Disable build and install of doc/ section]),,[
|
||||||
enable_doc=yes])
|
enable_doc=yes])
|
||||||
@@ -109,38 +81,21 @@ AC_ARG_ENABLE(contrib,
|
|||||||
AS_HELP_STRING([--disable-contrib], [Disable build and install of contrib section]),,[
|
AS_HELP_STRING([--disable-contrib], [Disable build and install of contrib section]),,[
|
||||||
enable_contrib=yes])
|
enable_contrib=yes])
|
||||||
|
|
||||||
AC_ARG_ENABLE([rescue],
|
|
||||||
AS_HELP_STRING([--disable-rescue], [Disable potentially unsafe rescue mode]),,
|
|
||||||
[enable_rescue=yes])
|
|
||||||
|
|
||||||
# Check for extra plugins to enable
|
# Check for extra plugins to enable
|
||||||
AC_ARG_ENABLE(all_plugins,
|
enable_all_plugins=auto
|
||||||
AS_HELP_STRING([--enable-all-plugins], [Enable all plugins, default: auto]),
|
|
||||||
enable_all_plugins=$enableval, enable_all_plugins=auto)
|
|
||||||
AC_PLUGIN([alsa-utils], [no], [Save and restore ALSA sound settings using alsactl])
|
AC_PLUGIN([alsa-utils], [no], [Save and restore ALSA sound settings using alsactl])
|
||||||
AC_PLUGIN([dbus], [yes], [Setup and start system message bus, D-Bus])
|
AC_PLUGIN([dbus], [no], [Setup and start system message bus, D-Bus])
|
||||||
AC_PLUGIN([modules-load], [no], [Scans /etc/modules-load.d for modules to load])
|
AC_PLUGIN([modules-load], [no], [Scans /etc/modules-load.d for modules to load])
|
||||||
AC_PLUGIN([modprobe], [no], [Coldplug modules using modalias magic])
|
AC_PLUGIN([modprobe], [yes], [Coldplug modules using modalias magic])
|
||||||
AC_PLUGIN([resolvconf], [no], [Setup necessary files for resolvconf])
|
AC_PLUGIN([resolvconf], [no], [Setup necessary files for resolvconf])
|
||||||
AC_PLUGIN([x11-common], [no], [Console setup (for X)])
|
AC_PLUGIN([x11-common], [no], [Console setup (for X)])
|
||||||
AC_PLUGIN([netlink], [yes], [Basic netlink plugin for IFUP/IFDN and GW events. Can be replaced with externally built plugin that links with libnl or similar.])
|
AC_PLUGIN([netlink], [yes], [Basic netlink plugin for IFUP/IFDN and GW events. Can be replaced with externally built plugin that links with libnl or similar.])
|
||||||
AC_PLUGIN([hook-scripts], [no], [Trigger script execution from hook points])
|
AC_PLUGIN([hotplug], [yes], [Setup and start udev or mdev hotplug daemon])
|
||||||
AC_PLUGIN([hotplug], [no], [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])
|
|
||||||
|
|
||||||
# Check for extra arguments or packages
|
# Check for extra arguments or packages
|
||||||
AC_ARG_WITH([bash-completion-dir],
|
|
||||||
AS_HELP_STRING([--with-bash-completion-dir[=PATH]], [Directory to install Bash completion, default: auto]),
|
|
||||||
[bash_dir=$withval], [bash_dir=yes])
|
|
||||||
|
|
||||||
AC_ARG_WITH(fstab,
|
|
||||||
AS_HELP_STRING([--with-fstab=FILE], [System default fstab, default $sysconfdir/fstab]),
|
|
||||||
[fstab=$withval], [fstab=yes])
|
|
||||||
|
|
||||||
AC_ARG_WITH(heading,
|
AC_ARG_WITH(heading,
|
||||||
AS_HELP_STRING([--with-heading=GREET], [Heading for boot progress. Default: PRETTY_NAME from /etc/os-release, fallback to "Finit vX.YY"]),
|
AS_HELP_STRING([--with-heading=GREET], [Heading for boot progress. Default: PRETTY_NAME from /etc/os-release, fallback to "Finit vX.YY"]),
|
||||||
[heading=$withval], [heading=yes])
|
[heading=$withval], [heading=yes])
|
||||||
@@ -162,7 +117,7 @@ AC_ARG_WITH(sysconfig,
|
|||||||
[sysconfig=$withval], [sysconfig=default])
|
[sysconfig=$withval], [sysconfig=default])
|
||||||
|
|
||||||
AC_ARG_WITH(group,
|
AC_ARG_WITH(group,
|
||||||
AS_HELP_STRING([--with-group=NAME], [Group for /run/finit/socket and /run/finit/bus, default: root]),
|
AS_HELP_STRING([--with-group=NAME], [Group for /run/finit/socket (initctl), default: root]),
|
||||||
[group=$withval], [group=root])
|
[group=$withval], [group=root])
|
||||||
|
|
||||||
AC_ARG_WITH(hostname,
|
AC_ARG_WITH(hostname,
|
||||||
@@ -170,7 +125,7 @@ AC_ARG_WITH(hostname,
|
|||||||
[hostname=$withval], [hostname=yes])
|
[hostname=$withval], [hostname=yes])
|
||||||
|
|
||||||
AC_ARG_WITH(runlevel,
|
AC_ARG_WITH(runlevel,
|
||||||
AS_HELP_STRING([--with-runlevel=N], [Runlevel to switch to after bootstrap [1-9], default: 2]),
|
AS_HELP_STRING([--with-runlevel=N], [Runlevel to switch to after bootstrap, default: 2]),
|
||||||
[runlevel=$withval], [runlevel=yes])
|
[runlevel=$withval], [runlevel=yes])
|
||||||
|
|
||||||
AC_ARG_WITH(random-seed,
|
AC_ARG_WITH(random-seed,
|
||||||
@@ -178,37 +133,11 @@ AC_ARG_WITH(random-seed,
|
|||||||
[random_seed=$withval], [random_seed=yes])
|
[random_seed=$withval], [random_seed=yes])
|
||||||
|
|
||||||
AC_ARG_WITH(keventd,
|
AC_ARG_WITH(keventd,
|
||||||
AS_HELP_STRING([--with-keventd], [Enable built-in keventd device manager, default: yes]),, [with_keventd=yes])
|
AS_HELP_STRING([--with-keventd], [Enable built-in keventd, default: no]),, [with_keventd=no])
|
||||||
|
|
||||||
AC_ARG_WITH(udev-rules,
|
|
||||||
AS_HELP_STRING([--without-udev-rules], [Skip install of curated udev rules under /lib/udev/rules.d, default: yes when keventd enabled]),, [with_udev_rules=yes])
|
|
||||||
|
|
||||||
AC_ARG_WITH(sulogin,
|
|
||||||
AS_HELP_STRING([--with-sulogin@<:@=USER@:>@], [Built-in sulogin, optional USER to request password for, default: yes (root)]),[sulogin=$withval],[with_sulogin=yes sulogin=yes])
|
|
||||||
|
|
||||||
AC_ARG_WITH(watchdog,
|
AC_ARG_WITH(watchdog,
|
||||||
AS_HELP_STRING([--with-watchdog@<:@=DEV@:>@], [Built-in watchdog, default: yes (/dev/watchdog)]),
|
AS_HELP_STRING([--with-watchdog=[DEV]], [Enable built-in watchdog, default: /dev/watchdog]),
|
||||||
[watchdog=$withval], [with_watchdog=yes watchdog=yes])
|
[watchdog=$withval], [with_watchdog=no watchdog=])
|
||||||
|
|
||||||
AC_ARG_WITH(libsystemd,
|
|
||||||
AS_HELP_STRING([--with-libsystemd], [Build replacement libsystemd library, default: no]),
|
|
||||||
[with_libsystemd=$withval], [with_libsystemd=no])
|
|
||||||
|
|
||||||
AC_ARG_WITH(hook-scripts-path,
|
|
||||||
AS_HELP_STRING([--with-hook-scripts-path=DIR], [Base directory for hook scripts, default $libexecdir/finit/hook]),
|
|
||||||
[hook_scripts_path=$withval], [hook_scripts_path=yes])
|
|
||||||
|
|
||||||
AC_ARG_WITH(plugin-path,
|
|
||||||
AS_HELP_STRING([--with-plugin-path=DIR], [Search path for external plugins, default /usr/lib/finit/plugins:/usr/local/lib/finit/plugins]),
|
|
||||||
[plugin_path=$withval], [plugin_path=yes])
|
|
||||||
|
|
||||||
AC_ARG_WITH(rtc-date,
|
|
||||||
AS_HELP_STRING([--with-rtc-date=DATE], [If RTC date/time is too old, restore to DATE, format "YYYY-MM-DD HH:MM:SS", default "2000-01-01 00:00:00"]),
|
|
||||||
[rtc_date=$withval], [rtc_date=no])
|
|
||||||
|
|
||||||
AC_ARG_WITH(rtc-file,
|
|
||||||
AS_HELP_STRING([--with-rtc-file=FILE], [If RTC is missing, save and restore system clock from this file, default: no]),
|
|
||||||
[rtc_file=$withval], [rtc_file=no])
|
|
||||||
|
|
||||||
### Enable features ###########################################################################
|
### Enable features ###########################################################################
|
||||||
|
|
||||||
@@ -219,22 +148,6 @@ AS_IF([test "x$enable_auto_reload" = "xyes"], [
|
|||||||
AS_IF([test "x$enable_kernel_cmdline" = "xyes"], [
|
AS_IF([test "x$enable_kernel_cmdline" = "xyes"], [
|
||||||
AC_DEFINE(KERNEL_CMDLINE, 1, [Dumpster diving after init args from /proc/cmdline])])
|
AC_DEFINE(KERNEL_CMDLINE, 1, [Dumpster diving after init args from /proc/cmdline])])
|
||||||
|
|
||||||
AS_IF([test "x$enable_kernel_logging" = "xyes"], [
|
|
||||||
AC_DEFINE(KERNEL_LOGGING, 1, [Keep kernel warn/err logs to console])])
|
|
||||||
|
|
||||||
AS_IF([test "x$enable_cgroup" = "xyes"], [
|
|
||||||
AC_DEFINE(CGROUP2_ENABLED, 1, [Autodetect cgroup v2 support from /sys/fs/cgroup])])
|
|
||||||
|
|
||||||
AS_IF([test "x$enable_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])])
|
||||||
|
|
||||||
@@ -248,28 +161,9 @@ AS_IF([test "x$enable_redirect" = "xyes"], [
|
|||||||
AS_IF([test "x$enable_logrotate" != "xno"], [
|
AS_IF([test "x$enable_logrotate" != "xno"], [
|
||||||
AC_DEFINE(LOGROTATE_ENABLED, 1, [Enable built-in rotation of /var/log/wtmp et al.])])
|
AC_DEFINE(LOGROTATE_ENABLED, 1, [Enable built-in rotation of /var/log/wtmp et al.])])
|
||||||
|
|
||||||
AS_IF([test "x$enable_rescue" != "xno"], [
|
|
||||||
AC_DEFINE([RESCUE_MODE], 1, [Define to enable support for rescue mode.])])
|
|
||||||
|
|
||||||
AM_CONDITIONAL(LOGROTATE, [test "x$enable_logrotate" = "xyes"])
|
AM_CONDITIONAL(LOGROTATE, [test "x$enable_logrotate" = "xyes"])
|
||||||
|
|
||||||
AS_IF([test "x$enable_dbus" = "xyes"], [
|
|
||||||
AC_DEFINE(HAVE_DBUS, 1, [Build D-Bus support via libink])])
|
|
||||||
AM_CONDITIONAL(DBUS, [test "x$enable_dbus" = "xyes"])
|
|
||||||
|
|
||||||
### With features ##############################################################################
|
### With features ##############################################################################
|
||||||
AS_IF([test "x$bash_dir" = "xyes"], [
|
|
||||||
PKG_CHECK_MODULES([BASH_COMPLETION], [bash-completion >= 2.0],
|
|
||||||
[BASH_DIR="$(pkg-config --variable=completionsdir bash-completion)"],
|
|
||||||
[BASH_DIR="$datadir/bash-completion/completions"])], [
|
|
||||||
BASH_DIR="$bash_dir"])
|
|
||||||
|
|
||||||
AS_IF([test "x$with_fstab" != "xno"], [
|
|
||||||
AS_IF([test "x$fstab" = "xyes"], [fstab=$sysconfdir/fstab])
|
|
||||||
AC_EXPAND_DIR(fstab_path, "$fstab")
|
|
||||||
AC_DEFINE_UNQUOTED(FINIT_FSTAB, "$fstab_path", [Built-in default: /etc/fstab])],[
|
|
||||||
AC_DEFINE_UNQUOTED(FINIT_FSTAB, NULL, [No built-in default fstab])])
|
|
||||||
|
|
||||||
AS_IF([test "x$with_config" != "xno"], [
|
AS_IF([test "x$with_config" != "xno"], [
|
||||||
AS_IF([test "x$conf" = "xyes"], [
|
AS_IF([test "x$conf" = "xyes"], [
|
||||||
conf=$sysconfdir/finit.conf])])
|
conf=$sysconfdir/finit.conf])])
|
||||||
@@ -285,9 +179,10 @@ AC_DEFINE_UNQUOTED(FINIT_RCSD, "$rcsd_path", [Finit rcS.d/, default /etc/finit.d
|
|||||||
AC_SUBST(FINIT_RCSD, "$rcsd_path")
|
AC_SUBST(FINIT_RCSD, "$rcsd_path")
|
||||||
|
|
||||||
AS_IF([test "x$with_rc_local" != "xno"], [
|
AS_IF([test "x$with_rc_local" != "xno"], [
|
||||||
AS_IF([test "x$rclocal" = "xyes"], [rclocal=$sysconfdir/rc.local])
|
AS_IF([test "x$rclocal" = "xyes"], [
|
||||||
AC_EXPAND_DIR(rclocal_path, "$rclocal")
|
rclocal=$sysconfdir/rc.local])])
|
||||||
AC_DEFINE_UNQUOTED(FINIT_RC_LOCAL, "$rclocal_path", [Compat SysV /etc/rc.local file to run last at boot.])])
|
AC_EXPAND_DIR(rclocal_path, "$rclocal")
|
||||||
|
AC_DEFINE_UNQUOTED(FINIT_RC_LOCAL, "$rclocal_path", [Compat SysV /etc/rc.local file to run last at boot.])
|
||||||
|
|
||||||
AS_IF([test "x$with_sysconfig" != "xno"], [
|
AS_IF([test "x$with_sysconfig" != "xno"], [
|
||||||
AS_IF([test "x$sysconfig" != "xdefault"], [
|
AS_IF([test "x$sysconfig" != "xdefault"], [
|
||||||
@@ -302,7 +197,7 @@ AS_IF([test "x$with_heading" != "xno"], [
|
|||||||
AS_IF([test "x$with_group" != "xno"], [
|
AS_IF([test "x$with_group" != "xno"], [
|
||||||
AS_IF([test "x$group" = "xyes"], [
|
AS_IF([test "x$group" = "xyes"], [
|
||||||
group=root])])
|
group=root])])
|
||||||
AC_DEFINE_UNQUOTED(DEFGROUP, "$group", [For /run/finit/socket and /run/finit/bus])
|
AC_DEFINE_UNQUOTED(DEFGROUP, "$group", [For /run/finit/socket])
|
||||||
|
|
||||||
AS_IF([test "x$with_hostname" != "xno"], [
|
AS_IF([test "x$with_hostname" != "xno"], [
|
||||||
AS_IF([test "x$hostname" = "xyes"], [
|
AS_IF([test "x$hostname" = "xyes"], [
|
||||||
@@ -321,29 +216,7 @@ AS_IF([test "x$with_random_seed" != "xno"], [
|
|||||||
AC_EXPAND_DIR(random_path, "$random_seed")
|
AC_EXPAND_DIR(random_path, "$random_seed")
|
||||||
AC_DEFINE_UNQUOTED(RANDOMSEED, "$random_path", [Improve random at boot by seeding it with sth from before.])])
|
AC_DEFINE_UNQUOTED(RANDOMSEED, "$random_path", [Improve random at boot by seeding it with sth from before.])])
|
||||||
|
|
||||||
AS_IF([test "x$rtc_date" != "xno"], [
|
AS_IF([test "x$with_keventd" != "xno"], [with_keventd=yes])
|
||||||
AC_DEFINE_UNQUOTED(RTC_TIMESTAMP_CUSTOM, "$rtc_date", [Custom RTC restore date, default: 2000-01-01 00:00])], [
|
|
||||||
rtc_date=""])
|
|
||||||
|
|
||||||
AS_IF([test "x$rtc_file" != "xno"], [
|
|
||||||
AS_IF([test "x$rtc_file" = "xyes"], [
|
|
||||||
rtc_file=/var/lib/misc/rtc])
|
|
||||||
AC_EXPAND_DIR(rtcfile_path, "$rtc_file")
|
|
||||||
AC_DEFINE_UNQUOTED(RTC_FILE, "$rtcfile_path", [Save and restore system time from this file if /dev/rtc is missing.])],[
|
|
||||||
AC_DEFINE_UNQUOTED(RTC_FILE, NULL)])
|
|
||||||
|
|
||||||
AS_IF([test "x$with_keventd" != "xno"], [
|
|
||||||
with_keventd=yes
|
|
||||||
PKG_CHECK_MODULES([blkid], [blkid],, [
|
|
||||||
AC_MSG_ERROR([libblkid (util-linux) is required to build keventd.
|
|
||||||
Install the dev package (e.g. libblkid-dev) or disable keventd with --without-keventd])])])
|
|
||||||
|
|
||||||
AS_IF([test "x$with_sulogin" != "xno"], [
|
|
||||||
AS_IF([test "x$sulogin" = "xyes"], [
|
|
||||||
sulogin=root])
|
|
||||||
with_sulogin=yes
|
|
||||||
AC_DEFINE_UNQUOTED(SULOGIN_USER, "$sulogin", [Built-in sulogin user, default: root])], [
|
|
||||||
sulogin=])
|
|
||||||
|
|
||||||
AS_IF([test "x$with_watchdog" != "xno"], [
|
AS_IF([test "x$with_watchdog" != "xno"], [
|
||||||
AS_IF([test "x$watchdog" = "xyes"], [
|
AS_IF([test "x$watchdog" = "xyes"], [
|
||||||
@@ -352,75 +225,31 @@ 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$hook_scripts_path" = "xyes"], [hook_scripts_path=$libexecdir/finit/hook])
|
|
||||||
AC_EXPAND_DIR(hook_scripts_path, "$hook_scripts_path")
|
|
||||||
AC_DEFINE_UNQUOTED(PLUGIN_HOOK_SCRIPTS_PATH, "$hook_scripts_path", [Built-in default: $libexecdir/finit])])
|
|
||||||
|
|
||||||
AS_IF([test "x$with_plugin_path" != "xno"], [
|
|
||||||
AS_IF([test "x$plugin_path" = "xyes"], [plugin_path=/usr/lib/finit/plugins:/usr/local/lib/finit/plugins])
|
|
||||||
AC_EXPAND_DIR(plugin_path, "$plugin_path")
|
|
||||||
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(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(WATCHDOGD, [test "x$with_watchdog" != "xno"])
|
||||||
AM_CONDITIONAL(UDEV_RULES, [test "x$with_keventd" != "xno" -a "x$with_udev_rules" != "xno"])
|
AM_CONDITIONAL(DOC, [test "x$enable_doc" = "xyes"])
|
||||||
AM_CONDITIONAL(SULOGIN, [test "x$with_sulogin" != "xno"])
|
AM_CONDITIONAL(CONTRIB, [test "x$enable_contrib" = "xyes"])
|
||||||
AM_CONDITIONAL(WATCHDOGD, [test "x$with_watchdog" != "xno"])
|
|
||||||
AM_CONDITIONAL(LIBSYSTEMD, [test "x$with_libsystemd" != "xno"])
|
|
||||||
AM_CONDITIONAL(DOC, [test "x$enable_doc" = "xyes"])
|
|
||||||
AM_CONDITIONAL(CONTRIB, [test "x$enable_contrib" = "xyes"])
|
|
||||||
AM_CONDITIONAL(TESTSERV, [test "x$enable_testserv_plugin" = "xyes"])
|
|
||||||
|
|
||||||
# Workaround for as-of-yet unreleased runstatedir support, planned for
|
|
||||||
# autoconf 2.70, which some major distros have backported.
|
|
||||||
AS_IF([test -z "$runstatedir"], runstatedir="$localstatedir/run")
|
|
||||||
AC_SUBST(runstatedir)
|
|
||||||
|
|
||||||
# Override default libdir, used for plugins and rescue.conf
|
# Override default libdir, used for plugins and rescue.conf
|
||||||
pkglibdir=$libdir/finit
|
pkglibdir=$libdir/finit
|
||||||
AC_SUBST(pkglibexecdir)
|
AC_SUBST(pkglibexecdir)
|
||||||
AC_EXPAND_DIR(pkglibexecdir, "$libexecdir/finit")
|
AC_EXPAND_DIR(pkglibexecdir, "$libexecdir/finit")
|
||||||
AC_DEFINE_UNQUOTED(FINIT_EXECPATH_, "$pkglibexecdir", [Finit libexec path])
|
AC_DEFINE_UNQUOTED(FINIT_LIBPATH_, "$pkglibexecdir", [Finit libexec path])
|
||||||
AC_EXPAND_DIR(finit_runpath, "$runstatedir/finit/system")
|
|
||||||
AC_DEFINE_UNQUOTED(FINIT_RUNPATH_, "$finit_runpath", [Finit runtime dynamic system services])
|
|
||||||
|
|
||||||
AC_EXPAND_DIR(plugin_path, "$pkglibdir/plugins")
|
AC_EXPAND_DIR(plugin_path, "$libdir/finit/plugins")
|
||||||
AC_SUBST(plugin_path)
|
AC_SUBST(plugin_path)
|
||||||
AC_DEFINE_UNQUOTED(PLUGIN_PATH, "$plugin_path", [Finit plugin path])
|
AC_DEFINE_UNQUOTED(PLUGIN_PATH, "$plugin_path", [Finit plugin path])
|
||||||
|
|
||||||
AC_EXPAND_DIR(tmpfiles_path, "$libdir/tmpfiles.d")
|
AC_EXPAND_DIR(rescue_conf, "$libdir/finit/rescue.conf")
|
||||||
AC_SUBST(tmpfiles_path)
|
|
||||||
AC_DEFINE_UNQUOTED(TMPFILES_PATH_, "$tmpfiles_path", [Main tmpfiles.d/, override in /etc])
|
|
||||||
|
|
||||||
AC_EXPAND_DIR(finit_tmpfiles, "$pkglibdir/tmpfiles.d")
|
|
||||||
AC_SUBST(finit_tmpfiles)
|
|
||||||
AC_DEFINE_UNQUOTED(FINIT_TMPFILES, "$finit_tmpfiles", [Finit tmpfiles.d/ .conf path])
|
|
||||||
|
|
||||||
AC_EXPAND_DIR(system_path, "$pkglibdir/system")
|
|
||||||
AC_SUBST(system_path)
|
|
||||||
AC_DEFINE_UNQUOTED(FINIT_SYSPATH_, "$system_path", [Static services, previously generated at runtime by plugins])
|
|
||||||
|
|
||||||
AC_EXPAND_DIR(rescue_conf, "$pkglibdir/rescue.conf")
|
|
||||||
AC_DEFINE_UNQUOTED(RESCUE_CONF, "$rescue_conf", [Finit rescue mode .conf])
|
AC_DEFINE_UNQUOTED(RESCUE_CONF, "$rescue_conf", [Finit rescue mode .conf])
|
||||||
AC_EXPAND_DIR(sample_conf, "$pkglibdir/sample.conf")
|
AC_EXPAND_DIR(sample_conf, "$libdir/finit/sample.conf")
|
||||||
AC_DEFINE_UNQUOTED(SAMPLE_CONF, "$sample_conf", [Finit sameple.conf for initctl create])
|
AC_DEFINE_UNQUOTED(SAMPLE_CONF, "$sample_conf", [Finit sameple.conf for initctl create])
|
||||||
|
|
||||||
AC_EXPAND_DIR(bash_completion_dir, "$BASH_DIR")
|
|
||||||
AC_SUBST(BASH_DIR, "$bash_completion_dir")
|
|
||||||
|
|
||||||
AS_IF([test "$heading" = ""], [heading="<DEFAULT>"])
|
AS_IF([test "$heading" = ""], [heading="<DEFAULT>"])
|
||||||
AS_IF([test "$heading" = "no"], [heading="<NONE>"])
|
AS_IF([test "$heading" = "no"], [heading="<NONE>"])
|
||||||
|
|
||||||
RTC_DATE=$rtc_date
|
|
||||||
AS_IF([test "$rtc_date" = ""], [RTC_DATE="<DEFAULT>"])
|
|
||||||
AS_IF([test "$rtc_date" = "no"], [RTC_DATE="<DEFAULT>"])
|
|
||||||
|
|
||||||
# Generate all files
|
# Generate all files
|
||||||
AC_OUTPUT
|
AC_OUTPUT
|
||||||
|
|
||||||
@@ -428,16 +257,14 @@ cat <<EOF
|
|||||||
|
|
||||||
------------------ Summary ------------------
|
------------------ Summary ------------------
|
||||||
$PACKAGE_NAME version $PACKAGE_VERSION
|
$PACKAGE_NAME version $PACKAGE_VERSION
|
||||||
Prefix................: $(eval echo $prefix)
|
Prefix................: $prefix
|
||||||
Exec prefix...........: $(eval echo $exec_prefix)
|
Exec prefix...........: $eprefix
|
||||||
Libdir................: $(eval echo $libdir)
|
|
||||||
Sysconfdir............: `eval echo $sysconfdir`
|
Sysconfdir............: `eval echo $sysconfdir`
|
||||||
Localstatedir.........: `eval echo $localstatedir`
|
Localstatedir.........: `eval echo $localstatedir`
|
||||||
Default fstab.........: `eval echo $fstab`
|
|
||||||
Finit config file.....: $conf_path
|
Finit config file.....: $conf_path
|
||||||
Finit config.d path...: $rcsd_path
|
Finit config.d path...: $rcsd_path
|
||||||
Finit plugin path.....: $plugin_path
|
Finit plugin path.....: $plugin_path
|
||||||
Compat rc.local path..: `eval echo $rclocal`
|
Compat rc.local path..: $rclocal_path
|
||||||
System environment....: ${sysconfig_path:-${sysconfig}}
|
System environment....: ${sysconfig_path:-${sysconfig}}
|
||||||
Random seed path......: $random_path
|
Random seed path......: $random_path
|
||||||
C Compiler............: $CC $CFLAGS $CPPFLAGS $LDFLAGS $LIBS
|
C Compiler............: $CC $CFLAGS $CPPFLAGS $LDFLAGS $LIBS
|
||||||
@@ -446,27 +273,16 @@ cat <<EOF
|
|||||||
Behavior:
|
Behavior:
|
||||||
Boot heading..........: $heading
|
Boot heading..........: $heading
|
||||||
Plugins...............: $plugins
|
Plugins...............: $plugins
|
||||||
RTC restore date......: $RTC_DATE
|
|
||||||
RTC fallback file.....: $rtc_file
|
|
||||||
|
|
||||||
Optional features:
|
Optional features:
|
||||||
Install doc/..........: $enable_doc
|
Install doc/..........: $enable_doc
|
||||||
Install contrib/......: $enable_contrib
|
Install contrib/......: $enable_contrib
|
||||||
Bash completion.......: $bash_completion_dir
|
Built-in keventd......: $with_keventd
|
||||||
Built-in keventd......: $with_keventd (blkid: $blkid_LIBS)
|
|
||||||
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
|
||||||
D-Bus support (libink): $enable_dbus
|
|
||||||
Replacement libsystemd: $with_libsystemd
|
|
||||||
Use cgroup v2.........: $enable_cgroup
|
|
||||||
Use libcap............: $enable_libcap
|
|
||||||
Parse kernel cmdline..: $enable_kernel_cmdline
|
|
||||||
Keep kernel logging...: $enable_kernel_logging
|
|
||||||
Skip fsck check.......: $enable_fastboot
|
Skip fsck check.......: $enable_fastboot
|
||||||
Run fsck fix mode.....: $enable_fsckfix
|
Run fsck fix mode.....: $enable_fsckfix
|
||||||
Redirect output.......: $enable_redirect
|
Redirect output.......: $enable_redirect
|
||||||
Rescue mode...........: $enable_rescue
|
|
||||||
Default hostname......: $hostname
|
Default hostname......: $hostname
|
||||||
Default group.........: $group
|
Default group.........: $group
|
||||||
Default runlevel......: $runlevel
|
Default runlevel......: $runlevel
|
||||||
|
|||||||
@@ -3,8 +3,3 @@ 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,7 +6,6 @@ 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,8 +1,5 @@
|
|||||||
HowTo: Finit on Alpine Linux 3.4...3.19
|
HowTo: Finit on Alpine Linux 3.4-3.6
|
||||||
=======================================
|
====================================
|
||||||
|
|
||||||
> [!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,
|
||||||
|
|||||||
@@ -17,8 +17,8 @@ PKG_CONFIG_LIBDIR=/usr/lib/pkgconfig:/usr/local/lib/pkgconfig ./configure \
|
|||||||
--prefix=/usr --exec-prefix= \
|
--prefix=/usr --exec-prefix= \
|
||||||
--sysconfdir=/etc --localstatedir=/var \
|
--sysconfdir=/etc --localstatedir=/var \
|
||||||
--enable-dbus-plugin --enable-x11-common-plugin \
|
--enable-dbus-plugin --enable-x11-common-plugin \
|
||||||
--enable-alsa-utils-plugin --without-watchdog \
|
--enable-alsa-utils-plugin --with-watchdog \
|
||||||
--with-keventd --with-sulogin
|
--with-keventd
|
||||||
|
|
||||||
echo
|
echo
|
||||||
echo "*** Building ..."
|
echo "*** Building ..."
|
||||||
@@ -35,3 +35,4 @@ fi
|
|||||||
echo
|
echo
|
||||||
echo "*** Done"
|
echo "*** Done"
|
||||||
echo
|
echo
|
||||||
|
|
||||||
|
|||||||
@@ -3,34 +3,24 @@
|
|||||||
|
|
||||||
## Runlevel to start after bootstrap, runlevel 'S'
|
## Runlevel to start after bootstrap, runlevel 'S'
|
||||||
# Default is 2
|
# Default is 2
|
||||||
#runlevel = 2
|
#runlevel 2
|
||||||
|
|
||||||
# Top-level cgroups and their default settings. All groups mandatory
|
# Top-level cgroups and their default settings. All groups mandatory
|
||||||
# but more can be added, max 8 groups in total currently. The cgroup
|
# but more can be added, max 8 groups in total currently. The cgroup
|
||||||
# 'root' is also available, reserved for RT processes. Settings are
|
# 'root' is also available, reserved for RT processes. Settings are
|
||||||
# as-is, only one shorthand 'mem.' exists, other than that it's the
|
# as-is, only one shorthand 'mem.' exists, other than that it's the
|
||||||
# cgroup v2 controller default names.
|
# cgroup v2 controller default names.
|
||||||
#cgroup init { cpu.weight = 100 }
|
#cgroup init cpu.weight:100
|
||||||
#cgroup user { cpu.weight = 100 }
|
#cgroup user cpu.weight:100
|
||||||
#cgroup system { cpu.weight = 9700 }
|
#cgroup system cpu.weight:9700
|
||||||
|
|
||||||
# Task to run if ctrl-alt-del is pressed. This condition is asserted by
|
# Task to run if ctrl-alt-del is pressed. This condition is asserted by
|
||||||
# Finit upon receiving SIGINT (from the kernel).
|
# Finit upon receiving SIGINT (from the kernel).
|
||||||
#task reboot {
|
#task <sys/key/ctrlaltdel> [12345789] initctl reboot -- Rebooting system
|
||||||
# description = "Rebooting system"
|
|
||||||
# runlevel = "12345789"
|
|
||||||
# conditions = { "sys/key/ctrlaltdel" }
|
|
||||||
# command = "initctl reboot"
|
|
||||||
#}
|
|
||||||
|
|
||||||
# Task to run if the kernel gets a power fail condition is pressed.
|
# Task to run if the kernel gets a power fail condition is pressed.
|
||||||
# Asserted by Finit upon receiving SIGPWR (from the kernel).
|
# Asserted by Finit upon receiving SIGPWR (from the kernel).
|
||||||
#task poweroff {
|
#task <sys/pwr/fail> [12345789] initctl poweroff -- Shutting down system
|
||||||
# description = "Shutting down system"
|
|
||||||
# runlevel = "12345789"
|
|
||||||
# conditions = { "sys/pwr/fail" }
|
|
||||||
# command = "initctl poweroff"
|
|
||||||
#}
|
|
||||||
|
|
||||||
## Bootstrap services and tasks
|
## Bootstrap services and tasks
|
||||||
# Can be listed here or in /etc/finit.d/*.conf
|
# Can be listed here or in /etc/finit.d/*.conf
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
SUBDIRS = available
|
SUBDIRS = available
|
||||||
docsdir := @docdir@/contrib/alpine/finit.d
|
docsdir := @docdir@/contrib/alpine/finit.d
|
||||||
d_LINKS = acpid.conf crond.conf dropbear.conf getty.conf \
|
d_LINKS = acpid.conf crond.conf dropbear.conf getty.conf \
|
||||||
keymap.conf modules.conf ntpd.conf syslogd.conf
|
keymap.conf modules.conf ntpd.conf \
|
||||||
|
klogd.conf syslogd.conf
|
||||||
|
|
||||||
install-exec-hook:
|
install-exec-hook:
|
||||||
@$(MKDIR_P) $(DESTDIR)$(docsdir)/available
|
@$(MKDIR_P) $(DESTDIR)$(docsdir)/available
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
docsdir := @docdir@/contrib/alpine/finit.d/available
|
docsdir := @docdir@/contrib/alpine/finit.d/available
|
||||||
docs_DATA = acpid.conf crond.conf dropbear.conf getty.conf keymap.conf \
|
docs_DATA = acpid.conf crond.conf dropbear.conf getty.conf keymap.conf \
|
||||||
lxdm.conf modules.conf ntpd.conf syslogd.conf watchdog.conf
|
lxdm.conf modules.conf ntpd.conf syslog.conf watchdog.conf
|
||||||
EXTRA_DIST = $(docs_DATA)
|
EXTRA_DIST = $(docs_DATA)
|
||||||
|
|||||||
@@ -1,9 +1,3 @@
|
|||||||
# Handle PWR button to shutdown/reboot -- useful in Qemu (virt-manager)
|
# Handle PWR button to shutdown/reboot -- useful in Qemu (virt-manager)
|
||||||
# Depends on syslogd having started. Redirect any output to log.
|
# Depends on syslogd having started. Redirect any output to log.
|
||||||
service acpid {
|
service [2345] <pid/syslogd> log acpid -f -- ACPI daemon
|
||||||
description = "ACPI daemon"
|
|
||||||
runlevel = "2345"
|
|
||||||
conditions = { "pid/syslogd" }
|
|
||||||
log { }
|
|
||||||
command = "acpid -f"
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,7 +1 @@
|
|||||||
service crond {
|
service [2345] <pid/syslogd> env:-/etc/conf.d/crond crond -f -S $CRON_OPTS -- Cron daemon
|
||||||
description = "Cron daemon"
|
|
||||||
runlevel = "2345"
|
|
||||||
conditions = { "pid/syslogd" }
|
|
||||||
envfile = "-/etc/conf.d/crond"
|
|
||||||
command = "crond -f -S $CRON_OPTS"
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,7 +1,2 @@
|
|||||||
# Start SSH daemon as soon as basic networking comes up
|
# Start SSH daemon as soon as basic networking comes up
|
||||||
service dropbear {
|
service [2345] env:-/etc/conf.d/dropbear dropbear -R -F $DROPBEAR_OPTS -- Dropbear SSH daemon
|
||||||
description = "Dropbear SSH daemon"
|
|
||||||
runlevel = "2345"
|
|
||||||
envfile = "-/etc/conf.d/dropbear"
|
|
||||||
command = "dropbear -R -F $DROPBEAR_OPTS"
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,24 +1,5 @@
|
|||||||
# Consoles to start getty on when system is up
|
# Consoles to start getty on when system is up
|
||||||
tty ttyS0 {
|
tty [12345] /dev/ttyS0 noclear
|
||||||
runlevel = "12345"
|
tty [12345] /dev/tty1 noclear nowait
|
||||||
device = "/dev/ttyS0"
|
tty [2345] /dev/tty2 noclear nowait
|
||||||
noclear = true
|
tty [2345] /dev/tty3 noclear nowait
|
||||||
}
|
|
||||||
tty tty1 {
|
|
||||||
runlevel = "12345"
|
|
||||||
device = "/dev/tty1"
|
|
||||||
noclear = true
|
|
||||||
nowait = true
|
|
||||||
}
|
|
||||||
tty tty2 {
|
|
||||||
runlevel = "2345"
|
|
||||||
device = "/dev/tty2"
|
|
||||||
noclear = true
|
|
||||||
nowait = true
|
|
||||||
}
|
|
||||||
tty tty3 {
|
|
||||||
runlevel = "2345"
|
|
||||||
device = "/dev/tty3"
|
|
||||||
noclear = true
|
|
||||||
nowait = true
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,7 +1,2 @@
|
|||||||
# Oneshot task to run once at bootstrap
|
# Oneshot task to run once at bootstrap
|
||||||
task keymap {
|
task [S] env:/etc/conf.d/loadkmap zcat $KEYMAP | loadkmap -- Loading keymap
|
||||||
description = "Loading keymap"
|
|
||||||
runlevel = "S"
|
|
||||||
envfile = "/etc/conf.d/loadkmap"
|
|
||||||
command = "zcat $KEYMAP | loadkmap"
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,5 +1 @@
|
|||||||
service lxdm {
|
service [2345] lxdm -- Lightweight Login Manager
|
||||||
description = "Lightweight Login Manager"
|
|
||||||
runlevel = "2345"
|
|
||||||
command = "lxdm"
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,2 +1,7 @@
|
|||||||
## Linux kernel modules to load
|
## Linux kernel modules to load
|
||||||
#modules = { "fbcon", "button", "evdev", "mousedev", "8139cp", "softdog" }
|
#module fbcon
|
||||||
|
#module button
|
||||||
|
#module evdev
|
||||||
|
#module mousedev
|
||||||
|
#module 8139cp
|
||||||
|
module softdog
|
||||||
|
|||||||
@@ -1,9 +1,2 @@
|
|||||||
# Busybox ntpd has no option to use syslog when running in foreground
|
# Busybox ntpd has no option to use syslog when running in foreground
|
||||||
service ntpd {
|
service [2345] <pid/syslogd> env:-/etc/conf.d/ntpd log ntpd -n $NTPD_OPTS -- NTP daemon
|
||||||
description = "NTP daemon"
|
|
||||||
runlevel = "2345"
|
|
||||||
conditions = { "pid/syslogd" }
|
|
||||||
envfile = "-/etc/conf.d/ntpd"
|
|
||||||
log { }
|
|
||||||
command = "ntpd -n $NTPD_OPTS"
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
# Start syslogd as soon as possible, should always run
|
||||||
|
# Start klogd as soon as possible, but after syslogd
|
||||||
|
service [S12345] env:-/etc/conf.d/syslog syslogd -n $SYSLOGD_OPTS -- Syslog daemon
|
||||||
|
service [S12345] <pid/syslogd> env:-/etc/conf.d/klogd klogd -n $KLOGD_OPTS -- Kernel log daemon
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
# Start syslogd as soon as possible, should always run
|
|
||||||
# Start klogd as soon as possible, but after syslogd
|
|
||||||
service syslogd {
|
|
||||||
description = "Syslog daemon"
|
|
||||||
runlevel = "S12345"
|
|
||||||
envfile = "-/etc/conf.d/syslog"
|
|
||||||
command = "syslogd -n $SYSLOGD_OPTS"
|
|
||||||
}
|
|
||||||
service klogd {
|
|
||||||
description = "Kernel log daemon"
|
|
||||||
runlevel = "S12345"
|
|
||||||
conditions = { "pid/syslogd" }
|
|
||||||
envfile = "-/etc/conf.d/klogd"
|
|
||||||
command = "klogd -n $KLOGD_OPTS"
|
|
||||||
}
|
|
||||||
@@ -1,6 +1 @@
|
|||||||
service watchdog {
|
service [S123456789] env:-/etc/conf.d/watchdog watchdog $WATCHDOG_OPTS $WATCHDOG_DEV -- System watchdog
|
||||||
description = "System watchdog"
|
|
||||||
runlevel = "S123456789"
|
|
||||||
envfile = "-/etc/conf.d/watchdog"
|
|
||||||
command = "watchdog $WATCHDOG_OPTS $WATCHDOG_DEV"
|
|
||||||
}
|
|
||||||
|
|||||||
+29
-35
@@ -1,53 +1,45 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
if [ "$(id -u)" != "0" ]; then
|
if [ "x`id -u`" != "x0" ]; then
|
||||||
printf "\n\e[1m*** This script must run as root\e[0m\n\n"
|
echo
|
||||||
|
echo "*** This script must run as root"
|
||||||
|
echo
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# shellcheck disable=SC3037,SC3045,SC2154
|
|
||||||
yorn()
|
|
||||||
{
|
|
||||||
printf "\e[1m> %s (y/N)?\e[0m " "$*"
|
|
||||||
read -rn1 yorn
|
|
||||||
echo
|
|
||||||
|
|
||||||
if [ "$yorn" = "y" ] || [ "$yorn" = "Y" ]; then
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
|
|
||||||
# Adjust base directory
|
# Adjust base directory
|
||||||
if grep -q contrib/alpine Makefile 2>/dev/null; then
|
grep -q alpine Makefile 2>/dev/null
|
||||||
|
if [ $? -eq 0 ]; then
|
||||||
cd ../..
|
cd ../..
|
||||||
fi
|
elif [ ! -e configure.ac ]; then
|
||||||
|
echo "*** Please run this script from the Finit base directory."
|
||||||
if [ ! -e configure.ac ]; then
|
|
||||||
printf "\n\e[1m*** Please run this script from the Finit base directory.\e[0m\n"
|
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
printf "\n\e[1mInstall Finit on Alpine Linux\n"
|
echo
|
||||||
printf "========================================================================\e[0m\n"
|
echo "*** Install Finit on Alpine Linux"
|
||||||
printf "/sbin/finit - PID 1\n"
|
echo "========================================================================"
|
||||||
printf "/lib/finit/plugins/* - All enabled Finit plugins\n"
|
echo "/sbin/finit - PID 1"
|
||||||
printf "/etc/finit.conf - Finit configuration file\n"
|
echo "/lib/finit/plugins/* - All enabled Finit plugins"
|
||||||
printf "/etc/finit.d/ - Finit services\n"
|
echo "/etc/finit.conf - Finit configuration file"
|
||||||
|
echo "/etc/finit.d/ - Finit services"
|
||||||
|
echo
|
||||||
|
read -p "Do you want to continue (y/N)? " yorn
|
||||||
|
|
||||||
if yorn "Do you want to continue"; then
|
if [ "x$yorn" = "xy" -o "x$yorn" = "xY" ]; then
|
||||||
printf "\n\e[1m*** Installing Finit files ...\e[0m\n"
|
echo
|
||||||
|
echo "*** Installing Finit files ..."
|
||||||
make install
|
make install
|
||||||
cd /usr/share/doc/finit/contrib/alpine || exit 1
|
cd /usr/share/doc/finit/contrib/alpine
|
||||||
for file in finit.conf rc.local; do
|
for file in finit.conf rc.local; do
|
||||||
install -vbD $file /etc/$file
|
install -vbD $file /etc/$file
|
||||||
done
|
done
|
||||||
cp -va finit.d /etc/
|
cp -va finit.d /etc/
|
||||||
|
|
||||||
if yorn "Install Finit as the system default Init"; then
|
read -p "*** Install Finit as the system default Init (y/N)? " yorn
|
||||||
printf "\e[1m*** Updating /sbin/init symlink --> finit ...\e[0m\n"
|
if [ "x$yorn" = "xy" -o "x$yorn" = "xY" ]; then
|
||||||
cd /sbin || exit 1
|
echo "*** Updating /sbin/init symlink --> finit ..."
|
||||||
|
cd /sbin
|
||||||
rm init
|
rm init
|
||||||
ln -s finit init
|
ln -s finit init
|
||||||
|
|
||||||
@@ -56,8 +48,10 @@ if yorn "Do you want to continue"; then
|
|||||||
ln -s reboot shutdown
|
ln -s reboot shutdown
|
||||||
ln -s reboot suspend
|
ln -s reboot suspend
|
||||||
fi
|
fi
|
||||||
printf "\n\e[1m*** Done\e[0m\n"
|
echo "*** Done"
|
||||||
echo
|
echo
|
||||||
else
|
else
|
||||||
printf "\n\e[1m*** Aborting install.\e[0m\n\n"
|
echo
|
||||||
|
echo "*** Aborting install."
|
||||||
|
echo
|
||||||
fi
|
fi
|
||||||
|
|||||||
@@ -20,9 +20,8 @@ tools pre-systemd work as intended.
|
|||||||
|
|
||||||
root@debian:~# apt install initscripts console-setup
|
root@debian:~# apt install initscripts console-setup
|
||||||
|
|
||||||
> [!TIP]
|
> **Note:** as of Debian 11 (Bullseye), libuev and libite are part of
|
||||||
> As of Debian 11 (Bullseye), libuev and libite are part of the main
|
> the main section of Debian. So just install the -dev packages :)
|
||||||
> 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:
|
||||||
@@ -48,8 +47,7 @@ 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]
|
> **NOTE:** X Window system, you may need to `sudo apt install elogind`
|
||||||
> 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
|
||||||
|
|||||||
@@ -59,3 +59,6 @@ else
|
|||||||
echo "*** Use 'sudo contrib/debian/install.sh' later to install Finit"
|
echo "*** Use 'sudo contrib/debian/install.sh' later to install Finit"
|
||||||
echo
|
echo
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -3,34 +3,24 @@
|
|||||||
|
|
||||||
## Runlevel to start after bootstrap, runlevel 'S'
|
## Runlevel to start after bootstrap, runlevel 'S'
|
||||||
# Default is 2
|
# Default is 2
|
||||||
#runlevel = 2
|
#runlevel 2
|
||||||
|
|
||||||
# Top-level cgroups and their default settings. All groups mandatory
|
# Top-level cgroups and their default settings. All groups mandatory
|
||||||
# but more can be added, max 8 groups in total currently. The cgroup
|
# but more can be added, max 8 groups in total currently. The cgroup
|
||||||
# 'root' is also available, reserved for RT processes. Settings are
|
# 'root' is also available, reserved for RT processes. Settings are
|
||||||
# as-is, only one shorthand 'mem.' exists, other than that it's the
|
# as-is, only one shorthand 'mem.' exists, other than that it's the
|
||||||
# cgroup v2 controller default names.
|
# cgroup v2 controller default names.
|
||||||
#cgroup init { cpu.weight = 100 }
|
#cgroup init cpu.weight:100
|
||||||
#cgroup user { cpu.weight = 100 }
|
#cgroup user cpu.weight:100
|
||||||
#cgroup system { cpu.weight = 9700 }
|
#cgroup system cpu.weight:9700
|
||||||
|
|
||||||
# Task to run if ctrl-alt-del is pressed. This condition is asserted by
|
# Task to run if ctrl-alt-del is pressed. This condition is asserted by
|
||||||
# Finit upon receiving SIGINT (from the kernel).
|
# Finit upon receiving SIGINT (from the kernel).
|
||||||
#task reboot {
|
#task <sys/key/ctrlaltdel> [12345789] initctl reboot -- Rebooting system
|
||||||
# description = "Rebooting system"
|
|
||||||
# runlevel = "12345789"
|
|
||||||
# conditions = { "sys/key/ctrlaltdel" }
|
|
||||||
# command = "initctl reboot"
|
|
||||||
#}
|
|
||||||
|
|
||||||
# Task to run if the kernel gets a power fail condition is pressed.
|
# Task to run if the kernel gets a power fail condition is pressed.
|
||||||
# Asserted by Finit upon receiving SIGPWR (from the kernel).
|
# Asserted by Finit upon receiving SIGPWR (from the kernel).
|
||||||
#task poweroff {
|
#task <sys/pwr/fail> [12345789] initctl poweroff -- Shutting down system
|
||||||
# description = "Shutting down system"
|
|
||||||
# runlevel = "12345789"
|
|
||||||
# conditions = { "sys/pwr/fail" }
|
|
||||||
# command = "initctl poweroff"
|
|
||||||
#}
|
|
||||||
|
|
||||||
## Bootstrap services and tasks
|
## Bootstrap services and tasks
|
||||||
# Can be listed here or in /etc/finit.d/*.conf
|
# Can be listed here or in /etc/finit.d/*.conf
|
||||||
|
|||||||
@@ -1,10 +1,3 @@
|
|||||||
# Handle PWR button to shutdown/reboot -- useful in Qemu (virt-manager)
|
# Handle PWR button to shutdown/reboot -- useful in Qemu (virt-manager)
|
||||||
# Depends on a syslog daemon having started. Redirect any output to log.
|
# Depends on a syslog daemon having started. Redirect any output to log.
|
||||||
service acpid {
|
service [2345] <pid/syslogd> env:-/etc/default/acpid log acpid -f $OPTIONS -- ACPI daemon
|
||||||
description = "ACPI daemon"
|
|
||||||
runlevel = "2345"
|
|
||||||
conditions = { "pid/syslogd" }
|
|
||||||
envfile = "-/etc/default/acpid"
|
|
||||||
log { }
|
|
||||||
command = "acpid -f $OPTIONS"
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,8 +1 @@
|
|||||||
task anacron {
|
task [2345] <sys/pwr/ac,pid/syslogd> halt:usr1 env:-/etc/default/anacron anacron -d -q $ANACRON_ARGS -- Anacron jobs
|
||||||
description = "Anacron jobs"
|
|
||||||
runlevel = "2345"
|
|
||||||
conditions = { "sys/pwr/ac", "pid/syslogd" }
|
|
||||||
envfile = "-/etc/default/anacron"
|
|
||||||
stop-signal = "usr1"
|
|
||||||
command = "anacron -d -q $ANACRON_ARGS"
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,6 +1,2 @@
|
|||||||
sysv apparmor {
|
sysv [S] /etc/init.d/apparmor -- AppArmor initialization
|
||||||
description = "AppArmor initialization"
|
|
||||||
runlevel = "S"
|
|
||||||
command = "/etc/init.d/apparmor"
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1 @@
|
|||||||
service avahi-daemon {
|
service [2345] env:-/etc/default/avahi-daemon avahi-daemon -s $AVAHI_DAEMON_OPTS -- Avahi mDNS/DNS-SD Stack
|
||||||
description = "Avahi mDNS/DNS-SD Stack"
|
|
||||||
runlevel = "2345"
|
|
||||||
envfile = "-/etc/default/avahi-daemon"
|
|
||||||
command = "avahi-daemon -s $AVAHI_DAEMON_OPTS"
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,9 +1,3 @@
|
|||||||
# To ignore errors like "org.freedesktop.hostname1", update the env file with
|
# To ignore errors like "org.freedesktop.hostname1", update the env file with
|
||||||
# "--noplugin=hostname", i.e. append to BLUETOOTHD_OPTS
|
# "--noplugin=hostname", i.e. append to BLUETOOTHD_OPTS
|
||||||
service bluetoothd {
|
service [2345] log:null env:-/etc/default/bluetooth /usr/libexec/bluetooth/bluetoothd -n $BLUETOOTHD_OPTS -- Bluetooth service
|
||||||
description = "Bluetooth service"
|
|
||||||
runlevel = "2345"
|
|
||||||
envfile = "-/etc/default/bluetooth"
|
|
||||||
log { file = "/dev/null" }
|
|
||||||
command = "/usr/libexec/bluetooth/bluetoothd -n $BLUETOOTHD_OPTS"
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,6 +1,2 @@
|
|||||||
# Oneshot task to run once at bootstrap
|
# Oneshot task to run once at bootstrap
|
||||||
task console-setup {
|
task [S] /lib/console-setup/console-setup.sh -- Setting up console font and keymap
|
||||||
description = "Setting up console font and keymap"
|
|
||||||
runlevel = "S"
|
|
||||||
command = "/lib/console-setup/console-setup.sh"
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,7 +1 @@
|
|||||||
service cron {
|
service [2345] <sys/pwr/ac,pid/syslogd> env:-/etc/default/cron cron -f $EXTRA_OPTS -- Background job processing daemon
|
||||||
description = "Background job processing daemon"
|
|
||||||
runlevel = "2345"
|
|
||||||
conditions = { "sys/pwr/ac", "pid/syslogd" }
|
|
||||||
envfile = "-/etc/default/cron"
|
|
||||||
command = "cron -f $EXTRA_OPTS"
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,9 +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 elogind {
|
service [2345] <pid/syslogd> /lib/elogind/elogind -- Login manager
|
||||||
description = "Login manager"
|
|
||||||
runlevel = "2345"
|
|
||||||
conditions = { "pid/syslogd" }
|
|
||||||
command = "/usr/libexec/elogind"
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,38 +1,7 @@
|
|||||||
# Consoles to start getty on when system is up
|
# Consoles to start getty on when system is up
|
||||||
tty tty1 {
|
tty [12345] /dev/tty1 linux noclear nowait
|
||||||
runlevel = "12345"
|
tty [2345] /dev/tty2 linux nowait
|
||||||
device = "/dev/tty1"
|
tty [2345] /dev/tty3 linux nowait
|
||||||
term = "linux"
|
tty [2345] /dev/tty4 linux nowait
|
||||||
noclear = true
|
tty [2345] /dev/tty5 linux nowait
|
||||||
nowait = true
|
tty [2345] /dev/tty6 linux nowait
|
||||||
}
|
|
||||||
tty tty2 {
|
|
||||||
runlevel = "2345"
|
|
||||||
device = "/dev/tty2"
|
|
||||||
term = "linux"
|
|
||||||
nowait = true
|
|
||||||
}
|
|
||||||
tty tty3 {
|
|
||||||
runlevel = "2345"
|
|
||||||
device = "/dev/tty3"
|
|
||||||
term = "linux"
|
|
||||||
nowait = true
|
|
||||||
}
|
|
||||||
tty tty4 {
|
|
||||||
runlevel = "2345"
|
|
||||||
device = "/dev/tty4"
|
|
||||||
term = "linux"
|
|
||||||
nowait = true
|
|
||||||
}
|
|
||||||
tty tty5 {
|
|
||||||
runlevel = "2345"
|
|
||||||
device = "/dev/tty5"
|
|
||||||
term = "linux"
|
|
||||||
nowait = true
|
|
||||||
}
|
|
||||||
tty tty6 {
|
|
||||||
runlevel = "2345"
|
|
||||||
device = "/dev/tty6"
|
|
||||||
term = "linux"
|
|
||||||
nowait = true
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,6 +1,2 @@
|
|||||||
# Oneshot task to run once at bootstrap
|
# Oneshot task to run once at bootstrap
|
||||||
task keyboard-setup {
|
task [S] /lib/console-setup/keyboard-setup.sh -- Setting up console keyboard layout
|
||||||
description = "Setting up console keyboard layout"
|
|
||||||
runlevel = "S"
|
|
||||||
command = "/lib/console-setup/keyboard-setup.sh"
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,5 +1 @@
|
|||||||
service lightdm {
|
service [3] lightdm -- Light Display Manager
|
||||||
description = "Light Display Manager"
|
|
||||||
runlevel = "3"
|
|
||||||
command = "lightdm"
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,2 +1,8 @@
|
|||||||
## Linux kernel modules to load
|
## Linux kernel modules to load
|
||||||
#modules = { "fbcon", "button", "evdev", "loop", "psmouse", "mousedev", "8139cp" }
|
#module fbcon
|
||||||
|
#module button
|
||||||
|
#module evdev
|
||||||
|
#module loop
|
||||||
|
#module psmouse
|
||||||
|
#module mousedev
|
||||||
|
#module 8139cp
|
||||||
|
|||||||
@@ -1,6 +1,2 @@
|
|||||||
# Need to stop plymouth, or it'll block stdin on tty1
|
# Need to stop plymouth, or it'll block stdin on tty1
|
||||||
task plymouth {
|
task [S] /usr/bin/plymouth quit -- Stopping Plymouth Boot Screen
|
||||||
description = "Stopping Plymouth Boot Screen"
|
|
||||||
runlevel = "S"
|
|
||||||
command = "/usr/bin/plymouth quit"
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,8 +1,3 @@
|
|||||||
# Start rsyslogd as soon as possible, should always run
|
# Start rsyslogd as soon as possible, should always run
|
||||||
# Provides pid/syslogd condition
|
# Provides pid/syslogd condition
|
||||||
service syslogd {
|
service [S12345] name:syslogd env:-/etc/default/rsyslog rsyslogd -n $RSYSLOGD_OPTIONS -- Reliable syslog daemon
|
||||||
description = "Reliable syslog daemon"
|
|
||||||
runlevel = "S12345"
|
|
||||||
envfile = "-/etc/default/rsyslog"
|
|
||||||
command = "rsyslogd -n $RSYSLOGD_OPTIONS"
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,8 +1,2 @@
|
|||||||
# Simple NTP client (SNTP)
|
# Simple NTP client (SNTP)
|
||||||
service sntpd {
|
service [2345] <net/route/default> env:-/etc/default/sntpd sntpd -n $SNTPD_OPTIONS -- SNTP client
|
||||||
description = "SNTP client"
|
|
||||||
runlevel = "2345"
|
|
||||||
conditions = { "net/route/default" }
|
|
||||||
envfile = "-/etc/default/sntpd"
|
|
||||||
command = "sntpd -n $SNTPD_OPTIONS"
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,8 +1,2 @@
|
|||||||
# Start SSH daemon as soon as basic networking comes up
|
# Start SSH daemon as soon as basic networking comes up
|
||||||
service sshd {
|
service [2345] <net/lo/up> env:-/etc/default/ssh /usr/sbin/sshd -D $SSHD_OPTS -- OpenSSH daemon
|
||||||
description = "OpenSSH daemon"
|
|
||||||
runlevel = "2345"
|
|
||||||
conditions = { "net/lo/up" }
|
|
||||||
envfile = "-/etc/default/ssh"
|
|
||||||
command = "/usr/sbin/sshd -D $SSHD_OPTS"
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,7 +1,2 @@
|
|||||||
# Start sysklogd as soon as possible, should always run if enabled
|
# Start sysklogd as soon as possible, should always run if enabled
|
||||||
service syslogd {
|
service [S123456789] env:-/etc/default/syslogd syslogd -F $SYSLOGD_OPTIONS -- System logging daemon
|
||||||
description = "System logging daemon"
|
|
||||||
runlevel = "S123456789"
|
|
||||||
envfile = "-/etc/default/syslogd"
|
|
||||||
command = "syslogd -F $SYSLOGD_OPTIONS"
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,8 +1,4 @@
|
|||||||
# Here we use XDM since it has few dependencies (relatively speaking).
|
# Here we use XDM since it has few dependencies (relatively speaking).
|
||||||
# It is also an example of a service without a -- description.
|
# It is also an example of a service without a -- description.
|
||||||
# service [3] lxdm -- Lightweight Login Manager
|
# service [3] lxdm -- Lightweight Login Manager
|
||||||
service xdm {
|
service [3] xdm -nodaemon -- X Display Manager
|
||||||
description = "X Display Manager"
|
|
||||||
runlevel = "3"
|
|
||||||
command = "xdm -nodaemon"
|
|
||||||
}
|
|
||||||
|
|||||||
+43
-107
@@ -1,149 +1,85 @@
|
|||||||
# Sample finit.conf to demonstrate the syntax
|
# Sample finit.conf to demonstrate the syntax
|
||||||
#
|
#
|
||||||
hostname = "testbed"
|
host testbed
|
||||||
|
|
||||||
# Linux kernel modules to load
|
# Linux kernel modules to load
|
||||||
modules = { "button", "evdev", "loop", "psmouse" }
|
module button
|
||||||
|
module evdev
|
||||||
|
module loop
|
||||||
|
module psmouse
|
||||||
|
|
||||||
# Top-level cgroups and their default settings. All groups mandatory
|
# Top-level cgroups and their default settings. All groups mandatory
|
||||||
# but more can be added, max 8 groups in total currently. The cgroup
|
# but more can be added, max 8 groups in total currently. The cgroup
|
||||||
# 'root' is also available, reserved for RT processes. Settings are
|
# 'root' is also available, reserved for RT processes. Settings are
|
||||||
# as-is, only one shorthand 'mem.' exists, other than that it's the
|
# as-is, only one shorthand 'mem.' exists, other than that it's the
|
||||||
# cgroup v2 controller default names.
|
# cgroup v2 controller default names.
|
||||||
cgroup init { cpu.weight = 100 }
|
cgroup init cpu.weight:100
|
||||||
cgroup user { cpu.weight = 100 }
|
cgroup user cpu.weight:100
|
||||||
cgroup system { cpu.weight = 9700 cpu.max = 50000 }
|
cgroup system cpu.weight:9700 cpu.max:50000
|
||||||
|
|
||||||
# Example extra cgroup
|
# Example extra cgroup
|
||||||
cgroup maint { cpu.weight = 100 }
|
cgroup maint cpu.weight:100
|
||||||
|
|
||||||
# Runlevel to start after bootstrap, runlevel 'S'
|
# Runlevel to start after bootstrap, runlevel 'S'
|
||||||
runlevel = 2
|
runlevel 2
|
||||||
|
|
||||||
# Network bringup script
|
# Network bringup script
|
||||||
network = "service networking start"
|
network service networking start
|
||||||
|
|
||||||
# Max file size for each log file: 100 kiB, rotate max 4 copies:
|
# 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 => log.1 => log.2.gz => log.3.gz => log.4.gz
|
||||||
log {
|
log size:100k count:4
|
||||||
size = 100k
|
|
||||||
count = 4
|
|
||||||
}
|
|
||||||
|
|
||||||
# Virtual consoles to start getty on
|
# Virtual consoles to start getty on
|
||||||
tty tty1 { device = "/dev/tty1" }
|
tty /dev/tty1
|
||||||
tty tty2 { device = "/dev/tty2" }
|
tty /dev/tty2
|
||||||
tty tty3 { device = "/dev/tty3" }
|
tty /dev/tty3
|
||||||
|
|
||||||
# Task to run if ctrl-alt-del is pressed. This condition is asserted by
|
# Task to run if ctrl-alt-del is pressed. This condition is asserted by
|
||||||
# Finit upon receiving SIGINT (from the kernel).
|
# Finit upon receiving SIGINT (from the kernel).
|
||||||
task reboot {
|
task <sys/key/ctrlaltdel> [12345789] initctl reboot -- Rebooting system
|
||||||
description = "Rebooting system"
|
|
||||||
runlevel = "12345789"
|
|
||||||
conditions = { "sys/key/ctrlaltdel" }
|
|
||||||
command = "initctl reboot"
|
|
||||||
}
|
|
||||||
|
|
||||||
# Task to run if the kernel gets a power fail condition is pressed.
|
# Task to run if the kernel gets a power fail condition is pressed.
|
||||||
# Asserted by Finit upon receiving SIGPWR (from the kernel).
|
# Asserted by Finit upon receiving SIGPWR (from the kernel).
|
||||||
task poweroff {
|
task <sys/pwr/fail> [12345789] initctl poweroff -- Shutting down system
|
||||||
description = "Shutting down system"
|
|
||||||
runlevel = "12345789"
|
|
||||||
conditions = { "sys/pwr/fail" }
|
|
||||||
command = "initctl poweroff"
|
|
||||||
}
|
|
||||||
|
|
||||||
# Alternative method instead of runparts
|
# Alternative method instead of runparts
|
||||||
#task keyboard-setup {
|
#task [S] /etc/init.d/keyboard-setup start -- Setting up preliminary keymap
|
||||||
# description = "Setting up preliminary keymap"
|
#task [S] /etc/init.d/acpid start -- Starting ACPI Daemon
|
||||||
# runlevel = "S"
|
#task [S] /etc/init.d/kbd start -- Preparing console
|
||||||
# command = "/etc/init.d/keyboard-setup start"
|
#run [2] /etc/init.d/networking start -- Start networking
|
||||||
#}
|
|
||||||
#task acpid {
|
|
||||||
# description = "Starting ACPI Daemon"
|
|
||||||
# runlevel = "S"
|
|
||||||
# command = "/etc/init.d/acpid start"
|
|
||||||
#}
|
|
||||||
#task kbd {
|
|
||||||
# description = "Preparing console"
|
|
||||||
# runlevel = "S"
|
|
||||||
# command = "/etc/init.d/kbd start"
|
|
||||||
#}
|
|
||||||
#run networking {
|
|
||||||
# description = "Start networking"
|
|
||||||
# runlevel = "2"
|
|
||||||
# command = "/etc/init.d/networking start"
|
|
||||||
#}
|
|
||||||
|
|
||||||
# Services to be monitored and respawned as needed
|
# Services to be monitored and respawned as needed
|
||||||
|
|
||||||
# klogd and syslogd are placed in the maint cgroup. There is no
|
# klgod and syslogd are placed in the maint cgroup
|
||||||
# "current cgroup" to switch in this format, every block names its own.
|
cgroup.maint
|
||||||
service klogd {
|
service [2345] <pid/syslogd> klogd -n -- Kernel logging server
|
||||||
description = "Kernel logging server"
|
service [2345] syslogd -n -- Syslog server
|
||||||
runlevel = "2345"
|
|
||||||
conditions = { "pid/syslogd" }
|
|
||||||
cgroup maint {}
|
|
||||||
command = "klogd -n"
|
|
||||||
}
|
|
||||||
service syslogd {
|
|
||||||
description = "Syslog server"
|
|
||||||
runlevel = "2345"
|
|
||||||
cgroup maint {}
|
|
||||||
command = "syslogd -n"
|
|
||||||
}
|
|
||||||
|
|
||||||
# gdm gets its own limits inside the system group, which is where
|
# gdm in the system cgroup (default when read from it's own .conf file)
|
||||||
# services end up when no cgroup block is given.
|
cgroup.system
|
||||||
service gdm {
|
service [3] cgroup:cpu.weight:250,mem.max:10M gdm -- GNOME Display Manager
|
||||||
description = "GNOME Display Manager"
|
|
||||||
runlevel = "3"
|
|
||||||
cgroup system {
|
|
||||||
cpu.weight = 250
|
|
||||||
memory.max = 10M
|
|
||||||
}
|
|
||||||
command = "gdm"
|
|
||||||
}
|
|
||||||
|
|
||||||
# Start SSH daemon with opts from /etc/default/ssh (if available), move
|
# Start SSH daemon with opts from /etc/default/ssh (if available), move
|
||||||
# to user cgroup with cpu.weight 250. Default weight in the user group
|
# to user cgroup with cpu.weight:250. Default for services is system
|
||||||
# is 100 (above).
|
# group. Default weight in user group is 100 (above). Max length of
|
||||||
service sshd {
|
# cgroup argument is (currently) 63 chars.
|
||||||
description = "OpenSSH daemon"
|
#
|
||||||
runlevel = "2345"
|
# Notice alternative syntax where current cgroup is only set for this
|
||||||
envfile = "-/etc/default/ssh"
|
# particular service.
|
||||||
cgroup user {
|
service [2345] cgroup.user:cpu.weight:250,mem.max:10M env:-/etc/default/ssh /usr/sbin/sshd -D $SSHD_OPTS -- OpenSSH daemon
|
||||||
cpu.weight = 250
|
|
||||||
memory.max = 10M
|
|
||||||
}
|
|
||||||
command = "/usr/sbin/sshd -D $SSHD_OPTS"
|
|
||||||
}
|
|
||||||
|
|
||||||
# The BusyBox ntpd does not use syslog when running in the foreground
|
# 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
|
# 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
|
# log file is rotated with the above settings. The condition declares
|
||||||
# a dependency on a system default route (gateway) to be set. ntpd
|
# a dependency on a system default route (gateway) to be set. A single
|
||||||
# does not respect SIGHUP, so Finit restarts it on reload instead.
|
# <!> at the beginning means ntpd does not respect SIGHUP for restart.
|
||||||
service ntpd {
|
service [2345] <!net/route/default> log:/var/log/ntpd.log ntpd -n -l -I eth0 -- NTP daemon
|
||||||
description = "NTP daemon"
|
|
||||||
runlevel = "2345"
|
|
||||||
conditions = { "net/route/default" }
|
|
||||||
reload-signal = "none"
|
|
||||||
log { file = "/var/log/ntpd.log" }
|
|
||||||
command = "ntpd -n -l -I eth0"
|
|
||||||
}
|
|
||||||
|
|
||||||
# Run start scripts from this directory
|
# Run start scripts from this directory
|
||||||
#runparts = "/etc/start.d"
|
# runparts /etc/start.d
|
||||||
|
|
||||||
# For multiple instances of the same service, add :ID to the block title.
|
# For multiple instances of the same service, add :ID somewhere between
|
||||||
service httpd:80 {
|
# the service/run/task keyword and the command.
|
||||||
description = "Web server"
|
service :80 [2345] /sbin/httpd -f -h /http -p 80 -- Web server
|
||||||
runlevel = "2345"
|
service :8080 [2345] /sbin/httpd -f -h /http -p 8080 -- Old web server
|
||||||
command = "/sbin/httpd -f -h /http -p 80"
|
|
||||||
}
|
|
||||||
service httpd:8080 {
|
|
||||||
description = "Old web server"
|
|
||||||
runlevel = "2345"
|
|
||||||
command = "/sbin/httpd -f -h /http -p 8080"
|
|
||||||
}
|
|
||||||
|
|||||||
-141
@@ -1,141 +0,0 @@
|
|||||||
_cond()
|
|
||||||
{
|
|
||||||
initctl -pt cond dump | awk '{print $4}' | sed 's/<\(.*\)>/\1/'
|
|
||||||
}
|
|
||||||
|
|
||||||
_ident()
|
|
||||||
{
|
|
||||||
if [ -n "$1" ]; then
|
|
||||||
initctl ident | grep -q $1
|
|
||||||
else
|
|
||||||
initctl ident
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
_svc()
|
|
||||||
{
|
|
||||||
initctl ls -pt | grep $1 | sed "s/.*\/\(.*\)/\1/g" | sort -u
|
|
||||||
}
|
|
||||||
|
|
||||||
_enabled()
|
|
||||||
{
|
|
||||||
echo "$(_svc enabled)"
|
|
||||||
}
|
|
||||||
|
|
||||||
_available()
|
|
||||||
{
|
|
||||||
all=$(mktemp)
|
|
||||||
ena=$(mktemp)
|
|
||||||
echo "$(_svc available)" >$all
|
|
||||||
echo "$(_svc enabled)" >$ena
|
|
||||||
grep -v -f $ena $all
|
|
||||||
rm $all $ena
|
|
||||||
}
|
|
||||||
|
|
||||||
# Determine first non-option word. Usually the command
|
|
||||||
_firstword() {
|
|
||||||
local firstword i
|
|
||||||
|
|
||||||
firstword=
|
|
||||||
for ((i = 1; i < ${#COMP_WORDS[@]}; ++i)); do
|
|
||||||
if [[ ${COMP_WORDS[i]} != -* ]]; then
|
|
||||||
firstword=${COMP_WORDS[i]}
|
|
||||||
break
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
echo $firstword
|
|
||||||
}
|
|
||||||
|
|
||||||
# Determine last non-option word. Uusally a sub-command
|
|
||||||
_lastword() {
|
|
||||||
local lastword i
|
|
||||||
|
|
||||||
lastword=
|
|
||||||
for ((i = 1; i < ${#COMP_WORDS[@]}; ++i)); do
|
|
||||||
if [[ ${COMP_WORDS[i]} != -* ]] && [[ -n ${COMP_WORDS[i]} ]] && [[ ${COMP_WORDS[i]} != $cur ]]; then
|
|
||||||
lastword=${COMP_WORDS[i]}
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
echo $lastword
|
|
||||||
}
|
|
||||||
|
|
||||||
_initctl()
|
|
||||||
{
|
|
||||||
local cur command
|
|
||||||
|
|
||||||
cur=${COMP_WORDS[COMP_CWORD]}
|
|
||||||
prev="${COMP_WORDS[COMP_CWORD-1]}"
|
|
||||||
firstword=$(_firstword)
|
|
||||||
lastword=$(_lastword)
|
|
||||||
|
|
||||||
commands="status cond debug help kill ls log version list enable \
|
|
||||||
disable touch show cat edit create delete reload start \
|
|
||||||
stop restart signal cgroup ps top plugins runlevel reboot \
|
|
||||||
halt poweroff suspend utmp"
|
|
||||||
cond_cmds="set get clear status dump"
|
|
||||||
cond_types="hook net pid service task usr"
|
|
||||||
signals="int term hup stop tstp cont usr1 usr2 pwr"
|
|
||||||
options="-b --batch \
|
|
||||||
-c --create \
|
|
||||||
-d --debug \
|
|
||||||
-f --force \
|
|
||||||
-h --help \
|
|
||||||
-j --json \
|
|
||||||
-n --noerr \
|
|
||||||
-1 --once \
|
|
||||||
-p --plain \
|
|
||||||
-q --quiet \
|
|
||||||
-t --no-heading \
|
|
||||||
-v --verbose \
|
|
||||||
-V --version"
|
|
||||||
|
|
||||||
case "${firstword}" in
|
|
||||||
enable)
|
|
||||||
COMPREPLY=($(compgen -W "$(_available)" -- $cur))
|
|
||||||
;;
|
|
||||||
disable|touch)
|
|
||||||
COMPREPLY=($(compgen -W "$(_enabled)" -- $cur))
|
|
||||||
;;
|
|
||||||
show|cat|edit|delete)
|
|
||||||
COMPREPLY=($(compgen -W "$(_svc .)" -- $cur))
|
|
||||||
;;
|
|
||||||
start|stop|restart|log|status)
|
|
||||||
COMPREPLY=($(compgen -W "$(_ident)" -- $cur))
|
|
||||||
;;
|
|
||||||
signal|kill)
|
|
||||||
if $(_ident "${prev}"); then
|
|
||||||
COMPREPLY=($(compgen -W "$signals" -- $cur))
|
|
||||||
else
|
|
||||||
COMPREPLY=($(compgen -W "$(_ident)" -- $cur))
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
cond)
|
|
||||||
case "${lastword}" in
|
|
||||||
set|clear)
|
|
||||||
compopt -o nospace
|
|
||||||
COMPREPLY=($(compgen -W "usr/" -- $cur))
|
|
||||||
;;
|
|
||||||
get)
|
|
||||||
COMPREPLY=($(compgen -W "$(_cond)" -- $cur))
|
|
||||||
;;
|
|
||||||
dump)
|
|
||||||
COMPREPLY=($(compgen -W "$cond_types" -- $cur))
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
COMPREPLY=($(compgen -W "$cond_cmds" -- $cur))
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
COMPREPLY=($(compgen -W "$commands" -- $cur))
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
if [[ $cur == -* ]]; then
|
|
||||||
COMPREPLY=($(compgen -W "$options" -- $cur))
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
complete -F _initctl initctl
|
|
||||||
@@ -18,7 +18,7 @@ PKG_CONFIG_LIBDIR=/usr/lib/pkgconfig:/usr/local/lib/pkgconfig ./configure \
|
|||||||
--sysconfdir=/etc --localstatedir=/var \
|
--sysconfdir=/etc --localstatedir=/var \
|
||||||
--enable-dbus-plugin --enable-x11-common-plugin \
|
--enable-dbus-plugin --enable-x11-common-plugin \
|
||||||
--enable-alsa-utils-plugin --with-watchdog \
|
--enable-alsa-utils-plugin --with-watchdog \
|
||||||
--with-keventd --with-sulogin
|
--with-keventd
|
||||||
|
|
||||||
echo
|
echo
|
||||||
echo "*** Building ..."
|
echo "*** Building ..."
|
||||||
@@ -35,3 +35,4 @@ fi
|
|||||||
echo
|
echo
|
||||||
echo "*** Done"
|
echo "*** Done"
|
||||||
echo
|
echo
|
||||||
|
|
||||||
|
|||||||
+6
-16
@@ -3,34 +3,24 @@
|
|||||||
|
|
||||||
## Runlevel to start after bootstrap, runlevel 'S'
|
## Runlevel to start after bootstrap, runlevel 'S'
|
||||||
# Default is 2
|
# Default is 2
|
||||||
#runlevel = 2
|
#runlevel 2
|
||||||
|
|
||||||
# Top-level cgroups and their default settings. All groups mandatory
|
# Top-level cgroups and their default settings. All groups mandatory
|
||||||
# but more can be added, max 8 groups in total currently. The cgroup
|
# but more can be added, max 8 groups in total currently. The cgroup
|
||||||
# 'root' is also available, reserved for RT processes. Settings are
|
# 'root' is also available, reserved for RT processes. Settings are
|
||||||
# as-is, only one shorthand 'mem.' exists, other than that it's the
|
# as-is, only one shorthand 'mem.' exists, other than that it's the
|
||||||
# cgroup v2 controller default names.
|
# cgroup v2 controller default names.
|
||||||
#cgroup init { cpu.weight = 100 }
|
#cgroup init cpu.weight:100
|
||||||
#cgroup user { cpu.weight = 100 }
|
#cgroup user cpu.weight:100
|
||||||
#cgroup system { cpu.weight = 9700 }
|
#cgroup system cpu.weight:9700
|
||||||
|
|
||||||
# Task to run if ctrl-alt-del is pressed. This condition is asserted by
|
# Task to run if ctrl-alt-del is pressed. This condition is asserted by
|
||||||
# Finit upon receiving SIGINT (from the kernel).
|
# Finit upon receiving SIGINT (from the kernel).
|
||||||
#task reboot {
|
#task <sys/key/ctrlaltdel> [12345789] initctl reboot -- Rebooting system
|
||||||
# description = "Rebooting system"
|
|
||||||
# runlevel = "12345789"
|
|
||||||
# conditions = { "sys/key/ctrlaltdel" }
|
|
||||||
# command = "initctl reboot"
|
|
||||||
#}
|
|
||||||
|
|
||||||
# Task to run if the kernel gets a power fail condition is pressed.
|
# Task to run if the kernel gets a power fail condition is pressed.
|
||||||
# Asserted by Finit upon receiving SIGPWR (from the kernel).
|
# Asserted by Finit upon receiving SIGPWR (from the kernel).
|
||||||
#task poweroff {
|
#task <sys/pwr/fail> [12345789] initctl poweroff -- Shutting down system
|
||||||
# description = "Shutting down system"
|
|
||||||
# runlevel = "12345789"
|
|
||||||
# conditions = { "sys/pwr/fail" }
|
|
||||||
# command = "initctl poweroff"
|
|
||||||
#}
|
|
||||||
|
|
||||||
## Bootstrap services and tasks
|
## Bootstrap services and tasks
|
||||||
# Can be listed here or in /etc/finit.d/*.conf
|
# Can be listed here or in /etc/finit.d/*.conf
|
||||||
|
|||||||
@@ -1,7 +1,3 @@
|
|||||||
# Handle PWR button to shutdown/reboot -- useful in Qemu (virt-manager)
|
# Handle PWR button to shutdown/reboot -- useful in Qemu (virt-manager)
|
||||||
# Depends on syslogd having started. Redirect any output to log.
|
# Depends on syslogd having started. Redirect any output to log.
|
||||||
service acpid {
|
service [2345] acpid -f -- ACPI daemon
|
||||||
description = "ACPI daemon"
|
|
||||||
runlevel = "2345"
|
|
||||||
command = "acpid -f"
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,6 +1 @@
|
|||||||
service crond {
|
service [2345] <pid/syslogd> crond -f -S -c /etc/crontabs -- Cron daemon
|
||||||
description = "Cron daemon"
|
|
||||||
runlevel = "2345"
|
|
||||||
conditions = { "pid/syslogd" }
|
|
||||||
command = "crond -f -S -c /etc/crontabs"
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,5 +1 @@
|
|||||||
service dhcpcd {
|
service [2345] dhcpcd -B -M -- DHCP client
|
||||||
description = "DHCP client"
|
|
||||||
runlevel = "2345"
|
|
||||||
command = "dhcpcd -B -M"
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,5 +1 @@
|
|||||||
service dmeventd {
|
service [S12345] dmeventd -f -- Device mapper event daemon
|
||||||
description = "Device mapper event daemon"
|
|
||||||
runlevel = "S12345"
|
|
||||||
command = "dmeventd -f"
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,19 +1,4 @@
|
|||||||
# Consoles to start Finit built-in getty on when system is up
|
# Consoles to start Finit built-in getty on when system is up
|
||||||
tty tty1 {
|
tty [12345] /dev/tty1 noclear nowait
|
||||||
runlevel = "12345"
|
tty [2345] /dev/tty2 noclear nowait
|
||||||
device = "/dev/tty1"
|
tty [2345] /dev/tty3 noclear nowait
|
||||||
noclear = true
|
|
||||||
nowait = true
|
|
||||||
}
|
|
||||||
tty tty2 {
|
|
||||||
runlevel = "2345"
|
|
||||||
device = "/dev/tty2"
|
|
||||||
noclear = true
|
|
||||||
nowait = true
|
|
||||||
}
|
|
||||||
tty tty3 {
|
|
||||||
runlevel = "2345"
|
|
||||||
device = "/dev/tty3"
|
|
||||||
noclear = true
|
|
||||||
nowait = true
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,6 +1,2 @@
|
|||||||
# Oneshot task to run once at bootstrap
|
# Oneshot task to run once at bootstrap
|
||||||
task keymap {
|
task [S] zcat /etc/keymap/se.bmap.gz | loadkmap -- Loading keymap
|
||||||
description = "Loading keymap"
|
|
||||||
runlevel = "S"
|
|
||||||
command = "zcat /etc/keymap/se.bmap.gz | loadkmap"
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,5 +1 @@
|
|||||||
service lxdm {
|
service [2345] lxdm -- Lightweight Login Manager
|
||||||
description = "Lightweight Login Manager"
|
|
||||||
runlevel = "2345"
|
|
||||||
command = "lxdm"
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,3 +1,7 @@
|
|||||||
## Linux kernel modules to load
|
## Linux kernel modules to load
|
||||||
# Other candidates: fbcon, button, evdev, mousedev, 8139cp
|
#module fbcon
|
||||||
modules = { "softdog" }
|
#module button
|
||||||
|
#module evdev
|
||||||
|
#module mousedev
|
||||||
|
#module 8139cp
|
||||||
|
module softdog
|
||||||
|
|||||||
@@ -1,8 +1,2 @@
|
|||||||
# Silly Busybox ntpd has no option to use syslog when running in foreground
|
# Silly Busybox ntpd has no option to use syslog when running in foreground
|
||||||
service ntpd {
|
service [2345] <pid/syslogd> log ntpd -n -N -p pool.ntp.org -- NTP daemon
|
||||||
description = "NTP daemon"
|
|
||||||
runlevel = "2345"
|
|
||||||
conditions = { "pid/syslogd" }
|
|
||||||
log { }
|
|
||||||
command = "ntpd -n -N -p pool.ntp.org"
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,6 +1,2 @@
|
|||||||
# Start SSH daemon as soon as basic networking comes up
|
# Start SSH daemon as soon as basic networking comes up
|
||||||
service sshd {
|
service [2345] /usr/sbin/sshd -D -- OpenSSH daemon
|
||||||
description = "OpenSSH daemon"
|
|
||||||
runlevel = "2345"
|
|
||||||
command = "/usr/sbin/sshd -D"
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,13 +1,4 @@
|
|||||||
# Start syslogd as soon as possible, should always run
|
# Start syslogd as soon as possible, should always run
|
||||||
# Start klogd as soon as possible, but after syslogd
|
# Start klogd as soon as possible, but after syslogd
|
||||||
service syslogd {
|
service [S12345] syslogd -n -- Syslog daemon
|
||||||
description = "Syslog daemon"
|
service [S12345] <pid/syslogd> klogd -n -- Kernel log daemon
|
||||||
runlevel = "S12345"
|
|
||||||
command = "syslogd -n"
|
|
||||||
}
|
|
||||||
service klogd {
|
|
||||||
description = "Kernel log daemon"
|
|
||||||
runlevel = "S12345"
|
|
||||||
conditions = { "pid/syslogd" }
|
|
||||||
command = "klogd -n"
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,7 +1 @@
|
|||||||
service uuidd {
|
service @uuidd:uuidd [2345] uuidd -F -- UUID generation daemon
|
||||||
description = "UUID generation daemon"
|
|
||||||
runlevel = "2345"
|
|
||||||
user = "uuidd"
|
|
||||||
group = "uuidd"
|
|
||||||
command = "uuidd -F"
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,6 +0,0 @@
|
|||||||
EXTRA_DIST = org.finit.conf
|
|
||||||
|
|
||||||
if DBUS
|
|
||||||
dbuspolicydir = $(datadir)/dbus-1/system.d
|
|
||||||
dist_dbuspolicy_DATA = org.finit.conf
|
|
||||||
endif
|
|
||||||
@@ -1,63 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<!DOCTYPE busconfig PUBLIC
|
|
||||||
"-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
|
|
||||||
"http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
|
|
||||||
<!--
|
|
||||||
System-bus policy for finit.
|
|
||||||
|
|
||||||
finit (PID 1, root) owns the `org.finit` well-known name. The
|
|
||||||
policy below lets unprivileged callers introspect, read
|
|
||||||
properties, and query service / condition state, but disallows
|
|
||||||
every state-changing method at the broker. finit *also* enforces
|
|
||||||
per-method authorisation itself (LINK_METHOD_PRIVILEGED), so
|
|
||||||
defense-in-depth: even if a permissive policy is installed by
|
|
||||||
mistake, finit rejects unprivileged state changes. It reads the
|
|
||||||
caller from SO_PEERCRED on the local bus, and on the system bus it
|
|
||||||
asks the broker who sent each privileged call, via
|
|
||||||
GetConnectionUnixUser.
|
|
||||||
-->
|
|
||||||
<busconfig>
|
|
||||||
|
|
||||||
<!-- Only finit (root) may own the org.finit bus name. -->
|
|
||||||
<policy user="root">
|
|
||||||
<allow own="org.finit"/>
|
|
||||||
<allow send_destination="org.finit"/>
|
|
||||||
<allow receive_sender="org.finit"/>
|
|
||||||
</policy>
|
|
||||||
|
|
||||||
<!-- Everyone may introspect, read properties, and call the
|
|
||||||
read-only Manager1 / Cond1 methods. Signals fan out
|
|
||||||
unconditionally. -->
|
|
||||||
<policy context="default">
|
|
||||||
<allow send_destination="org.finit"
|
|
||||||
send_interface="org.freedesktop.DBus.Introspectable"/>
|
|
||||||
<allow send_destination="org.finit"
|
|
||||||
send_interface="org.freedesktop.DBus.Peer"/>
|
|
||||||
<allow send_destination="org.finit"
|
|
||||||
send_interface="org.freedesktop.DBus.Properties"
|
|
||||||
send_member="Get"/>
|
|
||||||
<allow send_destination="org.finit"
|
|
||||||
send_interface="org.freedesktop.DBus.Properties"
|
|
||||||
send_member="GetAll"/>
|
|
||||||
|
|
||||||
<allow send_destination="org.finit"
|
|
||||||
send_interface="org.finit.Manager1"
|
|
||||||
send_member="ListServices"/>
|
|
||||||
<allow send_destination="org.finit"
|
|
||||||
send_interface="org.finit.Manager1"
|
|
||||||
send_member="GetService"/>
|
|
||||||
|
|
||||||
<allow send_destination="org.finit"
|
|
||||||
send_interface="org.finit.Cond1"
|
|
||||||
send_member="Get"/>
|
|
||||||
<allow send_destination="org.finit"
|
|
||||||
send_interface="org.finit.Cond1"
|
|
||||||
send_member="List"/>
|
|
||||||
<allow send_destination="org.finit"
|
|
||||||
send_interface="org.finit.Cond1"
|
|
||||||
send_member="Dump"/>
|
|
||||||
|
|
||||||
<allow receive_sender="org.finit"/>
|
|
||||||
</policy>
|
|
||||||
|
|
||||||
</busconfig>
|
|
||||||
-2209
File diff suppressed because it is too large
Load Diff
+4
-12
@@ -1,12 +1,4 @@
|
|||||||
SUBDIRS = config
|
docsdir := @docdir@/doc
|
||||||
EXTRA_DIST = AUTHORS ChangeLog.md
|
docs_DATA = config.md conditions.md distro.md plugins.md \
|
||||||
|
service.md signals.md svc-machine.png cmdline.md
|
||||||
docsdir := @docdir@/doc
|
EXTRA_DIST = $(docs_DATA)
|
||||||
dist_docs_DATA = build.md cmdline.md commands.md conditions.md \
|
|
||||||
dbus.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 @@
|
|||||||
index.md
|
config.md
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
Bootstrap
|
||||||
|
=========
|
||||||
|
|
||||||
|
1. Prepare emergency shell, if enabled
|
||||||
|
2. Set up initial signal handlers
|
||||||
|
3. Set up default $PATH early
|
||||||
|
4. Mount `/proc` and `/sys`
|
||||||
|
5. Check kernel command line for `debug` to figure out log level
|
||||||
|
6. Load all `.so` plugins
|
||||||
|
7. Call `fsck` on file systems listed in `/etc/fstab`
|
||||||
|
8. Populate `/dev` using either udev or mdev, depending on system type
|
||||||
|
9. Parse `/etc/finit.conf`
|
||||||
|
10. Start built-in watchdog, if enabled and `WDT_DEVNODE` exists. This
|
||||||
|
means any WDT that requires a kernel module need to be either
|
||||||
|
compiled into the kernel, or insmod'ed in `/etc/finit.conf`
|
||||||
|
11. Load all `/etc/finit.d/*.conf` files and set hostname
|
||||||
|
12. Remount `/` read-write if `/` is listed in `/etc/fstab` without `ro`
|
||||||
|
13. Call 1st level hooks, `HOOK_ROOTFS_UP`
|
||||||
|
14. Mount all file systems listed in `/etc/fstab` and swap, if available.
|
||||||
|
On mount error `HOOK_MOUNT_ERROR` is called. After mount, regardless
|
||||||
|
of error, `HOOK_MOUNT_POST` is called
|
||||||
|
15. Enable SysV init signals
|
||||||
|
16. Call 2nd level hooks, `HOOK_BASEFS_UP`
|
||||||
|
17. Cleanup stale files from `/tmp/*` et al, handled by `bootmisc` plugin
|
||||||
|
18. Load kernel params from `/etc/sysctl.d/*.conf`, `/etc/sysctl.conf`
|
||||||
|
et al. (Supports all locations that SysV init does.), handled by
|
||||||
|
`procps` plugin
|
||||||
|
19. Start all 'S' runlevel tasks and services
|
||||||
|
20. Bring up loopback interface and all `/etc/network/interfaces`, if
|
||||||
|
the `.conf` setting `network <SCRIPT>` is set, it is called instead
|
||||||
|
21. Call 3rd level hooks, `HOOK_NETWORK_UP`
|
||||||
|
22. If `runparts <DIR>` is set, [run-parts(8)][] is called on `<DIR>`
|
||||||
|
23. Switch to the configured runlevel from `/etc/finit.conf`, default 2.
|
||||||
|
At every runlevel change all `*.conf` files in `/etc/finit.d/` are
|
||||||
|
(re)loaded and new services, tasks, and blocking run commands are
|
||||||
|
started. Provided they are allowed in the new runlevel and all of
|
||||||
|
their conditions, if any, are set.
|
||||||
|
24. Call 4th level hooks, `HOOK_SVC_UP`
|
||||||
|
25. Call `/etc/rc.local`, if it exists and is an executable shell script
|
||||||
|
26. Call 5th level (last) hooks, `HOOK_SYSTEM_UP`
|
||||||
|
27. Start all configured TTYs
|
||||||
|
|
||||||
|
In (19) and (23) tasks and services defined in `/etc/finit.conf` and
|
||||||
|
`/etc/finit.d/*.conf` are started.
|
||||||
|
|
||||||
|
Notice the seven hook points that are called at various point in the
|
||||||
|
bootstrap process. This is where plugins can extend the boot in any
|
||||||
|
way they please. There are other hook points available, for more on
|
||||||
|
this, see [plugins.md](plugins.md).
|
||||||
|
|
||||||
|
For instance, at `HOOK_BASEFS_UP` a plugin could read an XML file from a
|
||||||
|
USB stick, convert/copy its contents to the system's `/etc/` directory,
|
||||||
|
well before all 'S' runlevel tasks are started. This could be used with
|
||||||
|
system images that are created read-only and all configuration is stored
|
||||||
|
on external media.
|
||||||
|
|
||||||
|
[run-parts(8)]: http://manpages.debian.org/cgi-bin/man.cgi?query=run-parts
|
||||||
+40
-147
@@ -1,37 +1,36 @@
|
|||||||
Building Finit
|
Building
|
||||||
==============
|
========
|
||||||
|
|
||||||
|
* [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 three external libraries:
|
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
|
||||||
- [libConfuse][], the parser behind the .conf format
|
|
||||||
|
|
||||||
The bundled device manager, keventd, needs a fourth: libblkid from
|
**NOTE:** Most free/open source software that uses `configure` default
|
||||||
[util-linux][]. It reads the filesystem UUID and label off block
|
to install to `/usr/local`. However, some Linux distributions do no
|
||||||
devices, which is what the curated rules name the `/dev/disk/by-uuid/`
|
longer search that path for installed software, e.g. Fedora and Alpine
|
||||||
and `/dev/disk/by-label/` symlinks after. keventd is enabled by
|
Linux. To get finit's configure script to find its dependencies you
|
||||||
default, so this is a hard requirement unless you build with
|
have to help the `pkg-config` tool a bit if you do not change the
|
||||||
`--without-keventd`.
|
default prefix path:
|
||||||
|
|
||||||
> [!IMPORTANT]
|
PKG_CONFIG_LIBDIR=/usr/local/lib/pkgconfig ./configure
|
||||||
> Most free/open source software packages that use `configure` default
|
|
||||||
> to install to `/usr/local`. However, some Linux distributions do no
|
|
||||||
> longer search that path for installed software, e.g. Fedora and Alpine
|
|
||||||
> Linux. To get finit's configure script to find its dependencies you
|
|
||||||
> have to help the `pkg-config` tool a bit if you do not change the
|
|
||||||
> default prefix path:
|
|
||||||
>
|
|
||||||
> PKG_CONFIG_LIBDIR=/usr/local/lib/pkgconfig ./configure
|
|
||||||
|
|
||||||
The configure script checks for all dependencies, including the correct
|
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:
|
||||||
|
|
||||||
- libite v2.2.0, or later
|
- libite v2.2.0
|
||||||
- libuEv v2.2.0, or later
|
- libuEv v2.2.0
|
||||||
- libConfuse v3.3, or later
|
|
||||||
- libblkid, any version, when keventd is enabled
|
|
||||||
|
|
||||||
|
|
||||||
Configure
|
Configure
|
||||||
@@ -55,58 +54,19 @@ Below are a few of the main switches to configure:
|
|||||||
will be linked statically.
|
will be linked statically.
|
||||||
|
|
||||||
* `--enable-kernel-cmdline`: Enable Finit pre-4.1 parsing of init args from
|
* `--enable-kernel-cmdline`: Enable Finit pre-4.1 parsing of init args from
|
||||||
`/proc/cmdline`, this is *not recommended* since Finit may be running as the
|
`/proc/cmdline`, this is not recommended since Finit may be running as the
|
||||||
init for container apps that can see the host's `/proc` filesystem
|
init for container apps that can see the host's `/proc` filesystem
|
||||||
|
|
||||||
* `--disable-dbus`: Opt out of Finit's built-in D-Bus support, enabled by
|
|
||||||
default. See [D-Bus Integration](dbus.md) for what it provides. Not to
|
|
||||||
be confused with `--disable-dbus-plugin` below, which only governs
|
|
||||||
starting an external `dbus-daemon`
|
|
||||||
|
|
||||||
* `--enable-alsa-utils-plugin`: Enable the optional `alsa-utils.so` sound plugin.
|
* `--enable-alsa-utils-plugin`: Enable the optional `alsa-utils.so` sound plugin.
|
||||||
|
|
||||||
* `--disable-dbus-plugin`: Drop the `dbus.so` plugin, which launches
|
* `--enable-dbus-plugin`: Enable the optional D-Bus `dbus.so` plugin.
|
||||||
`dbus-daemon` at boot. Enabled by default; the plugin does nothing on
|
|
||||||
a system that has no `dbus-daemon` installed, so opting out is only
|
|
||||||
needed to keep init from starting a bus on a system that has one.
|
|
||||||
Unrelated to the built-in bus, see `--disable-dbus` above.
|
|
||||||
|
|
||||||
* `--enable-resolvconf-plugin`: Enable the `resolvconf.so` optional plugin.
|
* `--enable-resolvconf-plugin`: Enable the `resolvconf.so` optional plugin.
|
||||||
|
|
||||||
* `--enable-x11-common-plugin`: Enable the optional X Window `x11-common.so` plugin.
|
* `--enable-x11-common-plugin`: Enable the optional X Window `x11-common.so` plugin.
|
||||||
|
|
||||||
* `--without-keventd`: Drop the bundled device manager, for systems that
|
|
||||||
run mdev, mdevd, or udevd instead. Enabled by default, and the only
|
|
||||||
thing that pulls in libblkid. See [Bundled Device Manager](keventd.md).
|
|
||||||
|
|
||||||
* `--without-sulogin`: Drop the bundled `sulogin`, enabled by default,
|
|
||||||
and use the system `sulogin(8)` instead. The one shipped with Finit
|
|
||||||
*allows password-less* login if the `root` user is disabled or has no
|
|
||||||
password at all. `--with-sulogin=USER` prompts for another user's
|
|
||||||
password than `root`'s.
|
|
||||||
|
|
||||||
* `--without-watchdog`: Drop the bundled `watchdogd`, enabled by default
|
|
||||||
on `/dev/watchdog`, `--with-watchdog=DEV` selects another device.
|
|
||||||
Finit starts it when the device node exists, see [Watchdog](watchdog.md).
|
|
||||||
|
|
||||||
* `--with-libsystemd`: Build the replacement `libsystemd`, which lets
|
|
||||||
programs that use `sd_notify()` talk to Finit without systemd. Off by
|
|
||||||
default because it installs `libsystemd.so.0` in `$libdir`: on a host
|
|
||||||
that has the real one, ours shadows it in the loader cache and every
|
|
||||||
program linking it, `dbus-daemon` and `udevd` included, loses the
|
|
||||||
symbols it needs. Safe on a systemd-free system, which is the point
|
|
||||||
of it.
|
|
||||||
|
|
||||||
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
|
|
||||||
> however included in (officially supported) released tarballs. The
|
|
||||||
> idea is that you should not need GNU autotools to build, only the
|
|
||||||
> above mentioned dependencies, a POSIX shell, a C compiler and make.
|
|
||||||
> Any contributing to Finit can generate it from `configure.ac` using
|
|
||||||
> the `autogen.sh` script.
|
|
||||||
|
|
||||||
|
|
||||||
Example
|
Example
|
||||||
-------
|
-------
|
||||||
@@ -114,15 +74,16 @@ Example
|
|||||||
First, unpack the archive:
|
First, unpack the archive:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
$ tar xf finit-4.3.tar.gz
|
$ tar xf finit-4.1.tar.gz
|
||||||
$ cd finit-4.3/
|
$ cd finit-4.1/
|
||||||
```
|
```
|
||||||
|
|
||||||
Then configure, build and install:
|
Then configure, build and install:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
$ ./configure --prefix=/usr --exec-prefix= \
|
$ ./configure --prefix=/usr --exec-prefix= \
|
||||||
--sysconfdir=/etc --localstatedir=/var
|
--sysconfdir=/etc --localstatedir=/var \
|
||||||
|
--with-keventd --with-watchdog
|
||||||
$ make
|
$ make
|
||||||
.
|
.
|
||||||
.
|
.
|
||||||
@@ -130,7 +91,7 @@ $ make
|
|||||||
$ DESTDIR=/tmp/finit make install
|
$ DESTDIR=/tmp/finit make install
|
||||||
```
|
```
|
||||||
|
|
||||||
In this example the [finit-4.3.tar.gz][1] archive is unpacked to the
|
In this example the [finit-4.1.tar.gz][1] archive is unpacked to the
|
||||||
user's home directory, configured, built and installed to a temporary
|
user's home directory, configured, built and installed to a temporary
|
||||||
staging directory. The environment variable `DESTDIR` controls the
|
staging directory. The environment variable `DESTDIR` controls the
|
||||||
destination directory when installing, very useful for building binary
|
destination directory when installing, very useful for building binary
|
||||||
@@ -143,65 +104,10 @@ Linux config to:
|
|||||||
|
|
||||||
CONFIG_UEVENT_HELPER_PATH="/sbin/mdev"
|
CONFIG_UEVENT_HELPER_PATH="/sbin/mdev"
|
||||||
|
|
||||||
> [!TIP]
|
**Note:** If you run into problems starting Finit, take a look at
|
||||||
> If you run into problems starting Finit, take a look at `finit.c`.
|
`finit.c`. One of the most common problems is a custom Linux kernel
|
||||||
> One of the most common problems is a custom Linux kernel build that
|
build that lack `CONFIG_DEVTMPFS`. Another is too much cruft in the
|
||||||
> lack `CONFIG_DEVTMPFS`. Another is too much cruft in the system
|
system `/etc/fstab`.
|
||||||
> `/etc/fstab`.
|
|
||||||
|
|
||||||
|
|
||||||
Testing
|
|
||||||
-------
|
|
||||||
|
|
||||||
`make check` runs the test suite in a private namespace, so it is safe
|
|
||||||
on a running system. It needs `unshare` and, on Ubuntu, unprivileged
|
|
||||||
user namespaces enabled:
|
|
||||||
|
|
||||||
```shell
|
|
||||||
sudo sysctl kernel.apparmor_restrict_unprivileged_userns=0
|
|
||||||
make check
|
|
||||||
```
|
|
||||||
|
|
||||||
The D-Bus message parser is the only place in Finit where bytes off a
|
|
||||||
socket become pointers, so it also has a fuzz target. `make check`
|
|
||||||
runs it as a fixed sweep, which takes milliseconds and needs nothing
|
|
||||||
beyond the normal build. To fuzz it properly, build it with clang and
|
|
||||||
libFuzzer:
|
|
||||||
|
|
||||||
```shell
|
|
||||||
clang -fsanitize=fuzzer,address -DLINK_FUZZ_LIBFUZZER -D_GNU_SOURCE \
|
|
||||||
-I libink -I . -o fuzz-msg-parse \
|
|
||||||
test/src/fuzz-msg-parse.c libink/*.c
|
|
||||||
mkdir -p .fuzz-corpus
|
|
||||||
./fuzz-msg-parse .fuzz-corpus -max_total_time=300
|
|
||||||
```
|
|
||||||
|
|
||||||
Give it a corpus directory as above and it saves what it learns there,
|
|
||||||
so the next run picks up where this one left off instead of starting
|
|
||||||
cold. Nothing writes to it unless you name it: without the argument
|
|
||||||
libFuzzer keeps everything in memory and the run leaves only crashes
|
|
||||||
behind. `make distclean` clears the corpus and the target.
|
|
||||||
|
|
||||||
Once a corpus has grown, most of it reaches code some earlier input
|
|
||||||
already reached. Minimise it:
|
|
||||||
|
|
||||||
```shell
|
|
||||||
./fuzz-msg-parse -merge=1 .fuzz-corpus-min .fuzz-corpus
|
|
||||||
rm -rf .fuzz-corpus && mv .fuzz-corpus-min .fuzz-corpus
|
|
||||||
```
|
|
||||||
|
|
||||||
Run `./configure` first, the target needs the generated `config.h`.
|
|
||||||
If the link fails with `cannot find -lstdc++`, install the `libstdc++`
|
|
||||||
headers matching the newest GCC on the system, not the default one:
|
|
||||||
clang picks the newest tree it finds, and that is the one that needs
|
|
||||||
them. CI runs this target on every pull request, carrying its
|
|
||||||
corpus between runs so it reaches deeper over time.
|
|
||||||
|
|
||||||
Feed a file back to the target to reproduce a find:
|
|
||||||
|
|
||||||
```shell
|
|
||||||
./fuzz-msg-parse crash-3f2a...
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
Running
|
Running
|
||||||
@@ -240,32 +146,21 @@ 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.
|
||||||
|
|
||||||
> [!IMPORTANT]
|
|
||||||
> In rescue mode `initctl` will not work, the same goes for `reboot`,
|
|
||||||
> `shutdown`, and `poweroff` commands, provided they are the Finit
|
|
||||||
> versions of these commands. Use the `-f` flag to force the action.
|
|
||||||
|
|
||||||
|
|
||||||
Debugging
|
Debugging
|
||||||
---------
|
---------
|
||||||
|
|
||||||
Edit, or append to, the kernel command line: remove `quiet` to enable
|
Edit, or append to, the kernel command line: remove `quiet` to enable
|
||||||
kernel messages and add `finit.debug` to enable Finit debug messages.
|
kernel messages and add `debug` to enable Finit debug messages.
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
append="init=/sbin/finit -- finit.debug"
|
append="init=/sbin/finit debug"
|
||||||
```
|
```
|
||||||
|
|
||||||
Notice the `--` separator.
|
|
||||||
|
|
||||||
To debug startup issues, in particular issues with getty/login, add
|
To debug startup issues, in particular issues with getty/login, add
|
||||||
the following to your Finit .conf file:
|
the following to your Finit .conf file:
|
||||||
|
|
||||||
tty board {
|
tty [12345789] notty noclear
|
||||||
runlevel = "12345789"
|
|
||||||
notty = true
|
|
||||||
noclear = true
|
|
||||||
}
|
|
||||||
|
|
||||||
The `notty` option ensures reusing the stdin/stdout set up by the
|
The `notty` option ensures reusing the stdin/stdout set up by the
|
||||||
kernel. Remember, this is only for debugging and would leave your
|
kernel. Remember, this is only for debugging and would leave your
|
||||||
@@ -276,12 +171,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.
|
||||||
|
|
||||||
> [!CAUTION]
|
**NOTE:** Neither of these options should be enabled on production
|
||||||
> None of these options should be enabled on production systems since
|
systems since they can potentially give a user root access.
|
||||||
> 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.1.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
|
||||||
[libConfuse]: https://github.com/libconfuse/libconfuse
|
|
||||||
[util-linux]: https://github.com/util-linux/util-linux
|
|
||||||
|
|||||||
+19
-89
@@ -4,70 +4,19 @@ 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.
|
||||||
|
|
||||||
> [!IMPORTANT]
|
|
||||||
> Remember to use `--` to separate kernel parameters from parameters to
|
|
||||||
> init. E.g., `init=/sbin/finit -- finit.debug rescue`
|
|
||||||
|
|
||||||
The `bool` setting is one of `on, off, true false, 1, 0`.
|
The `bool` setting is one of `on, off, true false, 1, 0`.
|
||||||
|
|
||||||
|
> **NOTE:** remember to use `--` to separate kernel parameters from
|
||||||
|
> 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.
|
||||||
|
|
||||||
* `fsck.mode=<auto,force,skip>`, default: `auto`, unless built with
|
|
||||||
`configure --enable-fastboot`, in which case the default is `skip`
|
|
||||||
|
|
||||||
* `fsck.repair=<preen,yes,no>`, default: `preen`, unless built with
|
|
||||||
`configure --enable-fsckfix`, in which case the default is `yes`.
|
|
||||||
This configure option also sets `fsck.mode=force`, unless fastboot
|
|
||||||
is selected at the same time. I.e., the `--enable-fastboot` build
|
|
||||||
option overrides the `fsck.mode` default value.
|
|
||||||
|
|
||||||
* `finit.cond=foo[,bar[,baz]]`: set `<boot/foo>` condition, optionally
|
|
||||||
multiple conditions can be set using the same option, separated with a
|
|
||||||
comma. Alternatively, multiple `foo.cond=arg` can be given. Each will
|
|
||||||
result in a `<boot/arg>` condition being set to control the rest of the
|
|
||||||
system bootstrap.
|
|
||||||
|
|
||||||
Very useful for selecting different boot modes, e.g. manufacturing test,
|
|
||||||
firmware upgrade, or [rescue mode][rescue].
|
|
||||||
|
|
||||||
> [!NOTE]
|
|
||||||
> `<boot/...>` conditions cannot be cleared with `initctl`!
|
|
||||||
|
|
||||||
* `finit.config=/path/to/alternative/finit.conf`: override the
|
|
||||||
compile-time bootstrap config file, default:
|
|
||||||
|
|
||||||
./configure --with-config=/etc/finit.conf
|
|
||||||
|
|
||||||
Useful when starting up in various [rescue mode][rescue], factory, or
|
|
||||||
production test setups. Use the top-level configuration file
|
|
||||||
setting `rcsd = "/path/to/finit.d"` to override the default rcS.d
|
|
||||||
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.
|
||||||
|
|
||||||
* `finit.fstab=</path/to/etc/fstab.alternative>`: Tell Finit to use an
|
* `finit.show_status[=bool]`: Control finit boot progress, including
|
||||||
alternate `fstab` to mount the file system from. Remember, this file
|
banner.
|
||||||
must be on the `root=...` file system provided to Finit from the
|
|
||||||
kernel. By default the built-in fstab is used, which itself defaults
|
|
||||||
to `/etc/fstab`, but can be changed at build time with:
|
|
||||||
|
|
||||||
./configure --with-fstab=/path/to/fstab
|
|
||||||
|
|
||||||
It is even possible to disable a built-in default using:
|
|
||||||
|
|
||||||
./configure --without-fstab
|
|
||||||
|
|
||||||
Making `finit.fstab=/path/to/fstab` a *mandatory* command line option.
|
|
||||||
Note, if the command line fstab is missing, Finit falls back to the
|
|
||||||
built-in fstab, and if both are missing, the system treats this as a
|
|
||||||
bad `fsck` and thus calls `sulogin`. If, in turn, `sulogin` is not
|
|
||||||
available on the system, Finit calls reboot, which is also what will
|
|
||||||
happen when a user exits from `sulogin`.
|
|
||||||
|
|
||||||
* `finit.status[=bool]`: Control finit boot progress, including banner.
|
|
||||||
(Used to be `finit.show_status`, which works but is deprecated.)
|
|
||||||
|
|
||||||
* `finit.status_style=<classic,modern>`: Set Finit boot progress style,
|
* `finit.status_style=<classic,modern>`: Set Finit boot progress style,
|
||||||
when enabled.
|
when enabled.
|
||||||
@@ -75,46 +24,27 @@ 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][rescue] instead.
|
`rescue` mode instead.
|
||||||
|
|
||||||
* `loglevel=<0-7>`, sets the kernel's log level, which is more granular
|
|
||||||
than `debug`. Also, when `loglevel=7`, Finit will *not disable*
|
|
||||||
kernel logs to the console. This is very useful when debugging the
|
|
||||||
kernel at system bring-up. Since `loglevel=7` is the same as `debug`
|
|
||||||
this means you have to use `quiet` for a quiet boot, until sysklogd
|
|
||||||
takes over logging of kernel events.
|
|
||||||
|
|
||||||
* `panic=SEC`: By default the kernel does not reboot after a kernel
|
* `panic=SEC`: By default the kernel does not reboot after a kernel
|
||||||
panic. This setting will cause a kernel reboot after SEC seconds.
|
panic. This setting will cause a kernel reboot after SEC seconds.
|
||||||
|
|
||||||
* `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.
|
||||||
|
|
||||||
* `rescue`: Start [rescue/maintenance mode][rescue]. If your system
|
* `rescue`: Start rescue/maintenance mode. If your system comes with
|
||||||
comes with the bundled `sulogin` program (Finit, or from util-linux,
|
the bundled `sulogin` program (Finit, or from util-linux/Busybox),
|
||||||
or Busybox), you will be given a root login to a maintenance shell.
|
you will be given a root login to a maintenance shell. However, if
|
||||||
However, if `sulogin` is missing, the file `/lib/finit/rescue.conf`
|
`sulogin` is missing, the file `/lib/finit/rescue.conf` is read and
|
||||||
is read and the system booted in a limited fallback mode.
|
the system booted in a limited fallback mode. See [config.md][]
|
||||||
|
for more information.
|
||||||
|
|
||||||
This option can be disabled with `configure --without-rescue`
|
* `single`, or `S`: Single user mode, runlevel 1, in Finit. Useful to
|
||||||
|
debug problems with the regular runlevel. All services and TTYs in
|
||||||
**Note:** in this mode `initctl` will not work. Correct the problem
|
`[1]` will be started, so a `tty [1] @console nologin` configuration
|
||||||
and use `reboot -f` to force reboot.
|
|
||||||
|
|
||||||
* `single`, or `S`: Overrides the configured runlevel (default: 2) to go
|
|
||||||
to after bootstrap by forcing it to runlevel 1, this is also known
|
|
||||||
as single user mode. Useful to debug startup problems. All services
|
|
||||||
and TTYs in runlevel 1 will be started, so a `tty` block with
|
|
||||||
`runlevel = "1"`, `device = "@console"`, and `nologin = true`
|
|
||||||
presents you with a root console without login.
|
presents you with a root console without login.
|
||||||
|
|
||||||
* `1-9`, except `6`: override the configured `runlevel`. Like the `S`
|
|
||||||
and `rescue`, giving a single number on the kernel command line tells
|
|
||||||
Finit to ignore any `runlevel` in `/etc/finit.conf` as well as the
|
|
||||||
configure fallback `--with-runlevel=N` setting. Remember, `6` is the
|
|
||||||
reboot runlevel and is not permitted. Any other values are ignored.
|
|
||||||
|
|
||||||
For more on kernel boot parameters, see the man page [bootparam(7)][].
|
For more on kernel boot parameters, see the man page [bootparam(7)][].
|
||||||
|
|
||||||
[rescue]: config/rescue.md
|
[config.md][]: config.md#rescue-mode
|
||||||
[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
|
||||||
|
|||||||
@@ -1,13 +0,0 @@
|
|||||||
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.
|
|
||||||
+63
-202
@@ -1,132 +1,56 @@
|
|||||||
Conditions
|
Finit 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 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"*
|
||||||
|
|
||||||
A condition is named in the `conditions` list of a `service`, `task`, or
|
Conditions are similar in syntax to declaring runlevels per service.
|
||||||
`run` block. The list may hold several, and they are logically AND'ed
|
They are specified within angle brackets `<>` and can be applied to any
|
||||||
|
of the `service`, `task`, or `run` stanza. Multiple conditions may be
|
||||||
|
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. In running text, and in `initctl` output, a condition
|
service to run.
|
||||||
is written inside angle brackets, `<pid/syslogd>`.
|
|
||||||
|
|
||||||
One prefix can be used on a condition:
|
|
||||||
|
|
||||||
- `~` -- propagate reload from this dependency, see below
|
|
||||||
|
|
||||||
The line-based format also accepts a leading `!` on the list, which is
|
|
||||||
not a condition and not a negation. It is a flag on the block, and it
|
|
||||||
means two unrelated things depending on where it sits: a service does
|
|
||||||
not support `SIGHUP` (noreload), or a run/task should not block
|
|
||||||
runlevel changes, i.e. bootstrap. Each of those is its own key here:
|
|
||||||
|
|
||||||
| Line-based | Block format |
|
|
||||||
|---|---|
|
|
||||||
| `<!...>` on a service or sysv | `reload-signal = "none"` |
|
|
||||||
| `<!...>` on a run or task | `required = false` |
|
|
||||||
|
|
||||||
Finit guarantees by default that all run/tasks run (at least) once
|
|
||||||
per runlevel. For most tasks this is a good default, for example
|
|
||||||
checking SSH host keys or loading keymap. However, for conditions
|
|
||||||
that are unlikely to happen it is not. (See example below.)
|
|
||||||
|
|
||||||
### Example
|
### Example
|
||||||
|
|
||||||
service netd {
|
service [2345] <pid/setupd,pid/zebra> /sbin/netd -- Network monitor
|
||||||
description = "Network monitor"
|
|
||||||
runlevel = "2345"
|
|
||||||
conditions = { "pid/setupd", "pid/zebra" }
|
|
||||||
command = "/sbin/netd"
|
|
||||||
}
|
|
||||||
|
|
||||||
In this example the Network monitor daemon `netd` is not started until
|
In this example the Network monitor daemon `netd` is not started until
|
||||||
both the `pid/setupd` *and* `pid/zebra` conditions are satisfied. A
|
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.
|
||||||
|
|
||||||
> [!IMPORTANT]
|
**NOTE:** Conditions also stop services when a condition is no longer
|
||||||
> Conditions also stop services when a condition is no longer asserted.
|
asserted. I.e., if the Zebra process above stops or restarts, netd
|
||||||
> I.e., if the `zebra` process above stops or restarts, `netd` will also
|
will also stop or restart.
|
||||||
> stop or restart.
|
|
||||||
|
|
||||||
Another example is `dropbear`, it does not support `SIGHUP`, but we can
|
|
||||||
also see optional sourcing of arguments from an environment file:
|
|
||||||
|
|
||||||
service dropbear {
|
|
||||||
description = "Dropbear SSH daemon"
|
|
||||||
runlevel = "2345789"
|
|
||||||
reload-signal = "none"
|
|
||||||
envfile = "-/etc/default/dropbear"
|
|
||||||
command = "dropbear -F -R $DROPBEAR_ARGS"
|
|
||||||
}
|
|
||||||
|
|
||||||
Finally, the weird "block runlevel changes" example. Here we see what
|
|
||||||
happens when Finit receives `SIGPWR`, sent from a power daemon like
|
|
||||||
[powstatd(8)][]. A condition is asserted and a user can set up their
|
|
||||||
own task to act on it. We do not want this task to block Finit from
|
|
||||||
moving to the next runlevel after bootstrap, so we set
|
|
||||||
`required = false`:
|
|
||||||
|
|
||||||
task pwrfail {
|
|
||||||
description = "Power failure, shutting down"
|
|
||||||
runlevel = "S0123456789"
|
|
||||||
conditions = { "sys/pwr/fail" }
|
|
||||||
required = false
|
|
||||||
command = "initctl poweroff"
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
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 svc_b {
|
|
||||||
description = "Needs A (barrier)"
|
|
||||||
conditions = { "pid/svc_a" }
|
|
||||||
command = "/sbin/svc_b"
|
|
||||||
}
|
|
||||||
|
|
||||||
service svc_c {
|
|
||||||
description = "Propagate reload from B"
|
|
||||||
conditions = { "~pid/svc_b" }
|
|
||||||
reload-signal = "none"
|
|
||||||
command = "/sbin/svc_c"
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
|
||||||
`reload-signal = "none"`, instead of merely resumed. If `svc_c`
|
|
||||||
supported `SIGHUP`, 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
|
||||||
----------
|
----------
|
||||||
|
|
||||||
Conditions are mainly triggered (asserted) by built-in plugins, e.g.,
|
Conditions are mainly triggered (asserted) by built-in plugins, e.g.,
|
||||||
|
`netlink.so` and `pidfile.so`, see below for built-in conditions. Finit
|
||||||
- `netlink.so`: provides `<net/...>`
|
also supports user-defined conditions, sometimes referred to as static
|
||||||
- `pidfile.so`: provides `<pid/...>`
|
or one-shot conditions. They live in the `<usr/...` namespace and are
|
||||||
- Cmdline `finit.cond=arg`: provides `<boot/arg>`
|
constrained to a flat hierarchy without any sub-directories, unlike the
|
||||||
|
pidfile plugin, for instance.
|
||||||
See below for built-in conditions. Finit also supports user-defined
|
|
||||||
conditions, sometimes referred to as static or one-shot conditions.
|
|
||||||
They live in the `<usr/...>` namespace and are constrained to a flat
|
|
||||||
hierarchy without any sub-directories, unlike the pidfile plugin, for
|
|
||||||
instance.
|
|
||||||
|
|
||||||
User-defined conditions are controlled using the `initctl cond set` and
|
User-defined conditions are controlled using the `initctl cond set` and
|
||||||
`initctl cond clear` commands:
|
`initctl cond clear` commands:
|
||||||
@@ -136,15 +60,9 @@ 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 alarm {
|
|
||||||
description = "Foo alarm"
|
|
||||||
runlevel = "2345"
|
|
||||||
conditions = { "usr/foo" }
|
|
||||||
command = "alarm --arg foo"
|
|
||||||
}
|
|
||||||
|
|
||||||
For convenience, prefixing with `usr/` is allowed, but any other slashes
|
For convenience, prefixing with `usr/` is allowed, but any other slashes
|
||||||
or period characters are disallowed. E.g., to trigger the `Foo alarm`,
|
or period characters are disallowed. E.g., to trigger the `Foo alarm`,
|
||||||
@@ -160,60 +78,24 @@ 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.
|
||||||
|
|
||||||
Static (one-shot) conditions, like `usr/`, never enter the `flux` state.
|
> **Note:** For `pid/` conditions it is expected that services "touch"
|
||||||
|
> or recreate their PID file on `SIGHUP`.
|
||||||
|
|
||||||
> [!IMPORTANT]
|
Static (one-shot) conditions, like `usr/`, never enter the `flux` state.
|
||||||
> 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,
|
|
||||||
> set `reload-signal = "none"` to tell Finit the service does not
|
|
||||||
> support `SIGHUP`.
|
|
||||||
|
|
||||||
|
|
||||||
Built-in Conditions
|
Built-in Conditions
|
||||||
-------------------
|
-------------------
|
||||||
|
|
||||||
Finit comes with a set of plugins for conditions:
|
Finit comes with a set of plugins for conditions: `pidfile`, `netlink`,
|
||||||
|
`sys`, and `usr`. The `pidfile` plugin (recursively) watches `/run/`
|
||||||
- `keventd`: provides `<dev/...>`, `<class/...>`, `<driver/...>`, and
|
(recursively) for PID files created by the monitored services, and sets
|
||||||
`<sys/pwr/...>`
|
a corresponding condition in the `pid/` namespace. Similarly, the
|
||||||
- `devmon` (built-in fallback for `<dev/...>` without keventd)
|
`netlink` plugin provides basic conditions for when an interface is
|
||||||
- `netlink`: provides `<net/...>`
|
brought up/down and when a default route (gateway) is set, in the `net/`
|
||||||
- `pidfile`: provides `<pid/...>`
|
namespace. The `sys` and `usr` plugins monitor are passive condition
|
||||||
- `sys`
|
monitors where the action is provided by `keventd`, signal handlers,
|
||||||
- `usr`
|
and in the case of `usr`, the end-user via the `initctl` tool
|
||||||
|
|
||||||
The `dev/` conditions are provided by `keventd`, the built-in device
|
|
||||||
manager. When keventd creates a device node in `/dev`, it also asserts
|
|
||||||
the corresponding `dev/` condition. When a device is removed, the
|
|
||||||
condition is cleared. If keventd is not in use (an external device
|
|
||||||
manager like udevd is used instead), the `devmon` built-in provides the
|
|
||||||
same conditions by monitoring `/dev` and `/dev/dir` with inotify.
|
|
||||||
|
|
||||||
keventd also asserts `class/<subsystem>/<name>` for devices that have
|
|
||||||
no `/dev` node, e.g. LEDs and DSA switch ports, and `driver/<name>`
|
|
||||||
while a driver is bound to at least one device. See
|
|
||||||
[keventd](keventd.md) for details.
|
|
||||||
|
|
||||||
The `pidfile` plugin recursively watches `/run/` for PID files created
|
|
||||||
by the monitored services, and sets a corresponding condition in the
|
|
||||||
`pid/` namespace.
|
|
||||||
|
|
||||||
Similarly, the `netlink` plugin provides basic conditions for when an
|
|
||||||
interface is brought up/down and when a default route (gateway) is set,
|
|
||||||
in the `net/` namespace.
|
|
||||||
|
|
||||||
The `sys` and `usr` plugins are passive condition monitors where
|
|
||||||
the action is provided by `keventd`, signal handlers, and in the case of
|
|
||||||
`usr`, the end-user via the `initctl` tool.
|
|
||||||
|
|
||||||
Additionally, the various states of a run/task/sysv/service can also be
|
|
||||||
used as conditions, the image above shows the state names. The syntax
|
|
||||||
for a `service` type process: `<service/foo/STATE>`. The other types,
|
|
||||||
in particular run/task/sysv, there are the additional states `success`
|
|
||||||
and `failure`.
|
|
||||||
|
|
||||||
With the example listed above, finit does not start the `/sbin/netd`
|
With the example listed above, finit does not start the `/sbin/netd`
|
||||||
daemon until `setupd` and `zebra` has started *and* created their PID
|
daemon until `setupd` and `zebra` has started *and* created their PID
|
||||||
@@ -232,37 +114,30 @@ Built-in conditions:
|
|||||||
- `net/<IFNAME>/exist`
|
- `net/<IFNAME>/exist`
|
||||||
- `net/<IFNAME>/up`
|
- `net/<IFNAME>/up`
|
||||||
- `net/<IFNAME>/running`
|
- `net/<IFNAME>/running`
|
||||||
- `service/<NAME[:ID]>/<STATE>`
|
|
||||||
- `{run, task, sysv}/<NAME[:ID]>/{<STATE>, success, failure}`
|
|
||||||
- `sys/pwr/ac`
|
- `sys/pwr/ac`
|
||||||
- `sys/pwr/fail`
|
- `sys/pwr/fail`
|
||||||
- `sys/key/ctrlaltdel`
|
- `sys/key/ctrlaltdel`
|
||||||
- `usr/foo`
|
- `usr/foo`
|
||||||
- `boot/arg`
|
|
||||||
- `dev/node` and `dev/dir/node`
|
|
||||||
- `class/<subsystem>/<name>`
|
|
||||||
- `driver/<name>`
|
|
||||||
|
|
||||||
> [!NOTE]
|
**Note:** `up` means administratively up, the interface flag `IFF_UP`.
|
||||||
> Here, `up` means administratively up, the interface flag `IFF_UP`.
|
`running` is the `IFF_RUNNING` flag, meaning operatively up. The
|
||||||
> `running` is the `IFF_RUNNING` flag, meaning operatively up. The
|
difference is that `running` tells if the NIC has link.
|
||||||
> difference is that `running` tells if the NIC has link.
|
|
||||||
|
|
||||||
|
|
||||||
Composition
|
Composition
|
||||||
-----------
|
-----------
|
||||||
|
|
||||||
The `pid/` conditions are generated by the Finit `pidfile.so` plugin and
|
The `pid/` conditions are generated by the Finit `pidfile.so` plugin and
|
||||||
composed from a service's block title and its `:id`. By default the
|
composed from a service's `name:` and `:id`. By default the basename of
|
||||||
basename of the daemon and the empty string.
|
the daemon and the empty string.
|
||||||
|
|
||||||
| **service** | **condition** |
|
| **service** | **condition** |
|
||||||
|-------------------------------------------------------------------|------------------|
|
|----------------------------------------------------|------------------|
|
||||||
| `service { command = "/sbin/foo" }` | pid/foo |
|
| /sbin/foo | pid/foo |
|
||||||
| `service { command = "/sbin/bar -p /run/baz.pid" }` | pid/bar |
|
| /sbin/bar -p /run/baz.pid | pid/bar |
|
||||||
| `service lxc:foo { command = "lxc-start -n foo -p /run/lxc/foo.pid" }` | pid/lxc:foo |
|
| name:lxc :foo lxc-start -n foo -p /run/lxc/foo.pid | pid/lxc:foo |
|
||||||
| `service { command = "/usr/bin/dbus-daemon" }` | pid/dbus-daemon |
|
| /usr/bin/dbus-daemon | pid/dbus-daemon |
|
||||||
| `service dropbear:222 { command = "dropbear -p 222" }` | pid/dropbear:222 |
|
| :222 dropbear -p 222 | pid/dropbear:222 |
|
||||||
|
|
||||||
The condition is asserted when `pidfile.so` receives an inotify event
|
The condition is asserted when `pidfile.so` receives an inotify event
|
||||||
for a file matching `/run/*.pid`, `/run/**/*.pid`, or `/run/**/pid`,
|
for a file matching `/run/*.pid`, `/run/**/*.pid`, or `/run/**/pid`,
|
||||||
@@ -272,19 +147,14 @@ 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 setting `pidfile` and `pidfile-create` in the
|
can be worked around by using the `pid:/path/to/file.pid` syntax in
|
||||||
service block 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]
|
> **Note:** in versions of Finit prior to v4, the PID conditions were
|
||||||
> In versions of Finit prior to v4, the PID conditions were called 'svc'
|
> called 'svc' conditions, and they were far more complex.
|
||||||
> conditions, and they were far more complex.
|
|
||||||
|
|
||||||
|
|
||||||
Debugging
|
Debugging
|
||||||
@@ -293,7 +163,7 @@ Debugging
|
|||||||
If a service is not being started as it should, the problem might be
|
If a service is not being started as it should, the problem might be
|
||||||
that one of its conditions is not in the expected state. Use the
|
that one of its conditions is not in the expected state. Use the
|
||||||
command `initctl status` to inspect service status. Services in the
|
command `initctl status` to inspect service status. Services in the
|
||||||
`waiting` state are pending a condition.
|
`ready` state are pending a condition.
|
||||||
|
|
||||||
In that situation, running `initctl cond show` reveals which of the
|
In that situation, running `initctl cond show` reveals which of the
|
||||||
conditions that are not satisfied. Listed as `off` below.
|
conditions that are not satisfied. Listed as `off` below.
|
||||||
@@ -347,8 +217,6 @@ 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
|
||||||
@@ -359,14 +227,7 @@ 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 if it has
|
|
||||||
`reload-signal = "none"`, 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
|
||||||
to do this, see `plugins/pidfile.c`.
|
to do this, see `plugins/pidfile.c`.
|
||||||
|
|
||||||
[powstatd(8)]: https://manpages.ubuntu.com/manpages/trusty/en/man8/powstatd.8.html
|
|
||||||
|
|||||||
+743
@@ -0,0 +1,743 @@
|
|||||||
|
Configuration
|
||||||
|
=============
|
||||||
|
|
||||||
|
* [Introduction](#introduction)
|
||||||
|
* [Service Environment](#service-environment)
|
||||||
|
* [Service Wrapper Scripts](#service-wrapper-scripts)
|
||||||
|
* [Cgroups](#cgroups)
|
||||||
|
* [Configuration File Syntax](#configuration-file-syntax)
|
||||||
|
* [Hostname](#hostname)
|
||||||
|
* [Kernel Modules](#kernel-modules)
|
||||||
|
* [Networking](#networking)
|
||||||
|
* [Resource Limits](#resource-limits)
|
||||||
|
* [Runlevels](#runlevels)
|
||||||
|
* [One-shot Commands (sequence)](#one-shot-commands--sequence-)
|
||||||
|
* [One-shot Commands (parallel)](#one-shot-commands--parallel-)
|
||||||
|
* [SysV Init Scripts](#sysv-init-scripts)
|
||||||
|
* [Services](#services)
|
||||||
|
* [Run-parts Scripts](#run-parts-scripts)
|
||||||
|
* [Including Finit Configs](#including-finit-configs)
|
||||||
|
* [General Logging](#general-logging)
|
||||||
|
* [TTYs and Consoles](#ttys-and-consoles)
|
||||||
|
* [Non-privileged Services](#non-privileged-services)
|
||||||
|
* [Redirecting Output](#redirecting-output)
|
||||||
|
* [Rescue Mode](#rescue-mode)
|
||||||
|
* [Limitations](#limitations)
|
||||||
|
* [/etc/finit.conf](#etcfinitconf)
|
||||||
|
* [/etc/finit.d](#etcfinitd)
|
||||||
|
* [Watchdog](#watchdog)
|
||||||
|
* [keventd](#keventd)
|
||||||
|
|
||||||
|
|
||||||
|
Introduction
|
||||||
|
------------
|
||||||
|
|
||||||
|
Finit can be configured using only the original `/etc/finit.conf` file
|
||||||
|
or in combination with `/etc/finit.d/*.conf`. Useful for package-based
|
||||||
|
Linux distributions -- each package can provide its own "script" file.
|
||||||
|
|
||||||
|
- `/etc/finit.conf`: main configuration file
|
||||||
|
- `/etc/finit.d/*.conf`: snippets, usually one service per file
|
||||||
|
|
||||||
|
Not all configuration directives are available in `/etc/finit.d/*.conf`
|
||||||
|
and some directives are only available at [bootstrap][], runlevel `S`,
|
||||||
|
see the section [Limitations](#limitations) below for details.
|
||||||
|
|
||||||
|
To add a new service, drop a `.conf` file in `/etc/finit.d` and run
|
||||||
|
`initctl reload`. (It is also possible to `SIGHUP` to 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 handle any and all
|
||||||
|
conditions and dependencies between services automatically.
|
||||||
|
|
||||||
|
It is also possible to drop `.conf` files in `/etc/finit.d/available/`
|
||||||
|
and use `initctl enable` to enable a service `.conf` file. This may be
|
||||||
|
useful in particular to Linux distributions that may want to install all
|
||||||
|
files for a package and let the user decide when to enable a service.
|
||||||
|
|
||||||
|
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).
|
||||||
|
|
||||||
|
> When running <kbd>make install</kbd> no default `/etc/finit.conf` is
|
||||||
|
> installed since system requirements differ too much. There are some
|
||||||
|
> examples in the `contrib/` directory, which can be used as a base.
|
||||||
|
|
||||||
|
|
||||||
|
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 `-` 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.
|
||||||
|
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
|
||||||
|
Cgroups
|
||||||
|
-------
|
||||||
|
|
||||||
|
There are three major cgroup configuration directives:
|
||||||
|
|
||||||
|
1. Global top-level group: init, system, user, or a custom group
|
||||||
|
2. Selecting a top-level group for a set of run/task/services
|
||||||
|
3. Per run/task/service limits
|
||||||
|
|
||||||
|
Top-level group configuration.
|
||||||
|
|
||||||
|
# Top-level cgroups and their default settings. All groups mandatory
|
||||||
|
# but more can be added, max 8 groups in total currently. The cgroup
|
||||||
|
# 'root' is also available, reserved for RT processes. Settings are
|
||||||
|
# as-is, only one shorthand 'mem.' exists, other than that it's the
|
||||||
|
# cgroup v2 controller default names.
|
||||||
|
cgroup init cpu.weight:100
|
||||||
|
cgroup user cpu.weight:100
|
||||||
|
cgroup system cpu.weight:9800
|
||||||
|
|
||||||
|
Adding an extra cgroup `maint/` will require you to adjust the weight of
|
||||||
|
the above three. We leave `init/` and `user/` as-is reducing weight of
|
||||||
|
`system/` to 9700.
|
||||||
|
|
||||||
|
cgroup system cpu.weight:9700
|
||||||
|
|
||||||
|
# Example extra cgroup 'maint'
|
||||||
|
cgroup maint cpu.weight:100
|
||||||
|
|
||||||
|
By default, the `system/` cgroup is selected for almost everything. The
|
||||||
|
`init/` cgroup is reserved for PID 1 itself and its closest relatives.
|
||||||
|
The `user/` cgroup is for local TTY logins spawned by getty.
|
||||||
|
|
||||||
|
To select a different top-level cgroup, e.g. `maint/`, one can either
|
||||||
|
define it for a group of run/task/service directives in a `.conf` or per
|
||||||
|
each stanza:
|
||||||
|
|
||||||
|
cgroup.maint
|
||||||
|
service [...] <...> /path/to/foo args -- description
|
||||||
|
service [...] <...> /path/to/bar args -- description
|
||||||
|
|
||||||
|
or
|
||||||
|
|
||||||
|
service [...] <...> cgroup.maint /path/to/foo args -- description
|
||||||
|
|
||||||
|
The latter form also allows per-stanza limits on the form:
|
||||||
|
|
||||||
|
service [...] <...> cgroup.maint:cpu.max:10000,mem.max:655360 /path/to/foo args -- description
|
||||||
|
|
||||||
|
Notice the comma separation and the `mem.` exception to the rule: every
|
||||||
|
cgroup setting maps directly to cgroup v2 syntax. I.e., `cpu.max` maps
|
||||||
|
to the file `/sys/fs/cgroup/maint/foo/cpu.max`. There is no filtering,
|
||||||
|
except for expanding the shorthand `mem.` to `memory.`, if the file is
|
||||||
|
not available, either the cgroup controller is not available in your
|
||||||
|
Linux kernel, or the name is misspelled.
|
||||||
|
|
||||||
|
> Linux cgroups and details surrounding values are not explained in the
|
||||||
|
> Finit documentation. The Linux admin-guide cover this well:
|
||||||
|
> <https://www.kernel.org/doc/html/latest/admin-guide/cgroup-v2.html>
|
||||||
|
|
||||||
|
|
||||||
|
Configuration File Syntax
|
||||||
|
-------------------------
|
||||||
|
|
||||||
|
### 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][]).
|
||||||
|
|
||||||
|
|
||||||
|
### 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][]).
|
||||||
|
|
||||||
|
|
||||||
|
### Resource Limits
|
||||||
|
|
||||||
|
**Syntax:** `rlimit [hard|soft] RESOURCE <LIMIT|unlimited>`
|
||||||
|
|
||||||
|
Set the hard or soft limit for a resource, or both if that argument is
|
||||||
|
omitted. `RESOURCE` is the lower-case `RLIMIT_` string constants from
|
||||||
|
`setrlimit(2)`, without prefix. E.g. to set `RLIMIT_CPU`, use `cpu`.
|
||||||
|
|
||||||
|
LIMIT is an integer that depends on the resource being modified, see
|
||||||
|
the man page, or the kernel `/proc/PID/limits` file, for details.
|
||||||
|
Finit versions before v3.1 used `infinity` for `unlimited`, which is
|
||||||
|
still supported, albeit deprecated.
|
||||||
|
|
||||||
|
# No process is allowed more than 8MB of address space
|
||||||
|
rlimit hard as 8388608
|
||||||
|
|
||||||
|
# Core dumps may be arbitrarily large
|
||||||
|
rlimit soft core infinity
|
||||||
|
|
||||||
|
# CPU limit for all services, soft & hard = 10 sec
|
||||||
|
rlimit cpu 10
|
||||||
|
|
||||||
|
`rlimit` can be set globally, in `/etc/finit.conf`, or locally per
|
||||||
|
each `/etc/finit.d/*.conf` read. I.e., a set of task/run/service
|
||||||
|
stanzas can share the same rlimits if they are in the same .conf.
|
||||||
|
|
||||||
|
|
||||||
|
### Runlevels
|
||||||
|
|
||||||
|
**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.
|
||||||
|
|
||||||
|
Default: 2
|
||||||
|
|
||||||
|
> **Note:** only read and executed in runlevel S ([bootstrap][]).
|
||||||
|
|
||||||
|
|
||||||
|
### One-shot Commands (sequence)
|
||||||
|
|
||||||
|
**Syntax:** `run [LVLS] <COND> /path/to/cmd ARGS -- Optional description`
|
||||||
|
|
||||||
|
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. Highly useful if true serialization is needed.
|
||||||
|
|
||||||
|
> `<COND>` is described in the [Services](#services) section.
|
||||||
|
|
||||||
|
|
||||||
|
### One-shot Commands (parallel)
|
||||||
|
|
||||||
|
**Syntax:** `task [LVLS] <COND> /path/to/cmd ARGS -- Optional description`
|
||||||
|
|
||||||
|
One-shot like 'run', but starts in parallel with the next command.
|
||||||
|
|
||||||
|
Both `run` and `task` commands are run in a shell, so pipes and
|
||||||
|
redirects can be freely used:
|
||||||
|
|
||||||
|
task [s] echo "foo" | cat >/tmp/bar
|
||||||
|
|
||||||
|
> `<COND>` is described in the [Services](#services) section.
|
||||||
|
|
||||||
|
|
||||||
|
### SysV Init Scripts
|
||||||
|
|
||||||
|
**Syntax:** `sysv [LVLS] <COND> /path/to/init-script -- Optional description`
|
||||||
|
|
||||||
|
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
|
||||||
|
re-use 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`.
|
||||||
|
|
||||||
|
> `<COND>` is described in the [Services](#services) section.
|
||||||
|
|
||||||
|
|
||||||
|
### 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 controling this are configurable, see the options
|
||||||
|
below.
|
||||||
|
|
||||||
|
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 called forking
|
||||||
|
services and are supported using the same syntax as forking `sysv`
|
||||||
|
services, using the `pid:!/path/to/pidfile.pid` syntax.
|
||||||
|
|
||||||
|
**Example:**
|
||||||
|
|
||||||
|
In the case of `ospfd` (below), we omit the `-d` flag (daemonize) to
|
||||||
|
prevent it from forking to the background:
|
||||||
|
|
||||||
|
service [2345] <pid/zebra> /sbin/ospfd -- OSPF daemon
|
||||||
|
|
||||||
|
`[2345]` denote the runlevels `ospfd` is allowed to run in, they are
|
||||||
|
optional and default to level 2-5 if omitted.
|
||||||
|
|
||||||
|
`<...>` is the condition for starting `ospfd`. In this example Finit
|
||||||
|
waits for another service, `zebra`, to have created its PID file in
|
||||||
|
`/var/run/quagga/zebra.pid` before starting `ospfd`. Finit watches
|
||||||
|
*all* files in `/var/run`, for each file named `*.pid`, or `*/pid`,
|
||||||
|
Finit opens it and find the matching `NAME:ID` using the PID.
|
||||||
|
|
||||||
|
Some services do not maintain a PID file and rather than patching each
|
||||||
|
application Finit provides a workaround. A `pid` keyword can be set
|
||||||
|
to have Finit automatically create (when starting) and later remove
|
||||||
|
(when stopping) the PID file. The file is created in the `/var/run`
|
||||||
|
directory using the `basename(1)` of the service. The default can be
|
||||||
|
modified with an optional `pid:`-argument:
|
||||||
|
|
||||||
|
pid[:[/path/to/]filename[.pid]]
|
||||||
|
|
||||||
|
For example, by adding `pid:/run/foo.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>`.
|
||||||
|
|
||||||
|
> For a detailed description of conditions, and how to debug them,
|
||||||
|
> see the [Finit Conditions](conditions.md) document.
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
The name of a service, shown by the `initctl` tool, defaults to the
|
||||||
|
basename of the service executable. It can be changed with the
|
||||||
|
optional `name` argument:
|
||||||
|
|
||||||
|
name:<service-name>
|
||||||
|
|
||||||
|
As mentioned previously, services are automatically restarted, this is
|
||||||
|
configurable with the following options:
|
||||||
|
|
||||||
|
* `restart:NUM` -- number of times Finit tries to restart a crashing
|
||||||
|
service, default: 10. When this limit is reached the service is
|
||||||
|
marked *crashed* and must be restarted manually with `initctl`
|
||||||
|
* `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
|
||||||
|
* `norestart` -- dont restart on failures, same as `restart:0`
|
||||||
|
* `oncrash:reboot` -- when all retries have failed, and the service
|
||||||
|
has *crashed*, if this option is set the system is rebooted.
|
||||||
|
Note, future releases may include other `oncrash:` actions
|
||||||
|
|
||||||
|
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. If the process has not
|
||||||
|
been collected within 3 seconds, Finit sends `SIGKILL`. To halt the
|
||||||
|
process using a different signal, use the option `halt:SIGNAL`, e.g.,
|
||||||
|
`halt:SIGPWR`. To change the delay between your halt signal and KILL,
|
||||||
|
use the option `kill:SEC`, e.g., `kill:10` to wait 10 seconds before
|
||||||
|
sending `SIGKILL`.
|
||||||
|
|
||||||
|
Services support `pre:script` and `post:script` actions as well. These
|
||||||
|
run as the same `@USER:GROUP` as the service itself, with any `env:file`
|
||||||
|
sourced. The scripts must use an absolute path, but are executed from
|
||||||
|
the `$HOME` of the given user. The scripts are not called with any
|
||||||
|
argument (currently), but both get the `SERVICE_IDENT=foo` environment
|
||||||
|
variable set. Here `foo` denotes the identity of the service, which if
|
||||||
|
there are multiple services named `foo`, may be `foo:1`, or any unique
|
||||||
|
identifier specified in the .conf file. The `post:script` is called
|
||||||
|
with an additional set of environment variables:
|
||||||
|
|
||||||
|
- `EXIT_CODE=[exited,signal]`: set to one of `exited` or `signal`
|
||||||
|
- `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
|
||||||
|
|
||||||
|
The scripts have a default execution time of 3 seconds before they are
|
||||||
|
SIGKILLed, this can be adjusted using the above `kill:SEC` syntax.
|
||||||
|
|
||||||
|
> **Note:** the `pre:script` _must_ be idempotent, because a service
|
||||||
|
> can transition between READY and HALTED states any number
|
||||||
|
> of times before going to RUNNING.
|
||||||
|
|
||||||
|
|
||||||
|
### Run-parts Scripts
|
||||||
|
|
||||||
|
**Syntax:** `runparts <DIR>`
|
||||||
|
|
||||||
|
Call [run-parts(8)][] on `DIR` to run start scripts. All executable
|
||||||
|
files, or scripts, in the directory are called, in alphabetic order.
|
||||||
|
The scripts in this directory are executed at the very end of runlevel
|
||||||
|
`S`, [bootstrap][].
|
||||||
|
|
||||||
|
It can be beneficial to use `S01name`, `S02othername`, etc. if there
|
||||||
|
is a dependency order between the scripts. Symlinks to existing
|
||||||
|
daemons can talso be used, but make sure they daemonize by default.
|
||||||
|
|
||||||
|
Similar to the `/etc/rc.local` shell script, make sure that all your
|
||||||
|
services and programs either terminate or start in the background or
|
||||||
|
you will block Finit.
|
||||||
|
|
||||||
|
> **Note:** only read and executed in runlevel S ([bootstrap][]).
|
||||||
|
|
||||||
|
[run-parts(8)]: http://manpages.debian.org/cgi-bin/man.cgi?query=run-parts
|
||||||
|
|
||||||
|
|
||||||
|
### Including Finit Configs
|
||||||
|
|
||||||
|
**Syntax:** `include <CONF>`
|
||||||
|
|
||||||
|
Include another configuration file. Absolute path required.
|
||||||
|
|
||||||
|
|
||||||
|
### 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.
|
||||||
|
|
||||||
|
### 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-mode) 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
|
||||||
|
|
||||||
|
|
||||||
|
### Non-privileged Services
|
||||||
|
|
||||||
|
Every `run`, `task`, or `service` can also list the privileges the
|
||||||
|
`/path/to/cmd` should be executed with. Prefix the command with
|
||||||
|
`@USR[:GRP]`, group is optional, like this:
|
||||||
|
|
||||||
|
run [2345] @joe:users logger "Hello world"
|
||||||
|
|
||||||
|
For multiple instances of the same command, e.g. a DHCP client or
|
||||||
|
multiple web servers, add `:ID` somewhere between the `run`, `task`,
|
||||||
|
`service` keyword and the command, like this:
|
||||||
|
|
||||||
|
service :80 [2345] httpd -f -h /http -p 80 -- Web server
|
||||||
|
service :8080[2345] httpd -f -h /http -p 8080 -- Old web server
|
||||||
|
|
||||||
|
Without the `:ID` to the service the latter will overwrite the former
|
||||||
|
and only the old web server would be started and supervised.
|
||||||
|
|
||||||
|
|
||||||
|
### 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
|
||||||
|
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
The rescue mode comes in two flavors; *traditional* and *fallback*.
|
||||||
|
|
||||||
|
|
||||||
|
### Traditional
|
||||||
|
|
||||||
|
This is what most users expect. A very early maintenance login prompt,
|
||||||
|
served by the bundled `/libexec/finit/sulogin` program, or the standard
|
||||||
|
`sulogin` from util-linux or BusyBox is searched for in the UNIX default
|
||||||
|
`$PATH`. If a successful login is made, or the user exits (Ctrl-D), the
|
||||||
|
rescue mode is ended and the system boots up normally.
|
||||||
|
|
||||||
|
> **Note:** if the user (UID 0 and GID 0) does not have a password, or
|
||||||
|
> __the account is locked__, the user is presented with a password-less
|
||||||
|
> `"Press enter to enter maintenance mode."`, prompt which opens up a
|
||||||
|
> root shell.
|
||||||
|
|
||||||
|
|
||||||
|
### 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.
|
||||||
|
|
||||||
|
|
||||||
|
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`.
|
||||||
|
|
||||||
|
> **Note:** The `/etc/finit.d` directory was previously the default
|
||||||
|
> Finit [runparts](#run-parts-scripts) directory. Finit no
|
||||||
|
> longer has a default `runparts`, make sure to update your
|
||||||
|
> setup, or the finit configuration, accordingly.
|
||||||
|
|
||||||
|
|
||||||
|
Watchdog
|
||||||
|
--------
|
||||||
|
|
||||||
|
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. See [bootstrap][] for
|
||||||
|
details. This delegation is to ensure that the system is rebooted by a
|
||||||
|
hardware watchdog timer -- on many embedded systems this is crucial to
|
||||||
|
ensure all circuits on the board are properly reset for the next boot,
|
||||||
|
in effect ensuring the system works the same after both a power-on and
|
||||||
|
reboot event.
|
||||||
|
|
||||||
|
The delegation is performed at the very last steps of system shutdown,
|
||||||
|
if reboot has been selected and an elected watchdog is known, first a
|
||||||
|
`SIGPWR` is sent to advise watchdogd of the pending reboot. Then, when
|
||||||
|
the necessary steps of preparing the system for shutdown (umount etc.)
|
||||||
|
are completed, Finit sends `SIGTERM` to watchdogd and puts itself in a
|
||||||
|
10 sec timeout loop waiting for the WDT to reset the board. If a reset
|
||||||
|
is not done before the timeout, Finit falls back to`reboot(RB_AUTOBOOT)`
|
||||||
|
which tells the kernel to do the reboot.
|
||||||
|
|
||||||
|
An external watchdog service can also be used. The more advanced cousin
|
||||||
|
[watchdogd](https://github.com/troglobit/watchdogd/) is the recommended
|
||||||
|
option here. It can register itself with Finit using the same IPC as
|
||||||
|
`initctl`. If the bundled watchdogd is running a hand-over takes place,
|
||||||
|
so it's safe to have both services installed on a system. For the
|
||||||
|
hand-over to work it requires that the WDT driver supports the safe exit
|
||||||
|
functionality where `"V"` is written to the device before closing the
|
||||||
|
device descriptor. If the kernel driver has been built without this,
|
||||||
|
the only option is to remove `/libexec/finit/watchdogd` or build without
|
||||||
|
it at configure time.
|
||||||
|
|
||||||
|
[bootstrap]: bootstrap.md
|
||||||
|
|
||||||
|
|
||||||
|
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 `./configuure --with-keventd`. The bundled
|
||||||
|
contrib build scripts for Debian, Alpine, and Void have this enabled.
|
||||||
|
|
||||||
|
This daemon is planned to be extended with monitoring of other uevents,
|
||||||
|
patches and ideas are welcome in the issue tracker.
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
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
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
index.md
|
|
||||||
@@ -1,201 +0,0 @@
|
|||||||
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 with the `capabilities` key, alias `caps`:
|
|
||||||
|
|
||||||
```conf
|
|
||||||
service nginx {
|
|
||||||
description = "Web server"
|
|
||||||
runlevel = "2345"
|
|
||||||
user = "www-data"
|
|
||||||
group = "www-data"
|
|
||||||
capabilities = { "^cap_net_bind_service" }
|
|
||||||
command = "/usr/sbin/nginx -g 'daemon off;'"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
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
|
|
||||||
capabilities = { "^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 webserver {
|
|
||||||
runlevel = "2345"
|
|
||||||
user = "www-data"
|
|
||||||
group = "www-data"
|
|
||||||
capabilities = { "^cap_net_bind_service" }
|
|
||||||
command = "/usr/sbin/nginx -g 'daemon off;'"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Network Monitoring (Raw Sockets)
|
|
||||||
|
|
||||||
Allow packet capture without root privileges:
|
|
||||||
|
|
||||||
```conf
|
|
||||||
service tcpdump {
|
|
||||||
runlevel = "2345"
|
|
||||||
user = "tcpdump"
|
|
||||||
capabilities = { "^cap_net_raw", "^cap_net_admin" }
|
|
||||||
command = "/usr/sbin/tcpdump -i eth0 -w /var/log/capture.pcap"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### NTP Daemon (System Time)
|
|
||||||
|
|
||||||
Allow time synchronization without full root:
|
|
||||||
|
|
||||||
```conf
|
|
||||||
service ntpd {
|
|
||||||
runlevel = "2345"
|
|
||||||
user = "ntp"
|
|
||||||
capabilities = { "^cap_sys_time", "^cap_sys_nice" }
|
|
||||||
command = "/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` setting is **required** for `capabilities` to take effect
|
|
||||||
- For ambient capabilities (`^`), use a non-root user (not `"root"`)
|
|
||||||
- Example: `user = "www-data"`, `user = "nginx"`, `user = "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`, otherwise a `capabilities` list is
|
|
||||||
ignored, with a warning
|
|
||||||
|
|
||||||
## Limitations
|
|
||||||
|
|
||||||
- `capabilities` requires `user` to be set for it to take effect
|
|
||||||
- Without `user`, the service runs as root with full capabilities and
|
|
||||||
the `capabilities` list is silently ignored
|
|
||||||
- You can use `user = "root"`, but see below about ambient capabilities
|
|
||||||
- For ambient capabilities (`^`, recommended), the user **must be non-root**
|
|
||||||
- Using `user = "root"` with `^` capabilities will not work effectively, as ambient
|
|
||||||
capabilities are only added to the effective set when euid ≠ 0
|
|
||||||
- Use inheritable (`%`) or bounding (`!`) capabilities with `user = "root"` if needed
|
|
||||||
- Finit warns about this when reading the .conf file:
|
|
||||||
|
|
||||||
nginx: ambient capabilities ('^') have no effect as root, use a
|
|
||||||
non-root user, or '%' and '!' entries
|
|
||||||
- Services without `capabilities` use standard privilege dropping:
|
|
||||||
- Services with a non-root `user` 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
|
|
||||||
@@ -1,244 +0,0 @@
|
|||||||
Finit has two `cgroup` blocks for controlling resource allocation:
|
|
||||||
|
|
||||||
1. **Top-level definition**, at file scope: declares a group such as
|
|
||||||
`init`, `system`, or `user`, and its default settings.
|
|
||||||
|
|
||||||
cgroup system { cpu.weight = 9700 }
|
|
||||||
|
|
||||||
2. **Joining a group**, inside a service block: names the group this
|
|
||||||
service runs in, and may override settings for itself alone.
|
|
||||||
|
|
||||||
service foo {
|
|
||||||
cgroup maint { memory.max = 1G }
|
|
||||||
command = "/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 the early boot helpers Finit drives
|
|
||||||
itself, like udev and mdev. PID 1 runs in the root cgroup, since a
|
|
||||||
cgroup holding processes cannot delegate controllers to its children.
|
|
||||||
The `user/` cgroup is for local TTY logins spawned by getty.
|
|
||||||
|
|
||||||
Joining a Cgroup
|
|
||||||
----------------
|
|
||||||
|
|
||||||
**Syntax:** `cgroup NAME { settings }` (inside a service block)
|
|
||||||
|
|
||||||
Every block says which group it joins, by name. An empty block joins
|
|
||||||
without changing anything:
|
|
||||||
|
|
||||||
service foo {
|
|
||||||
cgroup maint {}
|
|
||||||
command = "/path/to/foo args"
|
|
||||||
}
|
|
||||||
|
|
||||||
service bar {
|
|
||||||
cgroup maint {}
|
|
||||||
command = "/path/to/bar args"
|
|
||||||
}
|
|
||||||
|
|
||||||
Both services run in the `maint/` cgroup. Settings inside the block
|
|
||||||
apply to that service alone:
|
|
||||||
|
|
||||||
service foo {
|
|
||||||
cgroup maint {
|
|
||||||
cpu.max = 10000
|
|
||||||
memory.max = 655360
|
|
||||||
}
|
|
||||||
command = "/path/to/foo args"
|
|
||||||
}
|
|
||||||
|
|
||||||
> [!NOTE]
|
|
||||||
> The legacy format has a standalone `cgroup.NAME` line that selects a
|
|
||||||
> group for every stanza following it in the file, and a `cgroup:options`
|
|
||||||
> form that applies settings to whichever group is current without
|
|
||||||
> naming it. Neither has an equivalent here, by design: a block that
|
|
||||||
> joins a group says so itself, so the group cannot depend on what came
|
|
||||||
> earlier in the file.
|
|
||||||
|
|
||||||
Every cgroup setting maps directly to cgroup v2 syntax, so `cpu.max`
|
|
||||||
maps to the file `/sys/fs/cgroup/maint/foo/cpu.max`. There is no
|
|
||||||
filtering, the one exception being the shorthand `mem.`, which expands
|
|
||||||
to `memory.`. If the file is not available, either the controller is
|
|
||||||
missing from 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), set `name`
|
|
||||||
inside the cgroup block:
|
|
||||||
|
|
||||||
service udevd {
|
|
||||||
description = "Device event daemon"
|
|
||||||
cgroup system { name = "udevd" }
|
|
||||||
command = "/lib/systemd/systemd-udevd"
|
|
||||||
}
|
|
||||||
|
|
||||||
This creates the cgroup at `/sys/fs/cgroup/system/udevd/` instead.
|
|
||||||
|
|
||||||
`name` combines with any other setting:
|
|
||||||
|
|
||||||
service udevd {
|
|
||||||
description = "Device event daemon"
|
|
||||||
cgroup system {
|
|
||||||
name = "udevd"
|
|
||||||
cpu.max = 10000
|
|
||||||
}
|
|
||||||
command = "/lib/systemd/systemd-udevd"
|
|
||||||
}
|
|
||||||
|
|
||||||
Or with delegation:
|
|
||||||
|
|
||||||
service podman {
|
|
||||||
description = "Podman API"
|
|
||||||
runlevel = "2345"
|
|
||||||
user = "podman"
|
|
||||||
group = "podman"
|
|
||||||
cgroup containers {
|
|
||||||
name = "podman"
|
|
||||||
delegate = true
|
|
||||||
memory.max = 4G
|
|
||||||
}
|
|
||||||
command = "/usr/bin/podman system service"
|
|
||||||
}
|
|
||||||
|
|
||||||
A daemon using `SCHED_RR` currently needs to run outside the default
|
|
||||||
cgroups.
|
|
||||||
|
|
||||||
service rt {
|
|
||||||
description = "Real-Time process"
|
|
||||||
cgroup root {}
|
|
||||||
command = "/path/to/daemon arg"
|
|
||||||
}
|
|
||||||
|
|
||||||
Cgroup Delegation
|
|
||||||
-----------------
|
|
||||||
|
|
||||||
For services that need to create their own child cgroups (container runtimes
|
|
||||||
like Docker, Podman, systemd-nspawn, LXC), set `delegate`:
|
|
||||||
|
|
||||||
service dockerd {
|
|
||||||
description = "Docker daemon"
|
|
||||||
runlevel = "2345"
|
|
||||||
user = "dockerd"
|
|
||||||
group = "dockerd"
|
|
||||||
cgroup system { delegate = true }
|
|
||||||
command = "/usr/bin/dockerd"
|
|
||||||
}
|
|
||||||
|
|
||||||
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` and `group` for proper ownership
|
|
||||||
- Controllers are delegated from the parent cgroup
|
|
||||||
|
|
||||||
**Example with additional config:**
|
|
||||||
|
|
||||||
service podman {
|
|
||||||
description = "Podman API"
|
|
||||||
runlevel = "2345"
|
|
||||||
user = "podman"
|
|
||||||
group = "podman"
|
|
||||||
cgroup containers {
|
|
||||||
delegate = true
|
|
||||||
memory.max = 4G
|
|
||||||
}
|
|
||||||
command = "/usr/bin/podman system service"
|
|
||||||
}
|
|
||||||
|
|
||||||
This delegates 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 container:%i {
|
|
||||||
description = "container %i"
|
|
||||||
runlevel = "2345"
|
|
||||||
reload-signal = "none"
|
|
||||||
pidfile = "/run/container:%i.pid"
|
|
||||||
stop-timeout = 30
|
|
||||||
log { priority = "local1" identity = "%i" }
|
|
||||||
|
|
||||||
exec-start-pre = "/usr/sbin/container"
|
|
||||||
exec-start-pre-timeout = 0
|
|
||||||
exec-cleanup = "/usr/sbin/container"
|
|
||||||
exec-cleanup-timeout = 0
|
|
||||||
|
|
||||||
cgroup system { delegate = true }
|
|
||||||
command = "container -n %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 a `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.
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
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).
|
|
||||||
|
|
||||||
Global environment variables go in an `environment` block, `env` for
|
|
||||||
short:
|
|
||||||
|
|
||||||
environment {
|
|
||||||
foo = "bar"
|
|
||||||
baz = "qux"
|
|
||||||
}
|
|
||||||
|
|
||||||
On reload of .conf files, all tracked environment variables are cleared
|
|
||||||
so if `foo` 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.
|
|
||||||
@@ -1,212 +0,0 @@
|
|||||||
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/
|
|
||||||
|- bus # Finit's own D-Bus socket, see doc/dbus.md
|
|
||||||
`- system/
|
|
||||||
|- 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 `/run/finit/system/*.conf` are generated by Finit for its
|
|
||||||
built-in services: runparts, [watchdog](../watchdog.md), and
|
|
||||||
[`keventd`](../keventd.md), if they are enabled. They are read before
|
|
||||||
the other .conf directories, so any later file can reference them in
|
|
||||||
`if:` statements and override them by name.
|
|
||||||
|
|
||||||
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 both directories can be either replaced by a system
|
|
||||||
administrator or overridden by a file with the same name in
|
|
||||||
`/etc/finit.d/`, which is always read last -- copy a .conf there and
|
|
||||||
modify it, or symlink it to `/dev/null` to disable it outright.
|
|
||||||
|
|
||||||
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 `/run/finit/system/*.conf`,
|
|
||||||
`/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:**
|
|
||||||
|
|
||||||
/run/finit/system/keventd.conf
|
|
||||||
/run/finit/system/runparts.conf
|
|
||||||
/lib/finit/system/10-hotplug.conf
|
|
||||||
/lib/finit/system/90-testserv.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 in order, 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 `run`. For an example on the relation of `service` and
|
|
||||||
`run`, 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 setting `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.
|
|
||||||
@@ -1,116 +0,0 @@
|
|||||||
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
|
|
||||||
--------------------------
|
|
||||||
|
|
||||||
A `.conf` file is a series of blocks. Every setting is a key inside
|
|
||||||
one, so nothing has to be remembered by position:
|
|
||||||
|
|
||||||
```aconf
|
|
||||||
service sysklogd {
|
|
||||||
description = "System log daemon"
|
|
||||||
runlevel = "S123456789"
|
|
||||||
envfile = "-/etc/default/sysklogd"
|
|
||||||
command = "syslogd -F $SYSLOGD_ARGS"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Values are quoted strings, bare words, or integers. Lists use braces,
|
|
||||||
and a block may carry a title, which becomes the service identity:
|
|
||||||
|
|
||||||
```aconf
|
|
||||||
# shell comment
|
|
||||||
// C++ comment
|
|
||||||
/* C comment */
|
|
||||||
|
|
||||||
key = "value" # string
|
|
||||||
number = 20 # integer
|
|
||||||
flag = true # boolean
|
|
||||||
list = { "one", "two" } # string list
|
|
||||||
block title { key = "value" } # titled section
|
|
||||||
|
|
||||||
path = "${HOME}/thing" # environment expansion
|
|
||||||
include("/etc/finit.d/extra.conf") # include another file
|
|
||||||
```
|
|
||||||
|
|
||||||
Bare words work wherever a string is expected, so `memory.max = 65M`
|
|
||||||
and `restart = always` need no quotes.
|
|
||||||
|
|
||||||
### Two conventions
|
|
||||||
|
|
||||||
Keys are kebab-case, never `snake_case` or `CamelCase`: `restart-sec`,
|
|
||||||
`stop-timeout`, `reboot-watchdog`.
|
|
||||||
|
|
||||||
Keys that take a list are plural: `conditions`, `conflicts`,
|
|
||||||
`capabilities`, `modules`, `extra-groups`. Two imperatives keep their
|
|
||||||
singular form because they are verbs rather than nouns: `mknod` and
|
|
||||||
`include`.
|
|
||||||
|
|
||||||
### Short forms
|
|
||||||
|
|
||||||
Nine keys have an alias. An alias may abbreviate the canonical name,
|
|
||||||
or preserve the spelling the line-based format used; it never renames.
|
|
||||||
|
|
||||||
| Canonical | Alias | Canonical | Alias |
|
|
||||||
|---|---|---|---|
|
|
||||||
| `description` | `desc` | `manual-start` | `manual` |
|
|
||||||
| `conditions` | `cond` | `remain-after-exit` | `remain` |
|
|
||||||
| `capabilities` | `caps` | `stop-signal` | `halt` |
|
|
||||||
| `modules` | `mod` | `stop-timeout` | `kill` |
|
|
||||||
| `envfile` | `env` | | |
|
|
||||||
|
|
||||||
### Optional paths
|
|
||||||
|
|
||||||
A leading `-` on a path means carry on if it is not there:
|
|
||||||
|
|
||||||
```aconf
|
|
||||||
service foo {
|
|
||||||
envfile = "-/etc/default/foo" # skip the file if missing
|
|
||||||
command = "-/usr/sbin/foo" # skip the whole block if missing
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
That is the only mark meaning "optional". Two others mean something
|
|
||||||
else: `!` on `runlevel` inverts the set, e.g. `runlevel = "!12345"`,
|
|
||||||
and `~` on a condition propagates a reload from the service it names.
|
|
||||||
Both are covered where they apply.
|
|
||||||
|
|
||||||
|
|
||||||
Both Formats Are Read
|
|
||||||
---------------------
|
|
||||||
|
|
||||||
Finit also reads the line-based format it has always used, where a
|
|
||||||
stanza is a keyword followed by values whose meaning comes from their
|
|
||||||
position:
|
|
||||||
|
|
||||||
```aconf
|
|
||||||
service [S123456789] env:-/etc/default/sysklogd syslogd -F $SYSLOGD_ARGS -- System log daemon
|
|
||||||
```
|
|
||||||
|
|
||||||
That format still works and is not going away. It is frozen at the
|
|
||||||
Finit 4.x feature set, so new settings appear only in the block format,
|
|
||||||
and the documentation is written in blocks throughout. To convert a
|
|
||||||
file, see the [Syntax Migration Guide](migration.md).
|
|
||||||
|
|
||||||
There is no new file extension and no marker line. Every file is still
|
|
||||||
`*.conf`, and Finit decides which format a file is in by reading it: if
|
|
||||||
it parses as blocks it is a block file, otherwise it goes to the
|
|
||||||
line-based parser. A file is one format or the other, never a mix.
|
|
||||||
|
|
||||||
Because the two are told apart before either parser commits, a typo
|
|
||||||
reports its own file and line instead of being mistaken for the other
|
|
||||||
format:
|
|
||||||
|
|
||||||
```
|
|
||||||
parse error: /etc/finit.d/foo.conf:3: no such option 'commnad'
|
|
||||||
```
|
|
||||||
|
|
||||||
The .conf files `/etc/finit.conf` and `/etc/finit.d/*` support many
|
|
||||||
settings. 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).
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
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.
|
|
||||||
@@ -1,82 +0,0 @@
|
|||||||
General Logging
|
|
||||||
===============
|
|
||||||
|
|
||||||
**Syntax:** `log { size = 200k count = 5 }`
|
|
||||||
|
|
||||||
Log rotation for run/task/services that redirect output to a log file
|
|
||||||
with their own `log` block. 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` blocks take a `log` block of their own,
|
|
||||||
redirecting `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.
|
|
||||||
|
|
||||||
An empty block means syslog with the defaults, and three keys adjust it:
|
|
||||||
|
|
||||||
| Setting | Description |
|
|
||||||
|---|---|
|
|
||||||
| `file` | Write to this path instead of syslog |
|
|
||||||
| `priority` | Syslog `facility.level`, default `daemon.info` |
|
|
||||||
| `identity` | Syslog tag, default the basename of the command |
|
|
||||||
|
|
||||||
`/dev/console` and `/dev/null` are spelled as the paths they are:
|
|
||||||
|
|
||||||
service foo { log { } command = "foo" } # syslog
|
|
||||||
service foo { log { file = "/var/log/foo" } command = "foo" } # a file
|
|
||||||
service foo { log { file = "/dev/console" } command = "foo" } # console
|
|
||||||
service foo { log { file = "/dev/null" } command = "foo" } # discard
|
|
||||||
|
|
||||||
> [!NOTE]
|
|
||||||
> A `log` block at file scope is a different setting -- that one is the
|
|
||||||
> global rotation above, and it takes only `size` and `count`.
|
|
||||||
|
|
||||||
Log rotation is controlled using the global `log` setting.
|
|
||||||
|
|
||||||
**Example:**
|
|
||||||
|
|
||||||
service ntpd {
|
|
||||||
description = "NTP daemon"
|
|
||||||
log {
|
|
||||||
priority = "user.warn"
|
|
||||||
identity = "ntpd"
|
|
||||||
}
|
|
||||||
command = "/sbin/ntpd pool.ntp.org"
|
|
||||||
}
|
|
||||||
|
|
||||||
Output Buffering
|
|
||||||
----------------
|
|
||||||
|
|
||||||
When using the `log` block, 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 myservice {
|
|
||||||
description = "My service"
|
|
||||||
log { }
|
|
||||||
command = "/usr/bin/stdbuf -oL /path/to/command"
|
|
||||||
}
|
|
||||||
|
|
||||||
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.
|
|
||||||
@@ -1,267 +0,0 @@
|
|||||||
Syntax Migration Guide
|
|
||||||
======================
|
|
||||||
|
|
||||||
Finit reads both configuration formats. Every file is still `*.conf`,
|
|
||||||
and the format is detected per file, so a system can be migrated one
|
|
||||||
file at a time -- a file is one format or the other, never a mix.
|
|
||||||
|
|
||||||
This guide maps each part of a line-based stanza to its block key.
|
|
||||||
|
|
||||||
The shape of the change:
|
|
||||||
|
|
||||||
service [S12345] <pid/syslogd> env:-/etc/default/klogd name:klogd klogd -n $KLOGD_OPTS -- Kernel log daemon
|
|
||||||
|
|
||||||
becomes
|
|
||||||
|
|
||||||
service klogd {
|
|
||||||
description = "Kernel log daemon"
|
|
||||||
runlevel = "S12345"
|
|
||||||
conditions = { "pid/syslogd" }
|
|
||||||
envfile = "-/etc/default/klogd"
|
|
||||||
command = "klogd -n $KLOGD_OPTS"
|
|
||||||
}
|
|
||||||
|
|
||||||
The block title is the service identity, shown by `initctl`. Multiple
|
|
||||||
instances spell the ID in the title: `service sshd:1 { ... }`. The
|
|
||||||
legacy bare-ID form, `service :80 ...`, has no equivalent -- the title
|
|
||||||
carries both name and ID.
|
|
||||||
|
|
||||||
Positional parts
|
|
||||||
----------------
|
|
||||||
|
|
||||||
| Line-based | Block key |
|
|
||||||
|----------------------------------|-------------------------------------------------------|
|
|
||||||
| `service`, `task`, `run`, `sysv` | same, as block type |
|
|
||||||
| `[S12345]` | `runlevel = "S12345"` |
|
|
||||||
| `<pid/a,net/b>` | `conditions = { "pid/a", "net/b" }` |
|
|
||||||
| `<!pid/a>` on service/sysv | `conditions = { "pid/a" }` + `reload-signal = "none"` |
|
|
||||||
| `<!pid/a>` on run/task | `conditions = { "pid/a" }` + `required = false` |
|
|
||||||
| `@user:group,extra` | `user`, `group`, `extra-groups = { "extra" }` |
|
|
||||||
| `name:foo :1` | block title `foo:1` |
|
|
||||||
| the command and arguments | `command = "..."` |
|
|
||||||
| `-- Description text` | `description = "..."` |
|
|
||||||
|
|
||||||
The `!` was a flag on the stanza, not a negation, and meant different
|
|
||||||
things for daemons and one-shots; each meaning is now its own key. A
|
|
||||||
`~` prefix on a condition is unchanged: `conditions = { "~pid/a" }`.
|
|
||||||
|
|
||||||
Service options
|
|
||||||
---------------
|
|
||||||
|
|
||||||
| Line-based | Block key |
|
|
||||||
|----------------------------------|--------------------------------------------------|
|
|
||||||
| `env:[-]/path` | `envfile = "[-]/path"` |
|
|
||||||
| `pid:/path` | `pidfile = "/path"` + `pidfile-create = true` |
|
|
||||||
| `pid:!/path` | `pidfile = "/path"` |
|
|
||||||
| `pid` | `pidfile = true` + `pidfile-create = true` |
|
|
||||||
| `log` | `log { }` |
|
|
||||||
| `log:/path` | `log { file = "/path" }` |
|
|
||||||
| `log:null`, `log:console` | `log { file = "/dev/null" }`, `"/dev/console"` |
|
|
||||||
| `log:prio:p,tag:t` | `log { priority = "p" identity = "t" }` |
|
|
||||||
| `notify:systemd` | `notify = "systemd"` |
|
|
||||||
| `type:forking` | `type = "forking"` |
|
|
||||||
| `manual:yes` | `manual-start = true` |
|
|
||||||
| `remain:yes` | `remain-after-exit = true` |
|
|
||||||
| `restart:always` / `restart:NUM` | `restart = "always"` / `restart-max = NUM` |
|
|
||||||
| `restart_sec:SEC` | `restart-sec = SEC` |
|
|
||||||
| `norestart` | `restart = "never"` |
|
|
||||||
| `respawn` | `respawn = true` |
|
|
||||||
| `oncrash:reboot` | `oncrash = "reboot"` |
|
|
||||||
| `halt:SIG` | `stop-signal = "SIG"` |
|
|
||||||
| `kill:SEC` | `stop-timeout = SEC` |
|
|
||||||
| `pre:[TMO,]/script` | `exec-start-pre`, `exec-start-pre-timeout` |
|
|
||||||
| `ready:[TMO,]/script` | `exec-start-ready`, and its `-timeout` |
|
|
||||||
| `stop:[TMO,]/script` | `exec-stop`, and its `-timeout` |
|
|
||||||
| `post:[TMO,]/script` | `exec-stop-post`, and its `-timeout` |
|
|
||||||
| `reload:[TMO,]/script` | `exec-reload`, and its `-timeout` |
|
|
||||||
| `cleanup:[TMO,]/script` | `exec-cleanup`, and its `-timeout` |
|
|
||||||
| `caps:^cap_a,%cap_b` | `capabilities = { "^cap_a", "%cap_b" }` |
|
|
||||||
| `conflict:a,b` | `conflicts = { "a", "b" }` |
|
|
||||||
| `if:svc` / `if:<cond>` | `if = "svc"` / `if = "cond"`, no angle brackets |
|
|
||||||
| `tty:/dev/x` | `tty = "/dev/x"` |
|
|
||||||
| `nowarn` | leading `-` on `command` or `envfile` |
|
|
||||||
| `restarttmo:` | dropped, was already an alias for `restart_sec:` |
|
|
||||||
|
|
||||||
Repeated stanzas
|
|
||||||
----------------
|
|
||||||
|
|
||||||
The line-based format has no titles, so the same service could be
|
|
||||||
declared more than once and Finit would sort out which line applied.
|
|
||||||
A block title *is* the identity, and two blocks sharing one in the
|
|
||||||
same file are rejected. The two shapes that relied on the repetition
|
|
||||||
convert differently.
|
|
||||||
|
|
||||||
**Several candidate binaries for one service.** The daemon is known
|
|
||||||
under more than one name and the stanzas were repeated once per name,
|
|
||||||
each with `nowarn` so the ones that were not installed were skipped:
|
|
||||||
|
|
||||||
service nowarn pid:!/run/udevd.pid [S12345789] /lib/systemd/systemd-udevd -- Device event daemon
|
|
||||||
service nowarn pid:!/run/udevd.pid [S12345789] udevd -- Device event daemon
|
|
||||||
|
|
||||||
The candidates now go in one block, and Finit starts the first one it
|
|
||||||
finds:
|
|
||||||
|
|
||||||
service udevd {
|
|
||||||
description = "Device event daemon"
|
|
||||||
runlevel = "S12345789"
|
|
||||||
pidfile = "/run/udevd.pid"
|
|
||||||
command = { "/lib/systemd/systemd-udevd", "-udevd" }
|
|
||||||
}
|
|
||||||
|
|
||||||
**One service gated differently per platform.** The command is the
|
|
||||||
same every time, only `if:` and the conditions differ, e.g. a syslog
|
|
||||||
daemon that has to wait for whichever hotplug daemon the system has:
|
|
||||||
|
|
||||||
service if:udevd nowarn env:-/etc/default/sysklogd <run/udevadm:5/success> \
|
|
||||||
[S0123456789] syslogd -F $SYSLOGD_ARGS -- System log daemon
|
|
||||||
service if:mdev nowarn env:-/etc/default/sysklogd <run/coldplug/success> \
|
|
||||||
[S0123456789] syslogd -F $SYSLOGD_ARGS -- System log daemon
|
|
||||||
|
|
||||||
All of these are one service, `syslogd`, and everything downstream
|
|
||||||
waits for the one `pid/syslogd` barrier it provides. That barrier is
|
|
||||||
the reason the repetition existed: the title alone spells it, so
|
|
||||||
separate titles would rename it.
|
|
||||||
|
|
||||||
Give each variant its own title and name the shared barrier with
|
|
||||||
`provides`:
|
|
||||||
|
|
||||||
service syslogd:udev {
|
|
||||||
description = "System log daemon"
|
|
||||||
runlevel = "S0123456789"
|
|
||||||
if = "udevd"
|
|
||||||
conditions = { "run/udevadm:5/success" }
|
|
||||||
provides = "pid/syslogd"
|
|
||||||
envfile = "-/etc/default/sysklogd"
|
|
||||||
command = "-syslogd -F $SYSLOGD_ARGS"
|
|
||||||
}
|
|
||||||
service syslogd:mdev {
|
|
||||||
description = "System log daemon"
|
|
||||||
runlevel = "S0123456789"
|
|
||||||
if = "mdev"
|
|
||||||
conditions = { "run/coldplug/success" }
|
|
||||||
provides = "pid/syslogd"
|
|
||||||
envfile = "-/etc/default/sysklogd"
|
|
||||||
command = "-syslogd -F $SYSLOGD_ARGS"
|
|
||||||
}
|
|
||||||
|
|
||||||
Whichever variant `if` qualifies asserts `pid/syslogd` on top of its
|
|
||||||
own `pid/syslogd:udev`, so downstream blocks need no change. The `if`
|
|
||||||
statements are meant to be mutually exclusive; if two of them do
|
|
||||||
qualify, the second claim is refused with a warning and only the first
|
|
||||||
variant supplies the barrier. See [Provided
|
|
||||||
Conditions](service-opts.md#provided-conditions).
|
|
||||||
|
|
||||||
`initctl` now knows the variants apart, `initctl status syslogd:udev`,
|
|
||||||
and a bare `initctl status syslogd` still lists them all.
|
|
||||||
|
|
||||||
Splitting the variants across files also works, since the ban on
|
|
||||||
duplicate titles is per file, as does leaving that one file in the
|
|
||||||
line-based format. Neither is needed for this shape any more.
|
|
||||||
|
|
||||||
Cgroups
|
|
||||||
-------
|
|
||||||
|
|
||||||
The standalone `cgroup.NAME` line selected a group for every stanza
|
|
||||||
after it in the file, and `cgroup:opts` applied settings to whichever
|
|
||||||
group was current. Neither survives: every block names its own group,
|
|
||||||
so nothing depends on what came earlier in the file.
|
|
||||||
|
|
||||||
cgroup.maint
|
|
||||||
service [2345] cgroup:cpu.weight:250 foo -- Foo daemon
|
|
||||||
|
|
||||||
becomes
|
|
||||||
|
|
||||||
service foo {
|
|
||||||
description = "Foo daemon"
|
|
||||||
runlevel = "2345"
|
|
||||||
cgroup maint { cpu.weight = 250 }
|
|
||||||
command = "foo"
|
|
||||||
}
|
|
||||||
|
|
||||||
Top-level group declarations keep their name and settings:
|
|
||||||
|
|
||||||
cgroup system cpu.weight:9700 mem.max:10M
|
|
||||||
|
|
||||||
becomes
|
|
||||||
|
|
||||||
cgroup system {
|
|
||||||
cpu.weight = 9700
|
|
||||||
memory.max = 10M
|
|
||||||
}
|
|
||||||
|
|
||||||
TTYs
|
|
||||||
----
|
|
||||||
|
|
||||||
The three positional variants become three key choices:
|
|
||||||
|
|
||||||
tty [12345] /dev/ttyS0 115200 noclear vt220
|
|
||||||
tty [12345] /sbin/getty -L ttyS0 115200 vt100
|
|
||||||
tty [12345] notty
|
|
||||||
|
|
||||||
become
|
|
||||||
|
|
||||||
tty ttyS0 {
|
|
||||||
runlevel = "12345"
|
|
||||||
device = "/dev/ttyS0"
|
|
||||||
baud = 115200
|
|
||||||
term = "vt220"
|
|
||||||
noclear = true
|
|
||||||
}
|
|
||||||
tty getty {
|
|
||||||
runlevel = "12345"
|
|
||||||
command = "/sbin/getty -L ttyS0 115200 vt100"
|
|
||||||
}
|
|
||||||
tty shell {
|
|
||||||
runlevel = "12345"
|
|
||||||
notty = true
|
|
||||||
}
|
|
||||||
|
|
||||||
The bare flags keep their names as booleans: `noclear`, `nowait`,
|
|
||||||
`nologin`, `passenv`, `rescue`, e.g. `passenv` becomes
|
|
||||||
`passenv = true`.
|
|
||||||
|
|
||||||
A `tty` block is named by the device, not the title, so all three above
|
|
||||||
show up as `tty:ttyS0` and the like in `initctl`. The title still has
|
|
||||||
to be unique within the file.
|
|
||||||
|
|
||||||
Top-level directives
|
|
||||||
--------------------
|
|
||||||
|
|
||||||
| Line-based | Block key |
|
|
||||||
|----------------------------------|----------------------------------------------------------|
|
|
||||||
| `host NAME`, `hostname NAME` | `hostname = "NAME"` |
|
|
||||||
| `module foo args` (repeated) | `modules = { "foo args", ... }` |
|
|
||||||
| `network script args` | `network = "script args"` |
|
|
||||||
| `runlevel N` | `runlevel = N` |
|
|
||||||
| `rcsd /path` | `rcsd = "/path"` |
|
|
||||||
| `runparts [progress] [sysv] DIR` | `runparts = "DIR"`, `runparts-progress`, `runparts-sysv` |
|
|
||||||
| `set KEY=VAL` (repeated) | `environment { KEY = "VAL" }` |
|
|
||||||
| `log size:100k count:4` | `log { size = 100k count = 4 }` |
|
|
||||||
| `rlimit [hard\|soft] RES LIM` | `rlimit { hard.res = LIM }` |
|
|
||||||
| `readiness none` | `readiness = "none"` |
|
|
||||||
| `reboot-delay N` | `reboot-delay = N` |
|
|
||||||
| `reboot-watchdog on` | `reboot-watchdog = true` |
|
|
||||||
| `service-interval SEC` | `service-interval = SEC` |
|
|
||||||
| `shutdown script` | `shutdown = "script"` |
|
|
||||||
| `mknod /dev/x c 1 2` | `mknod = { "/dev/x c 1 2" }` |
|
|
||||||
| `include /path` | `include("/path")` |
|
|
||||||
|
|
||||||
Worth knowing
|
|
||||||
-------------
|
|
||||||
|
|
||||||
* Templates work unchanged: `%i` is replaced before the file is
|
|
||||||
parsed, so `service serv:%i { ... }` in a `serv@.conf` behaves
|
|
||||||
exactly like its legacy counterpart.
|
|
||||||
* A list cannot hold comments; the lexer reads entries after a `#`
|
|
||||||
regardless. Put commented-out candidates above the list.
|
|
||||||
* `${VAR}` in a value is expanded when the file is read, against
|
|
||||||
Finit's environment, and `${VAR:-default}` works too. An unset
|
|
||||||
variable expands to nothing. A plain `$VAR` is left alone and
|
|
||||||
reaches the service, which is what keeps `command = "syslogd -F
|
|
||||||
$SYSLOGD_ARGS"` working with an `envfile`.
|
|
||||||
* New settings only appear in the block format. The first are the
|
|
||||||
[per-service directories](service-opts.md#service-directories),
|
|
||||||
`runtime-dir` and friends.
|
|
||||||
|
|
||||||
For the full description of every key, see the rest of the
|
|
||||||
[Configuration](index.md) section.
|
|
||||||
@@ -1,69 +0,0 @@
|
|||||||
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 rescue {
|
|
||||||
runlevel = "12345"
|
|
||||||
rescue = true
|
|
||||||
}
|
|
||||||
|
|
||||||
The `tty` block has `rescue` set, which works similar to the board
|
|
||||||
bring-up setting `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 falls back to a
|
|
||||||
built-in equivalent, which runs in every runlevel it can:
|
|
||||||
|
|
||||||
tty rescue {
|
|
||||||
runlevel = "12345789"
|
|
||||||
rescue = true
|
|
||||||
}
|
|
||||||
|
|
||||||
There is no way to exit the *fallback* rescue mode.
|
|
||||||
@@ -1,200 +0,0 @@
|
|||||||
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 console-setup {
|
|
||||||
runlevel = "S"
|
|
||||||
command = "/lib/console-setup/console-setup.sh"
|
|
||||||
}
|
|
||||||
|
|
||||||
service rsyslogd {
|
|
||||||
runlevel = "S12345"
|
|
||||||
envfile = "-/etc/default/rsyslog"
|
|
||||||
command = "rsyslogd -n $RSYSLOGD_ARGS"
|
|
||||||
}
|
|
||||||
|
|
||||||
When bootstrap has completed, Finit moves to runlevel 2. This can be
|
|
||||||
changed in `/etc/finit.conf` with `runlevel = N`, 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 `network = "script"`, 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 blocks 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:** `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:** `modules = { "MODULE [ARGS]", ... }`, alias `mod`
|
|
||||||
|
|
||||||
Load kernel modules, each with optional arguments. Similar to the
|
|
||||||
`insmod` command line tool.
|
|
||||||
|
|
||||||
modules = { "button", "evdev", "softdog" }
|
|
||||||
|
|
||||||
> [!NOTE]
|
|
||||||
> A list cannot hold comments; the lexer reads the entries after a `#`
|
|
||||||
> regardless. Put commented-out candidates above the list.
|
|
||||||
|
|
||||||
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. Hotplug module loading is
|
|
||||||
handled by [keventd](../keventd.md), the built-in device manager. On
|
|
||||||
systems using the hotplug plugin with BusyBox mdev instead, 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 { RESOURCE = LIMIT }`, with `soft.` or `hard.` prefix
|
|
||||||
|
|
||||||
Set the hard or soft limit for a resource, or both if the prefix 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.
|
|
||||||
|
|
||||||
rlimit {
|
|
||||||
hard.as = 8388608 # no more than 8MB of address space
|
|
||||||
soft.core = unlimited # core dumps may be arbitrarily large
|
|
||||||
cpu = 10 # soft & hard = 10 sec
|
|
||||||
}
|
|
||||||
|
|
||||||
`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
|
|
||||||
blocks 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 = true|false`
|
|
||||||
|
|
||||||
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.
|
|
||||||
@@ -1,52 +0,0 @@
|
|||||||
Run-parts Scripts
|
|
||||||
-----------------
|
|
||||||
|
|
||||||
**Syntax:** `runparts = "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:**
|
|
||||||
|
|
||||||
- `runparts-progress = true`: display the progress of each script being
|
|
||||||
executed
|
|
||||||
- `runparts-sysv = true`: 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 a standalone `run` block 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 also 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 `another/directory/foo`.
|
|
||||||
|
|
||||||
[run-parts(8)]: http://manpages.debian.org/cgi-bin/man.cgi?query=run-parts
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
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 foo {
|
|
||||||
description = "Example foo daemon"
|
|
||||||
runlevel = "2345"
|
|
||||||
envfile = "-/etc/default/foo"
|
|
||||||
command = "foo -n $FOO_OPTIONS"
|
|
||||||
}
|
|
||||||
|
|
||||||
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 `-` on `envfile` 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. The same mark works on `command`, where it means carry on if
|
|
||||||
> the binary is missing.
|
|
||||||
@@ -1,331 +0,0 @@
|
|||||||
Service Options
|
|
||||||
===============
|
|
||||||
|
|
||||||
The `run`, `task`, `tty`, `service` and `sysv` blocks take settings as
|
|
||||||
keys. This section lists them with their limitations.
|
|
||||||
|
|
||||||
The name of a service, shown by the `initctl` tool, is the block title.
|
|
||||||
It defaults to the basename of the executable if the title is omitted:
|
|
||||||
|
|
||||||
service sshd {
|
|
||||||
command = "/usr/sbin/sshd -D"
|
|
||||||
}
|
|
||||||
|
|
||||||
For multiple instances of a service, with the same name, add an
|
|
||||||
identifier after a colon to prevent Finit from replacing previous
|
|
||||||
instances:
|
|
||||||
|
|
||||||
service ssdp:eth1 { command = "ssdpd eth1" }
|
|
||||||
service ssdp:eth2 { command = "ssdpd 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
|
|
||||||
`conflicts` key:
|
|
||||||
|
|
||||||
service udevd { command = "udevd" }
|
|
||||||
run mdev {
|
|
||||||
runlevel = "S"
|
|
||||||
conflicts = { "udevd" }
|
|
||||||
command = "mdev -s"
|
|
||||||
}
|
|
||||||
|
|
||||||
The list may name several, and an instance is named the same way it is
|
|
||||||
declared:
|
|
||||||
|
|
||||||
service abc:1 { command = "abc 1" }
|
|
||||||
service abc:2 { command = "abc 2" }
|
|
||||||
service cde { conflicts = { "abc:1", "abc:2" } command = "cde" }
|
|
||||||
|
|
||||||
If a service should not be automatically started, set `manual-start`.
|
|
||||||
It can then be started at any time with `initctl start <service>`:
|
|
||||||
|
|
||||||
service lldpd {
|
|
||||||
manual-start = true
|
|
||||||
command = "/usr/sbin/lldpd -d"
|
|
||||||
}
|
|
||||||
|
|
||||||
Other run/task/service settings are:
|
|
||||||
|
|
||||||
* `capabilities` -- see the [Linux Capabilities](capabilities.md) section
|
|
||||||
* `cgroup NAME {}` -- see the [Cgroups](cgroups.md) section
|
|
||||||
* `envfile` -- see the [Service Environment](service-env.md) section
|
|
||||||
* `log {}` -- see [Redirecting Output](logging.md#redirecting-output)
|
|
||||||
* `tty` -- see [Controlling TTY](tty.md#controlling-tty-for-services)
|
|
||||||
* `notify` -- see [Service Synchronization](service-sync.md)
|
|
||||||
* `if` -- see [Conditional Execution](services.md#conditional-execution)
|
|
||||||
* `type = "forking"` -- see description of the [service](services.md) block
|
|
||||||
* a leading `-` on `command` -- see
|
|
||||||
[Conditional Loading](services.md#conditional-loading)
|
|
||||||
|
|
||||||
Command Candidates
|
|
||||||
------------------
|
|
||||||
|
|
||||||
The `command` setting may list several candidates for the same
|
|
||||||
service, in which case Finit starts the first one it finds:
|
|
||||||
|
|
||||||
service udevd {
|
|
||||||
command = { "/lib/systemd/systemd-udevd", "-udevd" }
|
|
||||||
}
|
|
||||||
|
|
||||||
A candidate that is not installed is skipped without a warning, that
|
|
||||||
is the point of listing more than one. The leading `-` is read from
|
|
||||||
the candidate that wins, or from the last one when none are found, so
|
|
||||||
a block with a single command behaves as it always has.
|
|
||||||
|
|
||||||
The candidates are alternative spellings of one service, not a
|
|
||||||
fallback for a service that fails to start. Finit chooses when the
|
|
||||||
.conf file is read and does not revisit the choice.
|
|
||||||
|
|
||||||
A [`tty`](tty.md) block takes the same list, where the candidates are
|
|
||||||
the getty to run:
|
|
||||||
|
|
||||||
tty ttyAMA0 {
|
|
||||||
command = { "/sbin/agetty -L ttyAMA0 115200 vt100",
|
|
||||||
"/sbin/getty -L 115200 /dev/ttyAMA0 vt100" }
|
|
||||||
}
|
|
||||||
|
|
||||||
Provided Conditions
|
|
||||||
-------------------
|
|
||||||
|
|
||||||
A service always asserts `pid/<ident>` for itself, named after the
|
|
||||||
block title. `provides` names conditions it asserts in addition to
|
|
||||||
that one:
|
|
||||||
|
|
||||||
service syslogd:udev {
|
|
||||||
if = "udevd"
|
|
||||||
provides = "pid/syslogd"
|
|
||||||
command = "syslogd -F"
|
|
||||||
}
|
|
||||||
|
|
||||||
This is what lets variants of one service, picked apart by
|
|
||||||
[`if`](services.md#conditional-execution), share the barrier that
|
|
||||||
everything downstream waits for. Each variant has its own title, so
|
|
||||||
each is its own service to `initctl`, while the condition they publish
|
|
||||||
stays the same.
|
|
||||||
|
|
||||||
Any namespace works, `pid/`, `usr/`, `service/`, since the point is
|
|
||||||
publishing a name existing configuration already waits on. A value
|
|
||||||
without a namespace separator is not a condition and is rejected. The
|
|
||||||
list holds at most four.
|
|
||||||
|
|
||||||
A provided condition is asserted and cleared with the service, exactly
|
|
||||||
like its own, so stopping the provider clears the barrier.
|
|
||||||
|
|
||||||
Two services cannot supply the same condition. The second claim is
|
|
||||||
refused, with the owner named:
|
|
||||||
|
|
||||||
finit.conf: second: provides condition <usr/barrier> already registered by service first, ignoring
|
|
||||||
|
|
||||||
The service itself still registers and runs, only the claim is
|
|
||||||
dropped. Which one is "first" is .conf load order, so it follows the
|
|
||||||
file names, see [Files & Layout](files.md).
|
|
||||||
|
|
||||||
A real identity outranks a claim on it. `provides = "pid/sshd"` in a
|
|
||||||
system that also runs a service titled `sshd` loses to that service,
|
|
||||||
because `pid/<ident>` is how Finit tracks the service itself.
|
|
||||||
|
|
||||||
`initctl cond dump` names the owner of every condition, which for a
|
|
||||||
provided one is the service that claimed it:
|
|
||||||
|
|
||||||
$ initctl cond dump
|
|
||||||
PID IDENT STATUS CONDITION
|
|
||||||
1234 syslogd:udev on <pid/syslogd>
|
|
||||||
1234 syslogd:udev on <pid/syslogd:udev>
|
|
||||||
|
|
||||||
Duplicate Titles
|
|
||||||
----------------
|
|
||||||
|
|
||||||
The title is the service identity, so two blocks sharing a title in
|
|
||||||
one file are two declarations of one service. The parser underneath
|
|
||||||
merges them without a word, leaving a single service holding a mix of
|
|
||||||
both, so Finit rejects the file and names the title:
|
|
||||||
|
|
||||||
/etc/finit.d/hotplug.conf:12: found duplicate title 'udevd'
|
|
||||||
|
|
||||||
Nothing from a rejected file is loaded and the rest of the
|
|
||||||
configuration is unaffected.
|
|
||||||
|
|
||||||
The same title in *another* file is fine. That is how a system .conf
|
|
||||||
is overridden, the later file wins, see [Files & Layout](files.md).
|
|
||||||
|
|
||||||
Two shapes need a single identity and used to be written as repeated
|
|
||||||
declarations. One is a service with several candidate binaries, which
|
|
||||||
is now a [command list](#command-candidates). The other is a service
|
|
||||||
gated differently per platform, e.g. a syslog daemon waiting for
|
|
||||||
whichever hotplug daemon the system happens to have. For that one,
|
|
||||||
give each variant its own file, or keep them as one-liners in the
|
|
||||||
line-based format, which has no titles. The [migration
|
|
||||||
guide](migration.md) works through it.
|
|
||||||
|
|
||||||
Restarting
|
|
||||||
----------
|
|
||||||
|
|
||||||
Services are automatically started, restarted, and stopped, depending
|
|
||||||
on the configuration and conditions. Within the confines of that the
|
|
||||||
following settings are available:
|
|
||||||
|
|
||||||
* `restart-max = NUM` -- number of times Finit tries to restart a
|
|
||||||
crashing service, default: 10. 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. The default is 2 seconds for the first
|
|
||||||
half of `restart-max` attempts, then a back-off to 5 seconds -- with
|
|
||||||
the default `restart-max` that is the first five retries. The
|
|
||||||
greater of this configured value and the back-off is used
|
|
||||||
* `restart = "always"` -- no upper limit on the number of times Finit
|
|
||||||
tries to restart a crashing service
|
|
||||||
* `restart = "never"` -- do not restart on failures. `false` is
|
|
||||||
accepted as a synonym, and `true` selects the default policy
|
|
||||||
* `respawn = true` -- bypasses the `restart` mechanism completely,
|
|
||||||
allowing endless restarts. Exiting is treated as normal work
|
|
||||||
rather than failure, so the service is restarted at once instead of
|
|
||||||
being counted and delayed. This is how a `tty` behaves; it is not
|
|
||||||
what `service` was designed for, so it is not the default
|
|
||||||
* `remain-after-exit = true` -- for `run` and `task` only. Prevents
|
|
||||||
the task from re-running on runlevel re-entry and ensures the
|
|
||||||
`exec-stop-post` script runs when the task is explicitly stopped or
|
|
||||||
leaves its valid runlevels. This is systemd's `RemainAfterExit=`.
|
|
||||||
See [Task and Run](task-and-run.md) for more details
|
|
||||||
* `oncrash = "reboot"` -- when all retries have failed, and the
|
|
||||||
service has *crashed*, the system is rebooted
|
|
||||||
* `oncrash = "script"` -- similarly, but instead of rebooting, call
|
|
||||||
the `exec-stop-post` script with exit code `crashed`, see below
|
|
||||||
|
|
||||||
Service directories
|
|
||||||
-------------------
|
|
||||||
|
|
||||||
Five settings ask Finit to create a directory for the service before it
|
|
||||||
starts, owned by its `user` and `group`, mode 0755. The value is a
|
|
||||||
directory name, resolved under a fixed base -- absolute paths and `..`
|
|
||||||
are refused:
|
|
||||||
|
|
||||||
| Setting | Base | Environment variable |
|
|
||||||
|---|---|---|
|
|
||||||
| `runtime-dir` | `/run` | `RUNTIME_DIRECTORY` |
|
|
||||||
| `state-dir` | `/var/lib` | `STATE_DIRECTORY` |
|
|
||||||
| `cache-dir` | `/var/cache` | `CACHE_DIRECTORY` |
|
|
||||||
| `logs-dir` | `/var/log` | `LOGS_DIRECTORY` |
|
|
||||||
| `config-dir` | `/etc` | `CONFIGURATION_DIRECTORY` |
|
|
||||||
|
|
||||||
Each resolved path is exported to the process environment under the
|
|
||||||
listed name, the same names systemd uses for `RuntimeDirectory=` and
|
|
||||||
friends. As in systemd, `config-dir` is the odd one out: it is created
|
|
||||||
but never chowned.
|
|
||||||
|
|
||||||
Each takes a matching `-mode`, e.g. `runtime-dir-mode = 0700`, default
|
|
||||||
0755. Modes are octal, with the leading zero.
|
|
||||||
|
|
||||||
The mode of the named directory is locked down again on every start.
|
|
||||||
Its contents are left alone as long as the owner is right; if the owner
|
|
||||||
has drifted, everything under it is chowned back.
|
|
||||||
|
|
||||||
The runtime directory is removed again when the service stops, after
|
|
||||||
any `exec-stop-post` script has run; `/run` is a tmpfs so it would not
|
|
||||||
survive a reboot anyway. The other four persist. A completed `run` or
|
|
||||||
`task` counts as stopped, unless `remain-after-exit` keeps it alive
|
|
||||||
until stopped for real. `runtime-dir-preserve` adjusts this, same
|
|
||||||
values as systemd's `RuntimeDirectoryPreserve=`:
|
|
||||||
|
|
||||||
* `"no"` -- removed when the service stops, the default
|
|
||||||
* `"restart"` -- kept across restarts, removed on a real stop
|
|
||||||
* `"yes"` -- never removed
|
|
||||||
|
|
||||||
This is what lets a service drop privileges and still create, and
|
|
||||||
later touch, its own PID file:
|
|
||||||
|
|
||||||
service ntpd {
|
|
||||||
user = "ntp"
|
|
||||||
group = "ntp"
|
|
||||||
runtime-dir = "ntpd"
|
|
||||||
pidfile = "/run/ntpd/ntpd.pid"
|
|
||||||
command = "/usr/sbin/ntpd -n -p /run/ntpd/ntpd.pid"
|
|
||||||
}
|
|
||||||
|
|
||||||
These settings exist only in the block format.
|
|
||||||
|
|
||||||
Stopping and reloading
|
|
||||||
----------------------
|
|
||||||
|
|
||||||
When stopping a service, either manually or when moving to another
|
|
||||||
runlevel, Finit starts by sending `SIGTERM` to let the process shut
|
|
||||||
down gracefully. If it has not been collected within 3 seconds,
|
|
||||||
`SIGKILL` follows. Both ends of that are configurable:
|
|
||||||
|
|
||||||
* `stop-signal = "SIGPWR"` -- send this instead of `SIGTERM`
|
|
||||||
* `stop-timeout = 10` -- seconds to wait before `SIGKILL`, 1-300
|
|
||||||
|
|
||||||
Some services need more than a signal:
|
|
||||||
|
|
||||||
* `exec-stop = "script [args]"` -- run instead of sending the stop
|
|
||||||
signal, and instead of `stop` for `sysv`
|
|
||||||
* `exec-reload = "script [args]"` -- run instead of sending `SIGHUP`.
|
|
||||||
Like systemd, Finit sets `$MAINPID` as a convenience to scripts,
|
|
||||||
which in effect also allows `exec-reload = "kill -HUP $MAINPID"`
|
|
||||||
|
|
||||||
If a daemon cannot be reloaded with a signal at all, say so and Finit
|
|
||||||
restarts it instead:
|
|
||||||
|
|
||||||
service dropbear {
|
|
||||||
reload-signal = "none"
|
|
||||||
command = "/usr/sbin/dropbear -R -F"
|
|
||||||
}
|
|
||||||
|
|
||||||
`SIGHUP` is the default and the only other accepted value, with or
|
|
||||||
without the `SIG` prefix and in any case.
|
|
||||||
|
|
||||||
Scripts
|
|
||||||
-------
|
|
||||||
|
|
||||||
Services, including the `sysv` variant, support six lifecycle scripts:
|
|
||||||
|
|
||||||
* `exec-start-pre` -- called before the sysv/service is started
|
|
||||||
* `exec-start-ready` -- called when the sysv/service is ready
|
|
||||||
* `exec-stop` -- called instead of the stop signal
|
|
||||||
* `exec-stop-post` -- called after the sysv/service has stopped
|
|
||||||
* `exec-reload` -- called instead of `SIGHUP`
|
|
||||||
* `exec-cleanup` -- called when run/task/sysv/service is removed
|
|
||||||
|
|
||||||
Each takes a matching `-timeout`, in seconds, 0-3600, after which Finit
|
|
||||||
kills the script. It defaults to the `stop-timeout` value and can be
|
|
||||||
disabled by setting it to zero:
|
|
||||||
|
|
||||||
service foo {
|
|
||||||
exec-start-pre = "/etc/foo/pre.sh"
|
|
||||||
exec-start-pre-timeout = 10
|
|
||||||
command = "/usr/sbin/foo"
|
|
||||||
}
|
|
||||||
|
|
||||||
These scripts run as the same user and group as the service itself,
|
|
||||||
with any `envfile` sourced. They 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 `exec-stop-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/sysv/service is removed (disable + reload) it is first
|
|
||||||
stopped and then removed from the runlevel. The `exec-stop-post`
|
|
||||||
script always runs when the process has stopped, and `exec-cleanup`
|
|
||||||
runs when the block has been removed from the runlevel.
|
|
||||||
|
|
||||||
> [!IMPORTANT]
|
|
||||||
> These script actions are intended for setup, cleanup, and readiness
|
|
||||||
> notification. A script that outlives its timeout is killed, so pick
|
|
||||||
> one that suits the work, or set it to zero to opt out and take
|
|
||||||
> responsibility for the script terminating.
|
|
||||||
@@ -1,81 +0,0 @@
|
|||||||
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 watchdogd { notify = "pid" command = "watchdogd" }
|
|
||||||
service foo { notify = "systemd" command = "foo" }
|
|
||||||
service bar { notify = "s6" command = "bar" }
|
|
||||||
service qux { notify = "none" command = "qux" }
|
|
||||||
|
|
||||||
The `notify = "none"` setting 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 watchdogd {
|
|
||||||
notify = "pid"
|
|
||||||
command = "watchdogd"
|
|
||||||
}
|
|
||||||
|
|
||||||
service stress-ng {
|
|
||||||
conditions = { "service/watchdogd/ready" }
|
|
||||||
command = "stress-ng --cpu 8"
|
|
||||||
}
|
|
||||||
|
|
||||||
For the full list of conditions, see [Finit Conditions](../conditions.md).
|
|
||||||
|
|
||||||
> [!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 `reload-signal = "none"`.)
|
|
||||||
>
|
|
||||||
> 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.
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
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 block. The following
|
|
||||||
example employs a wrapper script in `/etc/start.d`.
|
|
||||||
|
|
||||||
**Example:**
|
|
||||||
|
|
||||||
* `/etc/finit.d/available/program.conf`:
|
|
||||||
|
|
||||||
service program {
|
|
||||||
description = "Example Program"
|
|
||||||
runlevel = "235"
|
|
||||||
reload-signal = "none"
|
|
||||||
command = "/etc/start.d/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 `reload-signal = "none"` to say the program does not
|
|
||||||
> support `SIGHUP`. Finit then stop/starts the service instead of
|
|
||||||
> signalling it at restart/reload events.
|
|
||||||
@@ -1,356 +0,0 @@
|
|||||||
Services
|
|
||||||
========
|
|
||||||
|
|
||||||
**Syntax:** `service NAME { command = "/path/to/daemon ARGS" }`
|
|
||||||
|
|
||||||
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
|
|
||||||
[Service Options](service-opts.md).
|
|
||||||
|
|
||||||
> [!TIP]
|
|
||||||
> To allow endless restarts, see [`respawn`](service-opts.md#restarting)
|
|
||||||
|
|
||||||
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, by
|
|
||||||
naming the file to watch with `pidfile`. There is an alternative that
|
|
||||||
may be more intuitive, where Finit can also guess the PID file based on
|
|
||||||
the daemon's command name:
|
|
||||||
|
|
||||||
service ntpd {
|
|
||||||
description = "NTP daemon"
|
|
||||||
type = "forking"
|
|
||||||
command = "ntpd"
|
|
||||||
}
|
|
||||||
|
|
||||||
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, name the file yourself
|
|
||||||
with `pidfile = "/path/to/file.pid"`.
|
|
||||||
|
|
||||||
The file belongs to the service: Finit reads it but does not create or
|
|
||||||
remove it. That is the default, and `pidfile-create = true` is what
|
|
||||||
asks Finit to write the file instead. 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 ospfd {
|
|
||||||
description = "OSPF daemon"
|
|
||||||
runlevel = "2345"
|
|
||||||
conditions = { "pid/zebra" }
|
|
||||||
command = "/sbin/ospfd"
|
|
||||||
}
|
|
||||||
|
|
||||||
`runlevel` denotes the runlevels `ospfd` is allowed to run in, it is
|
|
||||||
optional and defaults to level 2-4 if omitted.
|
|
||||||
|
|
||||||
`conditions` lists what must be asserted before starting `ospfd`. In
|
|
||||||
this example Finit waits for another service, `zebra`, to have created
|
|
||||||
its PID file in `/var/run/quagga/zebra.pid`. Finit watches *all* files
|
|
||||||
in `/var/run`, for each file named `*.pid`, or `*/pid`, Finit opens it
|
|
||||||
and finds the matching `NAME:ID` using the PID.
|
|
||||||
|
|
||||||
A condition may be prefixed with `~` to propagate a reload of the
|
|
||||||
upstream service to this one, rather than merely pausing and resuming
|
|
||||||
it:
|
|
||||||
|
|
||||||
conditions = { "~pid/zebra" }
|
|
||||||
|
|
||||||
If `ospfd` cannot be reloaded with `SIGHUP` at all, that is a property
|
|
||||||
of `ospfd` and not of the condition, so it is said directly:
|
|
||||||
|
|
||||||
reload-signal = "none"
|
|
||||||
|
|
||||||
The legacy format spells that second one as a `!` leading the condition
|
|
||||||
list, which is not accepted here. 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. With `pidfile-create` Finit
|
|
||||||
creates the file when starting and removes it when stopping. The path
|
|
||||||
comes from `pidfile`, which takes three forms:
|
|
||||||
|
|
||||||
pidfile = true # /var/run/<command basename>.pid
|
|
||||||
pidfile = "bar" # a bare name, /var/run/bar.pid
|
|
||||||
pidfile = "/run/bar.pid" # an explicit path
|
|
||||||
|
|
||||||
Such a file is also used by the Finit condition subsystem, so another
|
|
||||||
service, run or task can depend on `pid/bar`. Here foo is not started
|
|
||||||
until bar has:
|
|
||||||
|
|
||||||
service bar {
|
|
||||||
description = "Bar Service"
|
|
||||||
pidfile = "/run/bar.pid"
|
|
||||||
pidfile-create = true
|
|
||||||
command = "bar"
|
|
||||||
}
|
|
||||||
|
|
||||||
service foo {
|
|
||||||
description = "Foo Service"
|
|
||||||
conditions = { "pid/bar" }
|
|
||||||
command = "foo"
|
|
||||||
}
|
|
||||||
|
|
||||||
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 is enabled with the `notify` key:
|
|
||||||
|
|
||||||
* `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 mdevd {
|
|
||||||
runlevel = "S12345789"
|
|
||||||
notify = "s6"
|
|
||||||
command = "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 mdevd-coldplug {
|
|
||||||
runlevel = "S"
|
|
||||||
conditions = { "service/mdevd/ready" }
|
|
||||||
user = "root"
|
|
||||||
group = "root"
|
|
||||||
command = "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
|
|
||||||
command should be executed with, using `user`, `group` and
|
|
||||||
`extra-groups`, all optional:
|
|
||||||
|
|
||||||
run hello {
|
|
||||||
runlevel = "2345"
|
|
||||||
user = "joe"
|
|
||||||
group = "users"
|
|
||||||
command = "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`, list them in `extra-groups`:
|
|
||||||
|
|
||||||
service caddy {
|
|
||||||
user = "caddy"
|
|
||||||
group = "caddy"
|
|
||||||
extra-groups = { "ssl-cert" }
|
|
||||||
command = "/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` to the block title, like this:
|
|
||||||
|
|
||||||
service httpd:80 {
|
|
||||||
description = "Web server"
|
|
||||||
runlevel = "2345"
|
|
||||||
command = "httpd -f -h /http -p 80"
|
|
||||||
}
|
|
||||||
|
|
||||||
service httpd:8080 {
|
|
||||||
description = "Old web server"
|
|
||||||
runlevel = "2345"
|
|
||||||
command = "httpd -f -h /http -p 8080"
|
|
||||||
}
|
|
||||||
|
|
||||||
Without the `:ID` the latter will overwrite the former and only the old
|
|
||||||
web server would be started and supervised.
|
|
||||||
|
|
||||||
> [!NOTE]
|
|
||||||
> The line-based format also accepts a bare ID, `service :80 ...`,
|
|
||||||
> deriving the name from the command. There is no block equivalent:
|
|
||||||
> the title carries both name and ID.
|
|
||||||
|
|
||||||
|
|
||||||
Conditional Loading
|
|
||||||
-------------------
|
|
||||||
|
|
||||||
Finit supports conditional loading of blocks. The following example is
|
|
||||||
taken from the `system/10-hotplug.conf` file in the Finit distribution.
|
|
||||||
Here we only show a simplified subset.
|
|
||||||
|
|
||||||
Starting with the udev daemon, which goes by two names depending on
|
|
||||||
how it was built. Both are candidates for the same service:
|
|
||||||
|
|
||||||
service udevd {
|
|
||||||
pidfile = "udevd"
|
|
||||||
command = { "/lib/systemd/systemd-udevd", "-udevd" }
|
|
||||||
}
|
|
||||||
|
|
||||||
When loading the .conf file Finit looks for
|
|
||||||
`/lib/systemd/systemd-udevd`, and if that is not there it moves on to
|
|
||||||
`udevd`. A candidate that is not installed is expected, so no warning
|
|
||||||
is logged for the ones that are skipped. The leading `-` on the last
|
|
||||||
one says it is also fine if none of them are found, in which case the
|
|
||||||
block is dropped quietly and no service named `udevd` exists.
|
|
||||||
|
|
||||||
> [!NOTE]
|
|
||||||
> This needs to be one block. The title is the service identity, so
|
|
||||||
> two blocks titled `udevd` in the same file are two declarations of
|
|
||||||
> one service, which Finit rejects. See [Duplicate
|
|
||||||
> titles](service-opts.md#duplicate-titles).
|
|
||||||
|
|
||||||
run udevadm:1 {
|
|
||||||
runlevel = "S"
|
|
||||||
if = "udevd"
|
|
||||||
conditions = { "pid/udevd" }
|
|
||||||
command = "-udevadm settle -t 0"
|
|
||||||
}
|
|
||||||
|
|
||||||
This block 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 mdev {
|
|
||||||
description = "Populating device tree"
|
|
||||||
runlevel = "S"
|
|
||||||
conflicts = { "udevd" }
|
|
||||||
command = "-mdev -s"
|
|
||||||
}
|
|
||||||
|
|
||||||
If `udevd` is not available, we try to run `mdev`, but if that is not
|
|
||||||
found, again we do not warn.
|
|
||||||
|
|
||||||
Conditional loading can also be negated, so the previous block can be
|
|
||||||
written as:
|
|
||||||
|
|
||||||
run mdev {
|
|
||||||
description = "Populating device tree"
|
|
||||||
runlevel = "S"
|
|
||||||
if = "!udevd"
|
|
||||||
command = "-mdev -s"
|
|
||||||
}
|
|
||||||
|
|
||||||
The reason for using `conflicts` in this example is that a conflict can
|
|
||||||
be resolved. Blocks naming a conflict are rechecked at runtime.
|
|
||||||
|
|
||||||
|
|
||||||
Conditional Execution
|
|
||||||
---------------------
|
|
||||||
|
|
||||||
Similar to conditional loading of blocks 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 with `runlevel = "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 startup {
|
|
||||||
runlevel = "S"
|
|
||||||
conditions = { "pid/sysrepo" }
|
|
||||||
command = "confd -b --load startup-config"
|
|
||||||
}
|
|
||||||
|
|
||||||
run failure {
|
|
||||||
runlevel = "S"
|
|
||||||
if = "usr/fail-startup"
|
|
||||||
conditions = { "pid/sysrepo" }
|
|
||||||
command = "confd --load failure-config"
|
|
||||||
}
|
|
||||||
|
|
||||||
The two run blocks 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 one to load
|
|
||||||
`failure-config`.
|
|
||||||
|
|
||||||
Notice the critical difference between the `conditions` list and `if`.
|
|
||||||
The former is a condition for starting; the latter is a condition to
|
|
||||||
check whether a run/task/service is qualified to even be considered.
|
|
||||||
`if` has a negation of its own, `!`, which is unrelated to anything in
|
|
||||||
the `conditions` list.
|
|
||||||
|
|
||||||
What `if` compares against depends on the value. A namespace
|
|
||||||
separator makes it a condition, anything else is a service name:
|
|
||||||
|
|
||||||
| `if` | Asks |
|
|
||||||
|---|---|
|
|
||||||
| `"udevd"` | is a service by this name known? |
|
|
||||||
| `"usr/foo"` | was this condition set? |
|
|
||||||
|
|
||||||
Both are questions about whether the block belongs in the running
|
|
||||||
configuration at all, usually answered from what bootstrap established.
|
|
||||||
A statement is all of one kind or the other, so the block is rejected
|
|
||||||
if you mix them.
|
|
||||||
|
|
||||||
> [!NOTE]
|
|
||||||
> `if` qualifies, it does not track. A condition asserted or cleared
|
|
||||||
> later does not start or stop the service by itself -- that is what
|
|
||||||
> the `conditions` list is for.
|
|
||||||
|
|
||||||
Conditional execution can also be negated, so provided the file loaded
|
|
||||||
did the opposite, i.e., set a condition on success, the previous block
|
|
||||||
can be written as:
|
|
||||||
|
|
||||||
run failure {
|
|
||||||
runlevel = "S"
|
|
||||||
if = "!usr/startup-ok"
|
|
||||||
conditions = { "pid/sysrepo" }
|
|
||||||
command = "confd ..."
|
|
||||||
}
|
|
||||||
|
|
||||||
Variants of one service are often qualified this way, one per platform,
|
|
||||||
and they usually have to supply the same barrier to whatever waits for
|
|
||||||
them. Each variant needs its own title, since a title is an identity,
|
|
||||||
and the shared barrier is named with `provides`. See [Provided
|
|
||||||
Conditions](service-opts.md#provided-conditions).
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user