DINIT-SERVICE(5)

NAME
Dinit service description files

SYNOPSIS
/etc/dinit.d/service-name, $HOME/dinit.d/service-name

DESCRIPTION
The service description files for Dinit each describe a service. The name of the file corresponds to the name of the service it describes.

Service description files specify the various attributes of a service. A service description file is named after the service it represents, and is a plain-text file with simple key-value format. The description files are located in a service description directory; by default, the system process searches /etc/dinit.d, /usr/local/lib/dinit.d and /lib/dinit.d, while a user process searches $HOME/dinit.d.

All services have a type and a set of dependencies. These are discussed in the following subsections. The type, dependencies, and other attributes are specified via property settings, the format of which are documented in the SERVICE PROPERTIES subsection, which also lists the available properties.

  SERVICE TYPES
There are four basic types of service:

•   Process services. This kind of service runs as a single process; starting the service simply requires starting the process; stopping the service is accomplished by stopping the process (via sending it a signal).

•   Bgprocess services ("background process" services). This kind of service is similar to a regular process service, but the process daemonizes or otherwise forks from the original process which starts it, and the process ID is written to a file. Dinit can read the process ID from the file and, if it is running as the system init process, can supervise it.

•   Scripted services are services which are started and stopped by a command (which need not actually be a script, despite the name). They can not be supervised.

•   Internal services do not run as an external process at all. They can be started and stopped without any external action. They are useful for grouping other services (via service dependencies).

Independent of their type, the state of services can be linked to other services via dependency relationships, which are discussed in the next section.

  SERVICE DEPENDENCIES
A service dependency relationship, broadly speaking, specifies that for one service to run, another must also be running. The first service is the dependent service and the latter is the dependency service (we will henceforth generally refer to the the dependency relationship as the relationship and use dependency to refer to the service). A dependency relationship is specified via the properties of the dependent. There are different relationship types, as follows:

•   A need (or "hard") relationship specifies that the dependent must wait for the dependency to be started before it starts, and that the dependency must remain started while the dependent is started. Starting the dependent will start the dependency, and stopping the dependency will stop the dependent. This type of relationship is specified using a depends-on property.

•   A milestone relationship specifies that the dependency must start successfully before the dependent starts. Starting the dependent will therefore start the dependency. Once started, the relationship is satisfied; if the dependency then stops, it has no effect on the dependent. However, if the dependency fails to start or has its startup cancelled, the dependent will not start (and will return to the stopped state). This type of relationship is specified using a depends-ms property.

•   A waits-for relationship specifies that the dependency must start successfully, or fail to start, before the dependent starts. Starting the dependent will attempt to first start the dependency, but failure will not prevent the dependent from starting. If the dependency starts, stopping it will have no effect on the dependent. This type of relationship is specified using a waits-for property.

Note that process-based services always wait for their dependency relationships to be satisfied (by the dependency starting, or failing to start in case of a waits-for relationship) before their process is launched. Conversely, a termination signal will not in general be sent to a service process until the service has no active dependents.

Since in general dependencies should remain started so long as their dependent does, an attachment forms between the two once both are started. This attachment is released when the dependent stops, and the dependency will then stop, unless it has other attachments or it has been explicitly started independently. Attachments between a dependent and dependency are re-created if a dependency starts (or starts again) while the dependent is still started.

  SERVICE PROPERTIES
This section described the various service properties that can be specified in a service description file. The properties specify the type of the service, dependencies of the service, and other service configuration.

