A service that drops privileges cannot create its own PID file in /run, root owns it. Finit can create the file with pidfile-create, but the daemon still cannot touch it to confirm a SIGHUP. Five new settings, block format only: runtime-dir, state-dir, cache-dir, logs-dir, and config-dir. The value is a directory name, resolved under /run, /var/lib, /var/cache, /var/log, and /etc, respectively. The directory is created before the service starts, mode 0755 owned by user/group, and the full path is exported to the process as RUNTIME_DIRECTORY, STATE_DIRECTORY, CACHE_DIRECTORY, LOGS_DIRECTORY, and CONFIGURATION_DIRECTORY. Mode and ownership are asserted at creation only, a daemon may tighten them afterwards. The runtime directory is removed when the unit stops, after any exec-stop-post script, like systemd with RuntimeDirectoryPreserve=no. A completed run/task counts as stopped unless remain-after-exit keeps it up. The other four persist across restarts. These are the first settings with no legacy token: they are validated by service_set_dir() and stored on the svc that service_register() now returns. systemd accepts a list of directories per setting; this is a single name for now, widening later is compatible since libconfuse accepts a bare value for a list option. The test sysroot gains libnss_files.so.2, which ldd cannot see, glibc dlopen()s it. Without it getpwnam() fails inside the chroot, so user/group settings never resolved and directory ownership could not be tested. Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
8.4 KiB
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 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 sectioncgroup NAME {}-- see the Cgroups sectionenvfile-- see the Service Environment sectionlog {}-- see Redirecting Outputtty-- see Controlling TTYnotify-- see Service Synchronizationif-- see Conditional Executiontype = "forking"-- see description of the service block- a leading
-oncommand-- see Conditional Loading
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 withinitctl restart NAMErestart-sec = SEC-- number of seconds before Finit tries to restart a crashing service. The default is 2 seconds for the first half ofrestart-maxattempts, then a back-off to 5 seconds -- with the defaultrestart-maxthat is the first five retries. The greater of this configured value and the back-off is usedrestart = "always"-- no upper limit on the number of times Finit tries to restart a crashing servicerestart = "never"-- do not restart on failures.falseis accepted as a synonym, andtrueselects the default policyrespawn = true-- bypasses therestartmechanism 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 attybehaves; it is not whatservicewas designed for, so it is not the defaultremain-after-exit = true-- forrunandtaskonly. Prevents the task from re-running on runlevel re-entry and ensures theexec-stop-postscript runs when the task is explicitly stopped or leaves its valid runlevels. This is systemd'sRemainAfterExit=. See Task and Run for more detailsoncrash = "reboot"-- when all retries have failed, and the service has crashed, the system is rebootedoncrash = "script"-- similarly, but instead of rebooting, call theexec-stop-postscript with exit codecrashed, 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.
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.
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 ofSIGTERMstop-timeout = 10-- seconds to wait beforeSIGKILL, 1-300
Some services need more than a signal:
exec-stop = "script [args]"-- run instead of sending the stop signal, and instead ofstopforsysvexec-reload = "script [args]"-- run instead of sendingSIGHUP. Like systemd, Finit sets$MAINPIDas a convenience to scripts, which in effect also allowsexec-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 startedexec-start-ready-- called when the sysv/service is readyexec-stop-- called instead of the stop signalexec-stop-post-- called after the sysv/service has stoppedexec-reload-- called instead ofSIGHUPexec-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:1SERVICE_NAME=fooSERVICE_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 crashedEXIT_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.