mirror of
https://github.com/troglobit/finit.git
synced 2026-10-10 16:52:39 +07:00
This patch adopts the BusyBox init signals for handling halt, reboot, and poweroff. The SIGINT and SIGPWR signals still behave the same as before, even though they likely will become configurable in a future release. Note: the disabling of Ctrl-Alt-Delete (SIGINT) is also removed! Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
428 lines
16 KiB
Markdown
428 lines
16 KiB
Markdown
```
|
|
_______ __ _____ ___ __ ___________ _______
|
|
/" "||" \ (\" \|" \ |" \(" _ ")/" __ )
|
|
(: ______)|| | |.\\ \ | || |)__/ \\__/(__/ _) ./
|
|
\/ | |: | |: \. \\ | |: | \\_ / / //
|
|
// ___) |. | |. \ \. | |. | |. | __ \_ \\
|
|
(: ( /\ |\| \ \ | /\ |\ \: | (: \__) :\
|
|
\__/ (__\_|_)\___|\____\)(__\_|_) \__| \_______)
|
|
```
|
|
|
|
Fast init for Linux
|
|
===================
|
|
[![Travis Status]][Travis] [![Coverity Status]][Coverity Scan]
|
|
|
|
Table of Contents
|
|
-----------------
|
|
|
|
* [Introduction](#introduction)
|
|
* [Features](#features)
|
|
* [/etc/finit.conf](doc/config.md#etcfinitconf)
|
|
* [/etc/finit.d](doc/config.md#etcfinitd)
|
|
* [Runparts & /etc/rc.local](#runparts--etcrclocal)
|
|
* [Bootstrap](doc/bootstrap.md#bootstrap)
|
|
* [Runlevels](#runlevels)
|
|
* [Inetd](doc/inetd.md#inetd)
|
|
* [Hooks, Callbacks & Plugins](doc/plugins.md#hooks-callbacks--plugins)
|
|
* [Rebooting & Halting](#rebooting--halting)
|
|
* [Commands & Status](#commands--status)
|
|
* [Building](doc/build.md#building)
|
|
* [Running](#running)
|
|
* [Debugging](#debugging)
|
|
* [Origin & References](#origin--references)
|
|
|
|
|
|
Introduction
|
|
------------
|
|
|
|
Finit is a plugin-based init with [process supervision][1] similar to
|
|
that of D.J. Bernstein's [daemontools][2] and Gerrit Pape's [runit][3].
|
|
The main focus of Finit is on small and embedded Linux systems, yet
|
|
fully usable on server and desktop installations as well.
|
|
|
|
Traditional [SysV init][4] style systems are scripted. For low-resource
|
|
embedded systems this is quite resource intensive and often leads to
|
|
long boot times. Finit reduces context switches and forking of shell
|
|
scripts to provide a swift [system bootstrap](doc/bootstrap.md) written
|
|
entirely in C.
|
|
|
|
Configuration is read from [/etc/finit.conf](doc/config.md#etcfinitconf)
|
|
which details kernel modules to load, services and TTYs to start. When
|
|
initial [bootstrap](doc/bootstrap.md) is done, including setting up
|
|
networking, [/etc/finit.d/](doc/config.md#etcfinitd) and the familiar
|
|
[/etc/rc.local](#runparts--etcrclocal) are run.
|
|
|
|
**Example /etc/finit.conf:**
|
|
|
|
```
|
|
# Fallback if /etc/hostname is missing
|
|
host myhostname
|
|
|
|
# Devices to fsck at boot
|
|
check /dev/vda1
|
|
|
|
# Runlevel to start after bootstrap, runlevel 'S'
|
|
runlevel 2
|
|
|
|
# Network bringup, not needed if /etc/network/interfaces exist
|
|
#network service networking start
|
|
#network /sbin/ifup -a
|
|
|
|
# Services to be monitored and respawned as needed
|
|
service [S12345] /sbin/watchdogd -L -f -- System watchdog daemon
|
|
service [S12345] /sbin/syslogd -n -b 3 -D -- System log daemon
|
|
service [S12345] /sbin/klogd -n -- Kernel log daemon
|
|
service 2345] /sbin/lldpd -d -c -M1 -H0 -i -- LLDP daemon (IEEE 802.1ab)
|
|
|
|
# For multiple instances of the same service, add :ID somewhere between
|
|
# the service/run/task keyword and the command.
|
|
service :1 [2345] /sbin/httpd -f -h /http -p 80 -- Web server
|
|
service :2 [2345] /sbin/httpd -f -h /http -p 8080 -- Old web server
|
|
|
|
# Alternative method instead of below runparts, can also use /etc/rc.local
|
|
#task [S] /etc/init.d/keyboard-setup start -- Setting up preliminary keymap
|
|
#task [S] /etc/init.d/acpid start -- Starting ACPI Daemon
|
|
#task [S] /etc/init.d/kbd start -- Preparing console
|
|
#run [2] /etc/init.d/networking start -- Start networking
|
|
|
|
# Inetd services to start on demand, with alternate ports and filtering
|
|
inetd ftp/tcp nowait [2345] /sbin/uftpd -i -f -- FTP daemon
|
|
inetd tftp/udp wait [2345] /sbin/uftpd -i -y -- TFTP daemon
|
|
inetd time/udp wait [2345] internal -- UNIX rdate service
|
|
inetd time/tcp nowait [2345] internal -- UNIX rdate service
|
|
inetd 3737/tcp nowait [2345] internal.time -- UNIX rdate service
|
|
inetd telnet/tcp nowait [2345] /sbin/telnetd -i -F -- Telnet daemon
|
|
inetd 2323/tcp nowait [2345] /sbin/telnetd -i -F -- Telnet daemon
|
|
inetd 222/tcp@eth0 nowait [2345] /sbin/dropbear -i -R -F -- SSH service
|
|
inetd ssh/tcp@*,!eth0 nowait [2345] /sbin/dropbear -i -R -F -- SSH service
|
|
|
|
# Run start scripts from this directory
|
|
# runparts /etc/start.d
|
|
|
|
# Virtual consoles to start getty on
|
|
tty [12345] /dev/tty1 115200 linux
|
|
tty [12345] /dev/ttyAMA0 115200 vt100
|
|
```
|
|
|
|
For an example of a full blown embedded Linux, see [TroglOS][9], or take
|
|
a look at the `contrib/` section with [Alpine Linux](contrib/alpine/)
|
|
support and more.
|
|
|
|
|
|
Features
|
|
--------
|
|
|
|
**Process Supervision**
|
|
|
|
Start, monitor and restart services should they fail.
|
|
|
|
|
|
**Inetd**
|
|
|
|
Finit comes with a built-in [inetd server](doc/inetd.md). No need to
|
|
maintain a separate config file for services that you want to start on
|
|
demand.
|
|
|
|
All inetd services started can be filtered per port and inbound
|
|
interface, reducing the need for a full blown firewall.
|
|
|
|
Built-in optional inetd services:
|
|
|
|
- echo RFC862
|
|
- chargen RFC864
|
|
- daytime RFC867
|
|
- discard RFC863
|
|
- time (rdate) RFC868
|
|
|
|
For more information, see [doc/inetd.md](doc/inetd.md).
|
|
|
|
**Runlevels**
|
|
|
|
Runlevels are optional in Finit, but support for [SysV runlevels][5] is
|
|
available if needed. All services in runlevel S(1) are started first,
|
|
followed by the desired run-time runlevel. 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>
|
|
|
|
|
|
**Plugins**
|
|
|
|
Finit plugins can be *callbacks*, *boot hooks* into different stages of
|
|
the boot process, or *pure extensions*. Plugins are written in C and
|
|
compiled into a dynamic library that is loaded automatically by finit at
|
|
boot. A basic set of plugins that extend and modify the basic behavior
|
|
are bundled in the `plugins/` directory.
|
|
|
|
Capabilities:
|
|
|
|
- **Task/Run/Service callbacks**
|
|
Modify service arguments, override service monitor's decisions to
|
|
start/stop/reload a service.
|
|
- **Hooks**
|
|
Hook into the boot at predefined points to extend Finit
|
|
- **I/O**
|
|
Listen to external events and control Finit behavior/services
|
|
- **Inetd**
|
|
Extend Finit with internal inetd services, for an example, see
|
|
`plugins/time.c`
|
|
|
|
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).
|
|
|
|
|
|
Runparts & /etc/rc.local
|
|
------------------------
|
|
|
|
At the end of the boot, when networking and all services are up, finit
|
|
calls its built-in [run-parts(8)][] on the `runparts <DIR>` directory,
|
|
and `/etc/rc.local`, in that order if they exist.
|
|
|
|
```shell
|
|
runparts /etc/rc.d/
|
|
```
|
|
|
|
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:
|
|
|
|
```shell
|
|
service [S12345] /sbin/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] /sbin/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.
|
|
|
|
Switching between runlevels can be done by calling init with a single
|
|
argument, e.g. <kbd>init 5</kbd> switches 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
|
|
-------------------
|
|
|
|
Finit is often used on embedded and small Linux systems with BusyBox.
|
|
For compatibility with its existing toolset (halt, poweroff, reboot),
|
|
the following signals have been adopted:
|
|
|
|
* `SIGUSR1`
|
|
Same effect as `finit q`, reloads all *.conf files in `/etc/finit.d/`
|
|
* `SIGUSR1`
|
|
Calls shutdown hooks, including HOOK_SHUTDOWN, stops all running
|
|
processes, and unmounts all file systems. Then tells kernel to
|
|
halt. Most people these days want SIGUSR2 though.
|
|
|
|
SysV init and systemd use this to re-open their FIFO/D-Bus.
|
|
* `SIGUSR2`
|
|
Like SIGUSR1, but tell kernel to power-off the system, if ACPI
|
|
or similar exists to actually do this. If the kernel fails
|
|
power-off, Finit falls back to halt.
|
|
|
|
SysV init N/A, systemd dumps its internal state to log.
|
|
* `SIGTERM`
|
|
Like `SIGUSR1`, but tell kernel to reboot the system when done.
|
|
|
|
SysV init N/A, systemd rexecutes itself.
|
|
* `SIGINT`
|
|
Sent from kernel when the CTRL-ALT-DEL key combo is pressed.
|
|
SysV init and systemd default to reboot with `shutdown -r`.
|
|
Finit currently forwards this to `SIGTERM`.
|
|
* `SIGPWR`
|
|
Sent from a power daemon, like `powstatd(8)`, on changes to the
|
|
UPS status. Traditionally SysV init read /etc/powerstatus and
|
|
acted on "OK", "FAIL", or "LOW" and then removed the file.
|
|
Finit currently forwards this to `SIGUSR2`.
|
|
|
|
Finit also listens to the classic SysV init FIFO, which used to be
|
|
located in `/dev` but these days default to `/run/initctl`. So existing
|
|
tools like, `poweroff`, `halt`, `reboot`, and `shutdown` work as
|
|
expected. Support for this old-style handling is implemented in the
|
|
optional `initctl.so` plugin and can be accessed with the traditional
|
|
`telinit` command line tool, symlinked to `finit`. Hence, if finit is
|
|
your system init, then `init q` will work as the UNIX beards intended.
|
|
|
|
```shell
|
|
~ $ telinit
|
|
Usage: telinit [OPTIONS] [q | Q | 0-9]
|
|
|
|
Options:
|
|
-h, --help This help text
|
|
-v, --version Show Finit version
|
|
|
|
Commands:
|
|
q | Q Reload *.conf in /etc/finit.d/, like SIGHUP
|
|
0 - 9 Change runlevel: 0 halt, 6 reboot
|
|
```
|
|
|
|
|
|
Commands & Status
|
|
-----------------
|
|
|
|
Finit also implements a more 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.
|
|
|
|
```shell
|
|
~ $ initctl -h
|
|
Usage: initctl [OPTIONS] <COMMAND>
|
|
|
|
Options:
|
|
-d, --debug Debug initctl (client)
|
|
-v, --verbose Verbose output
|
|
-h, --help This help text
|
|
|
|
Commands:
|
|
debug Toggle Finit (daemon) debug
|
|
help This help text
|
|
reload Reload *.conf in /etc/finit.d/ and activate changes
|
|
runlevel [0-9] Show or set runlevel: 0 halt, 6 reboot
|
|
status | show Show status of services
|
|
cond set <COND> Set (assert) condition => +COND
|
|
cond clear <COND> Clear (deassert) condition => -COND
|
|
cond flux <COND> Emulate flux condition => ~COND
|
|
cond show Show condition status
|
|
start <JOB|NAME>[:ID] Start service by job# or name, with optional ID
|
|
stop <JOB|NAME>[:ID] Stop/Pause a running service by job# or name
|
|
restart <JOB|NAME>[:ID] Restart (stop/start) service by job# or name
|
|
reload <JOB|NAME>[:ID] Reload (SIGHUP) service by job# or name
|
|
version Show Finit version
|
|
```
|
|
|
|
The `<!>` notation to a service stanza can be used empty, then it will
|
|
apply to `reload` and `runlevel` commands. I.e., when a service's
|
|
`.conf` file has been changed Finit will stop and start it instead. If
|
|
a service does *not* have `<!>` declared, the service will be reloaded
|
|
(`SIGHUP`:ed) in the `START` phase instead. The latter is the preferred
|
|
behaviour, but not all daemons support this, unfortunately.
|
|
|
|
**Note:** even though it is possible to start services not belonging to
|
|
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.
|
|
|
|
```shell
|
|
~ $ initctl status -v
|
|
1 running 476 [S12345] /sbin/watchdog -T 16 -t 2 -F /dev/watchdog
|
|
2 running 477 [S12345] /sbin/syslogd -n -b 3 -D
|
|
3 running 478 [S12345] /sbin/klogd -n
|
|
4:1 inetd 0 [2345] internal time allow *:37
|
|
4:2 inetd 0 [2345] internal time allow *:37
|
|
4:3 inetd 0 [2345] internal 3737 allow *:3737
|
|
5:1 inetd 0 [2345] /sbin/telnetd allow *:23 deny eth0,eth1
|
|
5:2 inetd 0 [2345] /sbin/telnetd allow eth0:2323,eth2:2323,eth1:2323
|
|
6:1 inetd 0 [345] /sbin/dropbear allow eth0:222
|
|
6:2 inetd 0 [345] /sbin/dropbear allow *:22 deny eth0
|
|
```
|
|
|
|
Running
|
|
-------
|
|
|
|
Having successfully [built Finit](doc/build.md) it may now be time to
|
|
take it for a test drive. The `make install` attempts to set up finit
|
|
as the system system init, `/sbin/init`, but this is usually a symlink
|
|
pointing to the current init.
|
|
|
|
So either change the symlink, or change your boot loader (GRUB, LOADLIN,
|
|
LILO, U-Boot/Barebox or RedBoot) configuration to append the following
|
|
to the kernel command line:
|
|
|
|
```shell
|
|
init=/sbin/finit
|
|
```
|
|
|
|
Remember to also set up an initial `/etc/finit.conf` before rebooting!
|
|
|
|

|
|
|
|
|
|
Debugging
|
|
---------
|
|
|
|
Add `finit_debug`, or `--debug`, to the kernel command line to enable
|
|
debug messages. See the output from `configure --help` for more on
|
|
how to assist debugging.
|
|
|
|
```shell
|
|
init=/sbin/finit --debug
|
|
```
|
|
|
|
|
|
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 Nilsson][] at [GitHub][].
|
|
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]: http://cr.yp.to/daemontools.html
|
|
[3]: http://smarden.org/runit/
|
|
[4]: http://en.wikipedia.org/wiki/Init
|
|
[5]: http://en.wikipedia.org/wiki/Runlevel
|
|
[9]: https://github.com/troglobit/troglos
|
|
[run-parts(8)]: http://manpages.debian.org/cgi-bin/man.cgi?query=run-parts
|
|
[original finit]: http://helllabs.org/finit/
|
|
[EeePC fastinit]: http://wiki.eeeuser.com/boot_process:the_boot_process
|
|
[Claudio Matsuoka]: https://github.com/cmatsuoka
|
|
[Joachim Nilsson]: http://troglobit.com
|
|
[GitHub]: https://github.com/troglobit/finit
|
|
[Travis]: https://travis-ci.org/troglobit/finit
|
|
[Travis Status]: https://travis-ci.org/troglobit/finit.png?branch=master
|
|
[Coverity Scan]: https://scan.coverity.com/projects/3545
|
|
[Coverity Status]: https://scan.coverity.com/projects/3545/badge.svg
|
|
|
|
<!--
|
|
-- Local Variables:
|
|
-- mode: markdown
|
|
-- End:
|
|
-->
|