4.1 Defining Services

A service is created by calling the service procedure, from the (shepherd service) module (automatically visible from your configuration file), as in this example:

(service
  '(sshd ssh-daemon)  ;for convenience, give it two names
  #:start (make-forkexec-constructor
           '("/usr/sbin/sshd" "-D")
           #:pid-file "/etc/ssh/sshd.pid")
  #:stop (make-kill-destructor)
  #:respawn? #t)

The example above creates a service with two names, sshd and ssh-daemon. It is started by invoking /usr/sbin/sshd, and it is considered up and running as soon as its PID file /etc/ssh/sshd.pid is available. It is stopped by terminating the sshd process. Finally, should sshd terminate prematurely, it is automatically respawned. We will look at #:start and #:stop later (see Service De- and Constructors), but first, here is the reference of the service procedure and its optional keyword arguments.

Procedure: service provision [#:requirement ’()] [#:one-shot? #f] [#:transient? #f] [#:respawn? #f] [#:start (const #t)] [#:stop (const #f)] [#:actions (actions)] [#:termination-handler default-service-termination-handler] [#:documentation #f]

Return a new service with the given provision, a list of symbols denoting what the service provides. The first symbol in the list is the canonical name of the service, thus it must be unique.

The meaning of keyword arguments is as follows:

#:requirement

#:requirement is, like provision, a list of symbols that specify services. In this case, they name what this service depends on: before the service can be started, services that provide those symbols must be started.

Note that every name listed in #:requirement must be registered so it can be resolved (see Service Registry).

#:respawn?

Specify whether the service should be respawned by shepherd. If this slot has the value #t, then, assuming the service has an associated process (its “running value” is a PID), restart the service if that process terminates.

There is a limit to avoid endless respawning: when the service gets respawned “too fast”, it is disabled—see #:respawn-limit below.

#:respawn-delay

Specify the delay before a service is respawned, in seconds (including a fraction), for services marked with #:respawn? #t. Its default value is (default-respawn-delay) (see Service De- and Constructors).

#:respawn-limit

Specify the limit that prevents shepherd from respawning too quickly the service marked with #:respawn? #t. Its default value is (default-respawn-limit) (see Service De- and Constructors).

The limit is expressed as a pair of integers: the first integer, n, specifies a number of consecutive respawns and the second integer, t, specifies a number of seconds. If the service gets respawned more than n times over a period of t seconds, it is automatically disabled (see service-enabled?). Once it is disabled, the service must be explicitly re-enabled using herd enable service before it can be started again.

Consider the service below:

(service '(xyz)
         #:start (make-forkexec-constructor ...)
         #:stop (make-kill-destructor)
         #:respawn? #t
         #:respawn-limit '(3 . 5))

The effect is that this service will be respawned at most 3 times over a period of 5 seconds; if its associated process terminates a fourth time during that period, the service will be marked as disabled.

#:one-shot?

Whether the service is a one-shot service. A one-shot service is a service that, as soon as it has been successfully started, is marked as “stopped.” Other services can nonetheless require one-shot services. One-shot services are useful to trigger an action before other services are started, such as a cleanup or an initialization action.

As for other services, the start method of a one-shot service must return a truth value to indicate success, and false to indicate failure.

#:transient?

Whether the service is a transient service. A transient service is automatically unregistered when it terminates, be it because its stop method is called or because its associated process terminates.

This is useful in the uncommon case of synthesized services that may not be restarted once they have completed.

#:start

Specify the constructor of the service, which will be called to start the service. This must be a procedure that accepts any number of arguments; those arguments will be those supplied by the user, for instance by passing them to herd start. If the starting attempt failed, it must return #f or throw an exception; otherwise, the return value is stored as the running value of the service.

Note: Constructors must terminate, successfully or not, in a timely fashion, typically less than a minute. Failing to do that, the service would remain in “starting” state and users would be unable to stop it.

See Service De- and Constructors, for info on common service constructors.

#:stop

This is the service destructor: a procedure of one or more arguments that should stop the service. It is called whenever the user explicitly stops the service; its first argument is the running value of the service, subsequent arguments are user-supplied. Its return value will again be stored as the running value, so it should return #f if it is now possible again to start the service at a later point.

Note: Destructors must also terminate in a timely fashion, typically less than a minute. Failing to do that, the service would remain in “stopping” state and users would be unable to stop it.

See Service De- and Constructors, for info on common service destructors.

#:termination-handler

The procedure to call when the process associated with the service terminates. It is passed the service, the PID of the terminating process, and its exit status, an integer as returned by waitpid (see waitpid in GNU Guile Reference Manual).

The default handler is the default-service-termination-handler procedure, which respawns the service if applicable.

#:actions

The additional actions that can be performed on the service when it is running. A typical example for this is the restart action. The actions macro can be used to defined actions (see below).

A special service that every other service implicitly depends on is the root (also known as shepherd) service. See The root Service, for more information.

Services and their dependencies form a graph. At the command-line, you can view that export a representation of that graph that can be consumed by any application that understands the Graphviz format, such as xdot:

herd graph | xdot -

Service actions are defined using the actions macro, as shown below.

Macro: actions (name proc) …

Create a value for the #:actions parameter of service. Each name is a symbol and each proc the corresponding procedure that will be called to perform the action. A proc has one argument, which will be the running value of the service.

Naturally, the (shepherd service) provides procedures to access this information for a given service object:

Procedure: service-provision service

Return the symbols provided by service.

Procedure: service-canonical-name service

Return the canonical name of service, which is the first element of the list returned by service-provision.

Procedure: service-requirement service

Return the list of services required by service as a list of symbols.

Procedure: one-shot-service? service
Procedure: transient-service? service

Return true if service is a one-shot/transient service.

Procedure: respawn-service? service

Return true if service is meant to be respawned if its associated process terminates prematurely.

Procedure: service-respawn-delay service

Return the respawn delay of service, in seconds (an integer or a fraction or inexact number). See #:respawn-delay above.

Procedure: service-respawn-limit service

Return the respawn limit of service, expressed as a pair—see #:respawn-limit above.

Procedure: service-documentation service

Return the documentation (a string) of service.