Each line of the file can specify a single property value, expressed as "property-name = value". Comments begin with a hash mark (#) and extend to the end of the line (they must be separated from setting values by at least one whitespace character). Values are interpreted literally, except that:

•   White space (comprised of spaces, tabs, etc) is collapsed to a single space, except leading or trailing white space around the property value, which is stripped.

•   Double quotes (") can be used around all or part of a property value, to prevent whitespace collapse and prevent interpretation of other special characters (such as "#") inside the quotes. The quote characters are not considered part of the parameter value.

•   A backslash (\) can be used to escape the next character, causing it to lose any special meaning and become part of the property value. A double backslash (\\) is collapsed to a single backslash within the parameter value.

The following properties can be specified:

type = {process | bgprocess | scripted | internal}
    Specifies the service type; see the SERVICE TYPES section.

command = command-string
    Specifies the command, including command-line arguments, for starting the process. Applies only to process, bgprocess and scripted services.

stop-command = command-string
    Specifies the command to stop the service. Applicable only to scripted services.

working-dir = directory
    Specifies the working directory for this service. For a scripted service, this affects both the start command and the stop command.

run-as = user-id
    Specifies which user to run the process(es) for this service as. Specify as a username or numeric ID. If specified by name, the group for the process will also be set to the primary group of the specified user.

restart = {yes | true | no | false}
    Indicates whether the service should automatically restart if it stops for any reason (including unexpected process termination, service dependency stopping, or user-initiated service stop).

smooth-recovery = {yes | true | no | false}
    Applies only to process and bgprocess services. When set true/yes, an automatic process restart can be performed without first stopping any dependent services. This setting is meaningless if the restart setting is set to false.

restart-delay = XXX.YYYY
    Specifies the minimum time between automatic restarts. Enforcing a sensible minimum prevents Dinit from consuming a large number of process cycles in case a process continuously fails immediately after it is started. The default is 0.2 (200 milliseconds).

restart-limit-interval = XXX.YYYY
    Sets the interval, in seconds, over which restarts are limited. If a process automatically restarts more than a certain number of times (specified by the restart-limit-count setting) in this time interval, it will not restart again. The default value is 10 seconds.

restart-limit-count = NNN
    Specifies the maximum number of times that a service can automatically restart over the interval specified by restart-limit-interval. Specify a value of 0 to disable the restart limit.

start-timeout = XXX.YYY
    Specifies the time in seconds allowed for the service to start. If the service takes longer than this, its process group is sent a SIGINT signal and enters the "stopping" state (this may be subject to a stop timeout, as specified via stop-timeout, after which the process group will be terminated via SIGKILL). The timeout period begins only when all dependencies have been stopped. The default timeout is 60 seconds. Specify a value of 0 to allow unlimited start time.

stop-timeout = XXX.YYY
    Specifies the time in seconds allowed for the service to stop. If the service takes longer than this, its process group is sent a SIGKILL signal which should cause it to terminate immediately. The timeout period begins only when all dependent services have already stopped. The default timeout is 10 seconds. Specify a value of 0 to allow unlimited stop time.

pid-file = path-to-file
    For bgprocess type services only; specifies the path of the file where daemon will write its process ID before detaching. Dinit will read the contents of this file when starting the service, once the initial process exits, will supervise the process with the discovered process ID, and may send signals to the process ID to stop the service; if Dinit runs as a privileged user the path should therefore not be writable by unprivileged users.

depends-on = service-name
    This service depends on the named service. Starting this service will start the named service; the command to start this service will not be executed until the named service has started. If the named service is stopped then this service will also be stopped.

depends-ms = service-name
    This service has a "milestone" dependency on the named service. Starting this service will start the named service; this service will not start until the named service has started, and will fail to start if the named service does not start. Once the named service reaches the started state, however, the dependency is effectively dropped until this service is next started.

waits-for = service-name
    When this service is started, wait for the named service to finish starting (or to fail starting) before commencing the start procedure for this service. Starting this service will automatically start the named service. If the named service fails to start, this service will start as usual (subject to other dependencies being met).

waits-for.d = directory-path
    For each file name in directory-path which does not begin with a dot, add a waits-for dependency to the service with the same name. Note that contents of files in the specified directory are not significant; expected usage is to have symbolic links to the associated service description files, but this is not required. Failure to read the directory contents, or to find any of the services named within, is not considered fatal. The directory path, if not absolute, is relative to the directory containing the service description file.

chain-to = service-name
    When this service terminates (i.e. starts successfully, and then stops of its own accord), the named service should be started. Note that the named service is not loaded until that time; naming an invalid service will not cause this service to fail to load. This can be used for a service that supplies an interactive "recovery mode" for another service; once the user exits the recovery shell, the primary service (as named via this setting) will then start. It also supports multi-stage system startup where later service description files reside on a separate filesystem that is mounted during the first stage; such service descriptions will not be found at initial start, and so cannot be started directly, but can be chained via this directive. The chain is not executed if the initial service was explicitly stopped, stopped due to a dependency stopping (for any reason), if it will restart (including due to a dependent restarting), or if its process terminates abnormally or with an exit status indicating an error. However, if always-chain option is set the chain is started regardless of the reason and the status of this service termination.

socket-listen = socket-path
    Pre-open a socket for the service and pass it to the service using the systemd activation protocol. This by itself does not give so called "socket activation", but does allow that any process trying to connect to the specified socket will be able to do so, even before the service is properly prepared to accept connections.

socket-permissions = octal-permissions-mask
    Gives the permissions for the socket specified using socket-listen. Normally this will be 600 (user access only), 660 (user and group access), or 666 (all users). The default is 666.

socket-uid = {numeric-user-id | username}
    Specifies the user (name or numeric ID) that should own the activation socket. If socket-uid is specified as a name without also specifying socket-gid, then the socket group is the primary group of the specified user (as found in the system user database, normally /etc/passwd). If the socket-uid setting is not provided, the socket will be owned by the user id of the dinit process.

socket-gid = {numeric-group-id | group-name}
    Specifies the group of the activation socket. See discussion of socket-uid.

term-signal = {none | HUP | INT | TERM | QUIT | USR1 | USR2 | KILL}
    Specifies the signal to send to the process when requesting it to terminate (applies to 'process' and 'bgprocess' services only). The default is SIGTERM. See also stop-timeout.

ready-notification = {pipefd:fd-number | pipevar:env-var-name}
    Specifies the mechanism, if any, by which a process service will notify that it is ready (successfully started). If not specified, a process service is considered started as soon as it has begun execution. The two options are:

    •   pipefd:fd-number — the service will write a message to the specified file descriptor, which dinit sets up as the write end of a pipe before execution. This mechanism is compatible with the S6 supervision suite.

    •   pipevar:env-var-name — the service will write a message to file descriptor identified using the contents of the specified environment variable, which will be set by dinit before execution to a file descriptor (chosen arbitrarily) attached to the write end of a pipe.

logfile = log-file-path
    Specifies the log file for the service. Output from the service process will go this file.

options = option...
    Specifies various options for this service. See the OPTIONS section. This directive can be specified multiple times to set additional options.

load-options = load_option...
    Specifies options for interpreting other settings when loading this service description. Currently there is only one available option, sub-vars, which specifies that command line arguments in the form of $NAME should be replaced with the contents of the environment variable with the specified name. Note that no word-splitting is performed and the variable value always becomes a single argument; if the variable is not defined, it is replaced with an empty (zero-length) argument.

inittab-id = id-string
    When this service is started, if this setting (or the inittab-line setting) has a specified value, an entry will be created in the system "utmp" database which tracks processes and logged-in users. Typically this database is used by the "who" command to list logged-in users. The entry will be cleared when the service terminates. The inittab-id setting specifies the "inittab id" to be written in the entry for the process. The value is normally quite meaningless. However, it should be distinct (or unset) for separate processes. It is typically limited to a very short length. The "utmp" database is mostly a historical artifact. Access to it on some systems is prone to denial-of-service by unprivileged users. It is therefore recommended that this setting not be used. However, "who" and similar utilities may not work correctly without this setting (or inittab-line) enabled appropriately. This setting has no effect if Dinit was not built with support for writing to the "utmp" database.

inittab-line = tty-name-string
    This specifies the tty line that will be written to the "utmp" database when this service is started. Normally, for a terminal login service, it would match the terminal device name on which the login process runs, without the "/dev/" prefix. See the description of the inittab-id setting for details.

rlimit-nofile = resource-limits
    Specifies the number of file descriptors that a process may have open simultaneously. See the RESOURCE LIMITS section.

rlimit-core = resource-limits
    Specifies the maximum size of the core dump file that will be generated for the process if it crashes (in a way that would result in a core dump). See the RESOURCE LIMITS section.

rlimit-data = resource-limits
    Specifies the maximum size of the data segment for the process, including statically allocated data and heap allocations. Precise meaning may vary between operating systems. See the RESOURCE LIMITS section.

rlimit-addrspace = resource-limits
    Specifies the maximum size of the address space of the process. See the RESOURCE LIMITS section. Note that some operating systems (notably OpenBSD) do not support this limit; the setting will be ignored on such systems.

  OPTIONS
These options are specified via the options parameter.

runs-on-console
    Specifies that this service uses the console; its input and output should be directed to the console (or precisely, to the device to which Dinit's standard output stream is connected). A service running on the console prevents other services from running on the console (they will queue for the console). The interrupt key (normally control-C) will be active for process / scripted services that run on the console. Handling of an interrupt is determined by the service process, but typically will cause it to terminate.

starts-on-console
    Specifies that this service uses the console during service startup. This is implied by runs-on-console, but can be specified separately for services that need the console while they start but not afterwards. This setting is not applicable to regular process services, but can be used for scripted and bgprocess services. It allows for interrupting startup via the interrupt key (normally control-C). This is useful to allow filesystem checks to be interrupted/skipped. This option is implied by runs-on-console, and is mutually exclusive with shares-console; setting this option, or setting runs-on-console, unsets shares-console.

shares-console
    Specifies that this service should be given access to the console (input and output will be connected to the console), but that it should not exclusively hold the console and not delay the start of services with starts-on-console. This is mutually exclusive with both starts-on-console and runs-on-console; setting this option unsets both those options.

starts-rwfs
    This service mounts the root filesystem read/write (or at least mounts the normal writable filesystems for the system). This prompts Dinit to create its control socket, if it has not already managed to do so.

starts-log
    This service starts the system log daemon. Dinit will begin logging via the /dev/log socket.

pass-cs-fd
    Pass an open Dinit control socket to the process when launching it (the DINIT_CS_FD environment variable will be set to the file descriptor of the socket). This allows the service to issue commands to Dinit even if the regular control socket is not available yet. Using this option has security implications! The service which receives the control socket must close it before launching any untrusted processes. You should not use this option unless the service is designed to receive a Dinit control socket.

start-interruptible
    This service can have its startup interrupted (cancelled) if it becomes inactive while still starting, by sending it the SIGINT signal. This is meaningful only for bgprocess and scripted services.

skippable
    For scripted services, indicates that if the service startup process terminates via an interrupt signal (SIGINT), then the service should be considered started. Note that if the interrupt was issued by Dinit to cancel startup, the service will instead be considered stopped.

signal-process-only
    Signal the service process only, rather than its entire process group, whenever sending it a signal for any reason.

always-chain
    Alters behavior of chains-to property forcing the chained service to always start on termination of this service.

The next section contains example service descriptions including some of the parameters and options described above.

  RESOURCE LIMITS
There are several settings for specifying process resource limits: rlimit-nofile, rlimit-core, rlimit-data and rlimit-addrspace. See the descriptions of each above. These settings place a limit on resource usage directly by the process. Note that resource limits are inherited by subprocesses, but that usage of a resource and subprocess are counted separately (in other words, a process can effectively bypass its resource limits by spawning a subprocess and allocating further resources within it). Resources have both a hard and soft limit. The soft limit is the effective limit, but note that a process can raise its soft limit up to the hard limit for any given resource. Therefore the soft limit acts more as a sanity-check; a process can exceed the soft limit only by deliberately raising it first. Resource limits are specified in the following format:
    soft-limit:hard-limit
Either the soft limit or the hard limit can be omitted (in which case it will be unchanged). A limit can be specified as a dash, `-', in which case the limit will be removed. If only one value is specified with no colon separator, it affects both the soft and hard limit.

  EXAMPLES

Here is an example service description for the mysql database server. It has a dependency on the rcboot service (not shown) which is expected to have set up the system to a level suitable for basic operation.
    # mysqld service
    type = process
    command = /usr/bin/mysqld --user=mysql
    logfile = /var/log/mysqld.log
    smooth-recovery = true
    restart = false
    depends-on = rcboot # Basic system services must be ready

Here is an examples for a filesystem check "service", run by a script (/etc/dinit.d/rootfscheck.sh). The script may need to reboot the system, but the control socket may not have been created, so it uses the pass-cs-fd option to allow the reboot command to issue control commands to Dinit. It runs on the console, so that output is visible and the process can be interrupted using control-C, in which case the check is skipped but dependent services continue to start.
    # rootfscheck service
    type = scripted
    command = /etc/dinit.d/rootfscheck.sh
    restart = false
    options = starts-on-console pass-cs-fd
    options = start-interruptible skippable
    depends-on = early-filesystems  # /proc and /dev
    depends-on = device-node-daemon
More examples are provided with the Dinit distribution.

AUTHOR
Dinit, and this manual, were written by Davin McCall.