Crate hermit_sm

Crate hermit_sm 

Expand description

Hermit Service Manager.

§General Concepts

There are two things that control whether a service should be running:

  1. The system is “active”. In our case this means that the system isn’t sleeping or shutting down.
  2. The service’s system dependencies are met.

Both of these are considered “inputs” as far as this crate is concerned and the service manager needs to be explicitly given their state. The system active state is enforced equally across all managed services, but the system dependencies can be defined by each service individually. System dependencies are hard requirements that must be met for the service to be running. Right now the only available system dependency is SystemDependency::TIME, which requires the system to have a correct time for the service to run.

The service manager uses a polling approach internally to manage services. Whenever it is polled, it will determine the desired state (i.e. running or not running) of each service based on whether the system is active and all of the service’s dependencies are met. If a service is not in the desired state, the service manager will start or stop the service as needed. If this fails, the error will be logged and the same action will be attempted again on the next poll (simply because the service still isn’t in the desired state).

As a nice side effect, crashed services will be restarted automatically.

§Service Discovery

Services are loaded from TOML configuration files in a directory. The ServiceManagerHandle::reload_services method can be used to re-discover all services in a list of directories.

A service config looks like this:

# optional: override the service ID (default is based on the file name)
id = "test"

# optional: command to run before starting the service (default is none)
            if it fails, the service will not be started.
exec_start_pre = ["mkdir", "/run/test"]
# optional: how long the exec_start_pre command is allowed to run (default is 10 seconds)
            if it doesn't finish in time, the process will be killed.
exec_start_pre_timeout = "10s"

# required: command to run
exec_start = ["test", "arg1", "arg2"]

# optional: the timeout in seconds to wait for the service to stop (default is 10 seconds)
#           if the service doesn't stop in time, it will be killed.
shutdown_timeout = "10s"

# optional: list of system dependencies for the service. available options: "TIME", "MOUNTS".
system_dependencies = ["TIME"]

The discovery can be repeated multiple times. The service manager automatically takes care of restarting updated services and stopping removed ones.

Modules§

service 🔒
start_stop_daemon 🔒
Start/stop service using start-stop-daemon command.
status 🔒

Structs§

CommandDefinition
Definition of a command consisting of an executable and arguments.
ServiceDefinition
A service to manage.
ServiceManager 🔒
ServiceManagerHandle
StartStopDaemon
Process spawner using start-stop-daemon command.
SystemDependency
System dependencies.

Enums§

Command 🔒

Constants§

CMD_CHANNEL_SIZE 🔒
CONCURRENCY_LIMIT 🔒
POLL_INTERVAL 🔒

Traits§

ProcessSpawner
Something that can spawn a process for a service.

Functions§

spawn
Spawns a new service manager.