123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347 |
- Dinit
- -----
- v0.05 (pre-release)
- What is it?
- =-=-=-=-=-=
- "Dinit" is a service supervisor with dependency support which can also
- act as the system "init" program.
- Specifically it can launch multiple services (generally, "daemon" processes,
- but see notes below) in parallel, with dependency management (i.e. if one
- service's operation depends on another, the latter service will be started
- first).
- For "process" services Dinit can monitor the process corresponding to the
- service, and re-start it if it dies. It does this in an intelligent way,
- first "rolling back" all dependent services, and restarting them when their
- dependencies are satisfied.
- Dinit includes a tool ("dinitctl") to issue commands to the main Dinit
- process, and a "shutdown" program (with scripts "halt" and "reboot") to
- manage shutting down and restarting the system.
- Dinit is designed to work on POSIXy operating systems such as Linux and
- OpenBSD. It is written in C++ and uses the "Dasynq" event handling library,
- which was written especially to support Dinit.
- Development goals include clean design, robustness, portability, and
- avoiding feature bloat (whilst still handling a variety of use cases).
- See doc/COMPARISON for a comparison of Dinit with similar software packages.
- Dinit is licensed under the Apache License, version 2.0. A copy of this
- license can be found in the LICENSE file.
- Dinit was written by Davin McCall <davmac@davmac.org>.
- See BUILD for information on how to build Dinit.
- Introduction to services
- =-=-=-=-=-=-=-=-=-=-=-=-
- A "service" is nominally a persistent process or system state. The two main
- types of service are a _process_ service (represented by a an actual process)
- and a _scripted_ service (which is started and stopped by running a process -
- often a shell script - to completion). There are also _bgprocess_ services
- and _internal_services.
- Many programs that you might want to run under dinit's supervision can run
- either "in the foreground" or as a daemon ("in the background"), and the
- choice is dictated by a command line switch (for instance the -D and -F
- switches to Samba's "smbd"). Although it might seem counterintuitive,
- the "foreground" mode should be used for programs registered as process
- services in dinit; this allows dinit to monitor the process.
- Process services are attractive due to the ease of monitoring (and
- restarting) the service, however, they have one inherent problem, which is
- that dinit cannot tell when the service is truly started. Once the process
- has been launched, dinit assumes that the service has started, but in fact
- there will be a short delay before the process sets itself up, starts
- listening on sockets, etc; during this time any other process (including
- one from a service listed as dependent) which tries to contact it will not
- be able to do so. In practice, this is not usually a problem (and external
- solutions, like D-Bus, do exist).
- A _scripted_ service has separate commands for startup and (optional)
- shutdown. Scripted services can be used for tasks such as mounting file
- systems that don't need a persisten process, and in some cases can be used
- for daemon processes (although Dinit will not be able to supervise a
- process that is registered as a scripted service).
- A _bgprocess_ service is a mix between a process service and a scripted
- service. A command is used to start the service, and once started, the
- process ID is expected to be available in a file which Dinit can then
- read. Many existing daemons can operate in this way. The process can only be
- supervised if Dinit runs as the system "init" (PID 1) - otherwise Dinit can
- not reliably know when the process has terminated.
- (Note, use of bgprocess services type requires care. The file from which the
- PID is read is trusted; Dinit may send signals to the specified PID. It
- should not be possible for unauthorised users to modify the file contents!)
- An _internal_ service is just a placeholder service that can be used to
- describe a set of dependencies. An internal service has no corresponding
- process.
- Service Hiearchy and states
- =-=-=-=-=-=-=-=-=-=-=-=-=-=
- Services can depend on other services for operation, and so form a
- dependency hierarchy. Starting a service which depends on another
- causes that other service to start (and the first service waits until
- the latter has started before its process is launched and it is itself
- considered started).
- Services are considered _active_ when they are not stopped. Services
- can also be explicitly marked as active (this normally happens when you
- explicitly start a service). Finally, a service with an active dependent
- is also considered active.
- If a service stops and becomes inactive (i.e. it is not explicitly marked
- active and has no active dependents) then any services it depends on will
- also be marked inactive and stopped unless they have other active
- dependents, or were explicitly started and marked active.
- What this means is that, in general, starting an (inactive, stopped)
- service and then stopping it will return the system to its prior state -
- no dependencies which were started automatically will be left running.
- Service Description files
- =-=-=-=-=-=-=-=-=-=-=-=-=
- Dinit discovers services by reading _service description files_. These files
- reside in a directory (/etc/dinit.d is the default "system" location) and
- their name matches the name of the service. Service descriptions are loaded
- lazily, as needed by Dinit.
- A service description file consists of a number of parameter settings.
- Settings in the SDF are denoted as a parameter name followed by either an
- equal sign or colon and then the parameter value (all on the same line).
- 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).
- Parameter values are interpreted literally, except that:
- - whitespace is collapsed to a single space
- - double quotes can be used around all or part(s) of a parameter to prevent
- whitespace collapse and interpretation of special characters
- - backslash can be used to 'escape' the next character, preventing any
- special meaning from being associated with it. It can be used to include
- non-collapsing whitespace, double-quote marks, and backslashes in the
- parameter value.
- Parameters are:
- type = process | bgprocess | scripted | internal
- command = ...
- logfile = ...
- options = ...
- depends-on = (service name)
- waits-for = (service name)
- command = (external script or executable, and arguments)
- For a 'process' service, this is the process to run.
- For a 'scripted' service, this command is run to start the service.
- stop-command = (external script or executable, and arguments)
- For a 'scripted' service, this command is run to stop the service.
- restart = yes | true | no | false
- Specifies whether the service should automatically restart if it becomes
- stopped (for any reason, including being explicitly requested to stop).
- Only active services will restart automatically.
- smooth-recovery = yes | true | no | false
- For process services only. Specifies that, should the process die, it
- can be restarted without bringing the service itself down. This means that
- any dependent services do not need to be stopped/restarted. Such recovery
- happens regardless of the "restart" setting (if smooth-recovery is enabled,
- the service does not reach the stopped state when the process terminates
- unexpectedly).
- restart-delay = XXX.YYYY
- Specifies the minimum time in seconds between automatic restarts. The
- default is 0.2 (i.e. 200ms). This prevents Dinit from consuming processor
- cycles when a process continuously fails immediately after it starts.
- restart-limit-interval = XXX.YYYY
- Specifies the interval, in seconds, over which restarts are limited. If a
- process automatically restarts more than a certain number of times (default
- 3) in this time interval, it will not restart again. The default value is
- 10 seconds. Use this to prevent broken services from continuously
- restarting ad infinitum.
- restart-limit-count = NNN
- Specifies the maximum number of times that a service can automatically
- restart over the interval specified by restart-limit-interval (default of
- 10 seconds). Specify a value of 0 to disable the restart limit.
- 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.
- 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.
- 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.
- 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).
- socket-uid = (numeric user id or username)
- Specifies the user that should own the activation socket. If socket-uid
- is specified 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 owner is not specified,
- the socket will be owned by the user id of the Dinit process.
- socket-gid = (numeric group id or group name)
- Specifies the group of the activation socket. See discussion of
- socket-uid.
- termsignal = HUP | INT | QUIT | USR1 | USR2
- Specifies an additional signal to send to the process when requesting it
- to terminate (applies to 'process' services only). SIGTERM is always
- sent along with the specified signal, unless the 'nosigterm' setting is
- set true.
- options = ( runs-on-console | nosigterm | starts-rwfs | starts-log ) ...
- Specifies various options for this service:
- no-sigterm : specifies that the TERM signal should not be send to the
- process to terminate it. (Another signal can be specified using
- the "termsignal" setting; if no other signal is specified, NO
- signal will be sent).
- runs-on-console : specifies that this service uses the console; its input
- and output should be directed to the console. 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.
- 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.
- logfile = (log file path)
- Specifies the log file for the service. Output from the service process
- will go this file.
- Controlling services
- =-=-=-=-=-=-=-=-=-=-
- You can use the "dinitctl" to start and stop services. Typical invocations
- are:
- dinitctl start <service-name>
- dinitctl stop <service-name>
- dinitctl release <service-name>
- Note that a "start" markes the service active, as well as starting it if it is
- not already started; the opposite of this is actually "release", which clears
- the active mark and stops it if it has no active dependent services. The "stop"
- command by default acts as a "release" which also forces the service to stop
- (although it may then immediately restart, depending on how it and its
- dependents are configured).
- Use the "-s" switch to talk the "system" instance of dinit, rather than a
- personal instance, e.g:
- dinitctl -s start mysql # start system mysql service
- For complete details on the command line, use:
- dinitctl --help
- You can "pin" a service in either the stopped or started state, which prevents
- it from changing state either due to a dependency/dependent or a direct
- command:
- dinitctl -s start --pin mysql # start mysql service, pin it as "started"
- dinitctl -s stop mysql # issues stop, but doesn't take effect due to pin
- dinitctl -s unpin mysql # release pin; service will now stop
- You can pin a service in the stopped state in order to make sure it doesn't
- get started accidentally (either via a dependency or directly). You can also
- use it to temporarily keep stopped a service that would otherwise restart
- immediately when you stopped it (because it, or a dependent, is configured
- to restart automatically).
- Finally, you can list the state of all loaded services:
- dinitctl -s list
- This may result in something like the following:
- [{+} ] boot
- [{+} ] tty1
- [{+} ] tty2
- [{+} ] tty3
- [{+} ] tty4
- [{+} ] loginready
- [{+} ] rcboot
- [{+} ] filesystems
- [{+} ] udevd
- [ {-}] mysql
- The above represents a number of started services and one stopped service
- (mysql). Services transitioning state (starting or stopping) are displayed
- with an arrow indicating the transition direction:
- [ <<{-}] mysql # starting
- [{+}>> ] mysql # stopping
- Remember that a "starting" service may be waiting for its dependencies to
- start, and a "stopping" service may be waiting for its dependencies to stop.
|