FINIT.CONF(5)
πΈ NAME πΈ
finit.conf β the Finit configuration file format, aka the vibe manual for this whole page π
(yes bestie, this is FINIT.CONF(5) from the System Manager's Manual, and it is long, so strap in)
π¦ SYNOPSIS π¦
/etc/finit.conf
/etc/finit.d/*.conf
/etc/finit.d/available/*.conf
/etc/finit.d/enabled/*.conf
β¨ DESCRIPTION β¨
okay so, if you're running a Finit based system you can literally set the whole thing up with one single file: /etc/finit.conf. That's the traditional way of doing it, and ngl it can be ideal for some setups because you get a gorgeous overview of your entire system configuration in one place π«Ά
But the more comprehensive setups? Those need more careful planning. The recommendation is per-package *.conf files living in /etc/finit.d/available/. Why? Because it lets end users enable and disable parts of the system config at runtime π₯
Here's the cute part: Finit tracks which tasks and services belong to a given file, so when the user calls initctl reload to activate the changes they made, only the affected tasks and services get stopped, started, or restarted. No collateral damage. Hence, this approach is useful for modern package-based Linux distributions π
The sections below go deep on all of this β starting with files, then the file format, then the available directives. And remember to also visit the other manual pages too (references at the bottom, iykyk).
π FILES π
/etc/finit.confβ main configuration file, optional/etc/finit.d/*.confβ static (system) service definitions/etc/finit.d/available/*.confβ available (installed) services/etc/finit.d/enabled/*.confβ enabled services (symlink back)
Static services, the .conf files in /etc/finit.d/, cannot be enabled or disabled using initctl [enable | disable] service[.conf]. An enabled service is a symlink back to the corresponding ../available/ service .conf file. Please use the initctl tool to manage these symlinks so everything operates properly π
NOTE: Previous versions of Finit created symlinks in/etc/finit.d/if/etc/finit.d/enabled/was missing β as of v4.4 this is not supported. π
π FILE FORMAT π
The file format is line based. Empty lines and comments β lines starting with # β are ignored. A configuration directive starts with a keyword, followed by a space, and the rest of the line is treated as the value. Simple as π
As of Finit v4.4, configuration directives can be broken up in multiple lines using the continuation character \, and trailing comments are allowed too. Iconic. Example:
# Escape \# chars if you want them literal in, e.g., descriptions
service name:sysklogd [S123456789] \
env:-/etc/default/sysklogd \
syslogd -F $SYSLOGD_ARGS \
-- System log daemon \# 1 # Comments allowed now
π DIRECTIVES π
This section lists all supported configuration directives. There also exist deprecated directives β see the Markdown documentation for details on those.
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 the 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're in the same .conf π«Ά
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. All the others can be used by operating system administrators. Default: 2
It's recommended to keep runlevel 1 as single-user mode, because finit.conf disables networking in this mode.
Note: only read and executed in runlevel S (bootstrap).
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. Usually only used in the bootstrap (S) runlevel β¨
β¨CONDβ© conditions are described in finit(8), see also the "Examples" section below.
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
sysv [LVLS] β¨CONDβ© /path/to/script ARGS [-- Optional description]
Similar to service is the sysv directive, which can be used to call SysV style start/stop scripts. The primary intention for this command is to be able to re-use traditional SysV init scripts in Linux distributions π
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 the sysv stanza is declared gets modified, Finit calls init-script restart on initctl reload. Similar to how service directives work.
Forking services started with sysv scripts can be monitored by Finit by declaring the PID file to look for:
sysv pid:!/path/to/pidfile.pid /path/to/script ...
The leading '!' is to prevent Finit from managing the PID file, which is the default behavior for the pid: command modifier.
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 restarted manually using initctl restart NAME. The number of restarts, the delay between each restart, and more is configurable β see the options below π
Tip: to allow endless restarts, see below option respawn
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 command modifier syntax. There is an alternative syntax that may be more intuitive, where Finit can also guess the PID file based on the daemon's command name:
service type:forking ntpd -- NTP daemon
Here we let BusyBox ntpd daemonize itself. Finit uses the basename of the binary to guess the PID file to watch for the PID: /var/run/ntpd.pid. If Finit guesses wrong, you have to submit the full pid:!/path/to/file.pid option to your service stanza.
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 runlevel 2-5 if omitted.
<pid/zebra> 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, */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 modifier 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(3) of the service. The full syntax of the pid modifier is:
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 the <pid/bar> condition π
As an alternative "readiness" notification, Finit supports both systemd and s6 style notification. This can be enabled by using the notify option:
notify:systemd tells Finit the service uses the sd_notify() API to signal PID 1 when it has completed its startup and is ready to service events. This API expects the environment variable NOTIFY_SOCKET to be set to the socket where the application can send READY=10 when it is starting up or has processed a SIGHUP. For details, see:
https://www.freedesktop.org/software/systemd/man/sd_notify.html
notify:s6 puts Finit in s6 compatibility mode. Compared to the systemd notification, s6 expect compliant daemons to send 0 and then close their socket. For details, see:
https://skarnet.org/software/s6/notifywhenup.html
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 notify:s6 mdevd -C -O 4 -D %n
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
If a service should not be automatically started, it can be configured as manual with the manual:yes command modifier. The service can then be started at any time by running initctl start NAME π¦
The name of a service, shown by the initctl tool, defaults to the basename of the service executable. It can be changed with the name:foo command modifier.
As mentioned previously, services are automatically restarted should they crash, this is configurable with the following options:
restart:NUMβ how many times Finit will try to bring a crashing service back up, default is10. Hit that ceiling and the service gets marked crashed, and from then on it's manual only β you gotta go wake it up yourself withinitctl(8). πrestart_sec:SECβ the gap in seconds before Finit retries a crashing service, default is 2 seconds for the first five retries, then it backs off to 5 seconds. And here's the tea: whichever is bigger, your configured value or those built-in ones (2and5), is what actually gets used.restart:alwaysβ no upper limit on retries, bestie, go absolutely feral. Exactly the same asrestart:-1. π₯norestartβ don't restart on failures, periodt. Same asrestart:0.respawnβ completely bypasses the restart mechanism, allows endless restarts. Super useful in lots of use-cases, but it's not whatservicewas originally designed for, so it's not the default behavior. πoncrash:rebootβ when every single retry has failed and the service has crashed, and this option is set, the whole system gets rebooted.oncrash:scriptβ same vibe asoncrash:reboot, except instead of rebooting, this action calls thepost:script(peep below π) so the operator can decide the best course of action. If thepost:scriptoption isn't set, this is a no-op.
The post:script gets called with the same environment variables, except EXIT_CODE is set to crashed.
reload:'script [args]'β some services don't supportSIGHUPbut have other ways to update the config of a running daemon. Whenreload:scriptis defined, it's preferred overSIGHUP. Like systemd, finit sets$MAINPIDas a convenience to scripts, which in effect also lets you doreload:'kill -HUP $MAINPID'. β¨stop:'script [args]'β some services need alternate methods to be stopped. Whenstop:scriptis defined, it's preferred overSIGTERMandstop, forserviceandsysvdirectives respectively. Same asreload:script, finit sets$MAINPIDfor you.
When stopping a service (run/task/sysv/service), whether you're doing it manually or moving to another runlevel, Finit starts by sending SIGTERM so the process can shut down gracefully. If the process hasn't been collected within 3 seconds, Finit sends SIGKILL. Want a different signal? Use the command modifier halt:SIGNAL, e.g. halt:SIGPWR. Want to change the delay between your halt signal and the KILL? Use kill:SEC, e.g. kill:10 to wait 10 seconds before sending SIGKILL. π
Services β and yes, the sysv variant too β support pre/post/ready and cleanup scripts:
pre:[0-3600,]scriptβ called before thesysv/serviceis startedpost:[0-3600,]scriptβ called after thesysv/servicehas stoppedready:[0-3600,]scriptβ called when thesysv/serviceis readycleanup:[0-3600,]scriptβ called whenrun/task/sysv/serviceis removed
That optional number (0-3600) is the timeout before Finit kills the script. It defaults to the kill delay value, and you can disable it by setting it to zero. These scripts run as the same @USER:GROUP as the service itself, with any env:file sourced. The scripts must use an absolute path, but they're executed from the $HOME of the given user. They're not called with any argument, but both get a set of environment variables:
SERVICE_IDENT=foo:1
SERVICE_NAME=foo
SERVICE_ID=1
The post:script gets an additional set of environment variables β and yes, the naming looks like it should be swapped, we know, it's giving chaos but it's canon:
EXIT_CODE=[exited,signal,crashed]β set to one ofexited,signal, orcrashed(see above).EXIT_STATUS=[num,SIGNAME]β set to one of exit status code from the program, if it exited normally, or the signal name (HUP,TERM, etc.) if it exited due to signal
When a run/task/sys/service is removed (disable + reload) it is first stopped and then removed from the runlevel. The post:script always runs when the process has stopped, and the cleanup:script runs when the stanza has been removed from the runlevel. π§
π runparts β¨DIRβ©
Call run-parts(8) on DIR to run start scripts. Every executable file, or script, in the directory gets called, in alphabetic order. The scripts in this directory are executed at the very end of bootstrap, runlevel S.
It can be beneficial to use S01name, S02othername, etc. if there's a dependency order between the scripts. Symlinks to existing daemons can also be used, but make sure they daemonize by default.
Similar to the /etc/rc.local shell script, make sure all your services and programs either terminate or start in the background β otherwise you will block Finit. π
Note: only read and executed in runlevel S (bootstrap).
πΈ include β¨CONFβ©
Include another configuration file. Absolute path required.
β log size:BYTES count:NUM
Log rotation for run/task/services using the log command modifier 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 size: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.
π tty [LVLS] β¨CONDβ© DEV [BAUD] [noclear] [nowait] [nologin] [TERM]
This form of the tty directive uses the built-in getty on the given TTY device DEV, in the given runlevels. DEV may be the special keyword @console, or 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 directive inherits runlevel, condition (and other feature) parsing from the service directive. So TTYs can run in one or many runlevels and depend on any condition supported by Finit. This is useful e.g. to depend on <pid/elogind> before starting a TTY.
tty [12345] /dev/ttyAMA0 115200 noclear vt220
π tty [LVLS] β¨CONDβ© CMD DEV [noclear] [nowait]
This form of the tty directive is for using an external getty, like agetty or the BusyBox getty.
By default, these first two syntax variants clear the TTY and wait for the user to press enter before starting getty.
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 Please 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 it 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 whether 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.
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 directive to start a stand-alone shell:
service [12345] /bin/sh -l
π¦ tty [LVLS] β¨CONDβ© [notty] [rescue]
The third tty form 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. The flags 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.
π COMMAND MODIFIERS π
The run/task/tty/service/sysv directives take modifiers, or options, to control their behavior. This section lists them with their limitations. All modifiers must be placed between the directive and its command. π
@user:groupβ everyrun,task, orservicecan also list the privileges the/path/to/cmdshould 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. π
log:/path/to/fileβ redirect stdout/stderr of a command to the given log file. See the globallogdirective, above, for details on log rotation.log:consoleβ redirect stdout/stderr of a command to/dev/console, only use this for debugging or bringup.log:nullβ redirect stdout/stderr of a command to/dev/null.log:prio:facility.level,tag:identβ redirect stdout/stderr of a command to syslog using the given priority and tag identity.
service log:prio:user.warn,tag:ntpd /sbin/ntpd pool.ntp.org -- NTP daemon
logβ default prio isdaemon.infoand the default tag identity is the basename of the service orrun/taskcommand.
π RESCUE MODE π
Finit has a whole rescue mode, and you turn it on with the rescue option on the kernel command line. It comes in two flavors: traditional and fallback. Pick your fighter π
π Traditional π
This is the one everyone expects, fr. A super early maintenance login prompt, served by the bundled /libexec/finit/sulogin program β or the standard sulogin from util-linux or BusyBox, which Finit goes looking for in the UNIX default $PATH. If you log in successfully, or you exit (Ctrl-D), rescue mode ends and the system boots up normally like nothing happened. β¨
Note: if the user (UID 0 and GID 0) has no password, or the account is locked, you get a password-less prompt instead: Press enter to enter maintenance mode. β which opens up a root shell. No cap. π
π¦ Fallback π¦
If no sulogin program is found, Finit tries to bring up as much of its own functionality as it possibly can, while limiting a lot of aspects. Meaning: no network, no fsck of file systems in /etc/fstab, no /etc/rc.local, no runparts, and most plugins get skipped (except the ones 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 the system administrator can freely modify. Bestie, it's yours.
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? sulogin is started to query for root/admin password. If sulogin is not found, rescue behaves like notty and gives you 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. That's it. That's the vibe. You live here now. π
πΈ SERVICE ENVIRONMENT πΈ
Finit supports sourcing environment variables from /etc/default/*, or similar. This is a super 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 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 needs to run additional commands, executed before the service is actually started β like systemd's 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.
/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 supportSIGHUP. That way Finit will stop/start the service instead of sendingSIGHUPat restart/reload events. Iconic behaviour, honestly. π
π§ TEMPLATING π§
Finit comes with rudimentary support for templating, similar to that of systemd. Best illustrated with an example:
$ initctl show avahi-autoipd@
service :%i avahi-autoipd --syslog %i -- ZeroConf for %i
To enable ZeroConf for, e.g., eth0, use
$ initctl enable avahi-autoipd@eth0.conf
The enabled symlink will be set up to avahi-autoipd@.conf and every instance of %i will in the instantiated directive be replaced with eth0. Inspect the result with:
$ initctl status avahi-autoipd:eth0
β¨ It's giving templates. Obsessed. β¨
π CGROUPS π
There are three major cgroup configuration directives:
- Global top-level group:
init,system,user, or a custom group - Selecting a top-level group for a set of run/task/services
- 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 (notice the single quotes for arguments that contain spaces):
service [...] <...> cgroup.maint:cpu.max:'200000 100000',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. 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 covers this well: https://www.kernel.org/doc/html/latest/admin-guide/cgroup-v2.html
π₯ CONDITIONAL LOADING π₯
Finit supports conditional loading of stanzas. The following example is taken from the system/hotplug.conf file in the Finit distribution. Here we only show a simplified subset.
Starting with the nowarn option.
service nowarn name:udevd pid:udevd /lib/systemd/systemd-udevd
service nowarn name:udevd pid:udevd udevd
When loading the .conf file Finit looks for /lib/systemd/systemd-udevd β if that is not found Finit automatically logs a warning. The nowarn option disables this warning so that the second line can be evaluated, which also provides a service named udevd.
run nowarn if:udevd <pid/udevd> :1 udevadm settle -t 0
This line is only loaded if we know of a service named udevd. Again, we do not warn if udevadm is not found, and execution will also stop here until the PID condition is asserted, i.e., Finit detecting udevd has started.
run nowarn conflict:udevd [S] mdev -s -- Populating device tree
If udevd is not available, we try to run mdev, but if that is not found, again we do not warn.
Conditional loading statements can also be negated, so the previous stanza can also be written as:
run nowarn if:!udevd [S] mdev -s -- Populating device tree
The reason for using conflict in this example is that a conflict can be resolved. Stanzas marked with conflict: are rechecked at runtime. π
β CONDITIONAL EXECUTION β
Similar to conditional loading of stanzas there is conditional runtime execution. This can be confusing at first, since Finit already has a condition subsystem, but this is more akin to the qualification to a runlevel. E.g., a task [123] is qualified to run only in runlevel 1, 2, and 3. It is not considered for other runlevels.
Conditional execution qualifies a run/task/service based on a condition. Consider this (simplified) example from the Infix operating system:
run [S] name:startup <pid/sysrepo> confd -b --load startup-config
run [S] if:<usr/fail-startup> name:failure <pid/sysrepo> confd --load failure-config
The two run statements reside in the same .conf file so Finit runs them in true sequence. If loading the file startup-config fails confd sets the condition usr/fail-startup, thus allowing the next run statement to load failure-config.
Notice the critical difference between the <pid/sysrepo> condition and if:<usr/fail-startup>. The former is a condition for starting and the latter is a condition to check if a run/task/service is qualified to even be considered. Big difference, bestie. π
Conditional execution statements can also be negated, so provided the file loaded did the opposite, i.e., set a condition on success, the previous stanza can also be written as:
run [S] if:<!usr/startup-ok> name:failure <pid/sysrepo> confd ...
π 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,
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. Go off, honestly. π
π SEE ALSO π
π AUTHORS π
Finit was conceived and reverse engineered by Claudio Matsuoka. Since v1.0, maintained by Joachim Wiberg, with contributions by many others. Legends only. π
And that's the whole page, bestie β this one's from the Linux release, dated July 10, 2025, and it's filed under FINIT.CONF(5). Go forth and init, you absolute icon. πβ¨π
π¦ where this page comes from
- ubuntu resolute: finit 4.14-1 Β· MIT
- ubuntu stonking: finit 4.14-1 Β· MIT
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms