= Understanding and administering systemd Christopher Engelhard; Kamil Páral; Caleb McKee :revnumber: unknown :revdate: 2020-08-05 :category: Administration :tags: How-to, Upgrade :source-highlighter: prettify :page-aliases: understanding-and-administering-systemd.adoc [abstract] Learn the basic principles of the _systemd_ init system: how to configure it and use it to administer the system. == Understanding systemd _Systemd_ is a system and service manager for Linux, compatible with SysV and LSB init scripts. _Systemd_ provides: * Aggressive parallelization capabilities * Uses socket and D-Bus activation for starting services * Offers on-demand starting of daemons, keeps track of processes using Linux cgroups * Supports snapshotting and restoring of the system state * Maintains mount and automount points * Implements an elaborate transactional dependency-based service control logic. The `systemctl` command is the primary tool to manage _systemd_. It combines the functionality of SysVinit's `service` and `chkconfig` commands into a single tool you can use to enable and disable services permanently or only for the current session. _Systemd_ manages so-called *_units_*, which are representations of system resources and services. This following list shows the unit types that _systemd_ can manage: service:: A service on the system, including instructions for starting, restarting, and stopping the service. socket:: A network socket associated with a service. device:: A device specifically managed with _systemd_. mount:: A mountpoint managed with _systemd_. automount:: A mountpoint automatically mounted on boot. swap:: Swap space on the system. target:: A synchronization point for other units. Usually used to start enabled services on boot. path:: A path for path-based activation. For example, you can start services based on the state of a certain path, such as whether it exists or not. timer:: A timer to schedule activation of another unit. snapshot:: A snapshot of the current _systemd_ state. Usually used to rollback after making temporary changes to _systemd_. slice:: Restriction of resources through Linux Control Group nodes (cgroups). scope:: Information from _systemd_ bus interfaces. Usually used to manage external system processes. == Starting, stopping, and querying systemd services You can perform various management tasks to control _systemd_ services using the `systemctl` command. The following is a set of example commands to demonstrate how to use `systemctl` to manage _systemd_ services. [discrete] == Prerequisites You are logged in as a user with administrator-level permissions. [discrete] == Procedure The following commands control the `foo` service: * Activate a service immediately: + ---- # systemctl start foo ---- * Deactivate a service immediately: + ---- # systemctl stop foo ---- * Restart a service: + ---- # systemctl restart foo ---- * Show the status of a service including, whether it is running or not: + ---- # systemctl status foo ---- * Enable a service to be started on boot: + ---- # systemctl enable foo ---- * Disable a service to not start during boot: + ---- # systemctl disable foo ---- * Prevent a service from starting dynamically or even manually unless unmasked: + ---- # systemctl mask foo ---- * Check if a service is enabled or not: + ---- # systemctl is-enabled foo ---- [discrete] === Related Information * Run `man systemctl` for more details. == Modifying existing systemd services This example shows how to modify an existing service. Service modification are stored within `/etc/systemd/system`, in a single file or in a subdirectory named after the service. For example, this procedure modifies the `httpd` service. [discrete] === Prerequisites * You are logged in as a user with administrator-level permissions. * You have a configured `httpd` server running through _systemd_. [discrete] === Procedure . _Systemd_ services can be modified using the `systemctl edit` command. + ---- # systemctl edit httpd.service ---- + This creates an override file `/etc/systemd/system/httpd.service.d/override.conf` and opens it in your text editor. Anything you put into this file will be *added* to the existing service file. . Add your custom configuration. For example: + ---- [Service] Restart=always RestartSec=30 ---- + To replace an option that can be set multiple times, it must cleared first, otherwise the override file will add the option a second time. + ---- [Service] ExecStart= ExecStart= ---- . Save the file. _Systemd_ automatically loads the new service configuration. . Restart the `httpd` service: + ---- # systemctl restart httpd ---- To completely replace (instead of just add to/modify) an existing service file, use `systemctl edit --full`, e.g. `systemctl edit --full httpd.service`. This will create `/etc/systemctl/system/httpd.service`, which will be used instead of the existing service file. [discrete] === Related Information * See link:#common-service-parameters[Common service parameters] for more information about the parameters used in this procedure. == Creating new systemd services This example shows how to create a unit file for a custom service. Custom unit files are located in `/etc/systemd/system/` and have a `.service` extension. For example, a custom `foo` service uses `/etc/systemd/system/foo.service` unit file. [discrete] === Prerequisites * You are logged in as a user with administrator-level permissions. [discrete] === Procedure This procedure creates a basic configuration file to control the `foo` service. . Create and edit the new configuration file: + ---- # nano /etc/systemd/system/foo.service ---- . The next few steps describe each section its parameters to add to the file: .. The `[Unit]` section provides basic information about the service. The `foo` service uses the following parameters: + `Description`:: A string describing the unit. _Systemd_ displays this description next to the unit name in the user interface. `After`:: Defines a relationship with a second unit. If you activate the unit, _systemd_ activates it only after the second one. For example, the `foo` service might require network connectivity, which means the `foo` services specifies `network.target` as an `After=` condition. + The resulting `[Unit]` section looks like this: + ---- [Unit] Description=My custom service After=network.target ---- .. The `[Service]` section provides instructions on how to control the service. The `foo` service uses the following parameters: + `Type`:: Defines the type of _systemd_ service. In this example, the `foo` service is a `simple` service, which starts the service without any special consideration. `ExecStart`:: The command to run to start the service. This includes the full path to the command and arguments to modify the service. + The resulting `[Service]` section looks like this: + ---- [Service] Type=simple ExecStart=/usr/bin/sleep infinity ---- .. The `[Install]` section provides instructions on how _systemd_ installs the service. The `foo` service uses the following parameters: + `WantedBy`:: Defines which service triggers the custom service if enabled with `systemctl enable`. This is mostly used for starting the custom service on boot. In this example, `foo.service` uses `multi-user.target`, which starts `foo.service` when _systemd_ loads `multi-user.target` on boot. . The full `foo.service` file contains the following contents: + ---- [Unit] Description=My custom service After=network.target [Service] Type=simple ExecStart=/usr/bin/sleep infinity [Install] WantedBy=multi-user.target ---- + Save the file. . To make _systemd_ aware of the new service, reload its service files + ---- # systemctl daemon-reload ---- . Start the custom `foo` service: + ---- # systemctl start foo ---- . Check the status of the service to ensure the service is running: + ---- $ systemctl status foo ● foo.service - My custom service Loaded: loaded (/etc/systemd/system/foo.service; static; vendor preset: disabled) Active: active (running) since Thu 2017-12-14 14:09:12 AEST; 6s ago Main PID: 31837 (sleep) Tasks: 1 (limit: 4915) CGroup: /system.slice/foo.service └─31837 /usr/bin/sleep infinity Dec 14 14:09:12 dansmachine systemd[1]: Started My custom service. ---- [discrete] === Related Information * See link:#common-service-parameters[Common service parameters] for more information about the parameters used in this procedure. == Converting SysVinit services to systemd Older versions of Fedora use SysVinit scripts to manage services. This section provides some guidelines on how to convert a SysVinit script to a _systemd_ equivalent. [discrete] === Prerequisites * You are logged in as a user with administrator-level permissions. * You have a custom SysVinit script to convert to a _systemd_ configuration. [discrete] === Procedure . Identify the runlevels in your SysVinit script. This is usually defined with `chkconfig` directive in the commented section at the beginning of the script. For example, the following indicates the service is using runlevels 3, 4, and 5: + ---- # chkconfig: 235 20 80 ---- + systemd uses targets instead of runlevels. Use the table in <<#converting-sysvinit-services>> to map the runlevels to targets. In this example, runlevels 2, 3, and 5 are all multi-user runlevels, so the _systemd_ service can use the following: + ---- [Install] WantedBy=multi-user.target ---- + If you enable the custom _systemd_ service to start at boot (`systemctl enable foo.service`), _systemd_ loads the service when loading the `multi-user.target` at boot time. . Identify the dependent services and targets. For example, if the custom service requires network connectivity, specify the `network.target` as a dependency: + ---- [Unit] Description=My custom service After=network.target ---- . Identify the command used to start the service in the SysVinit script and convert this to the _systemd_ equivalent. For example, the script might contain a `start` function in the following format: + [source,bash] ---- start() { echo "Starting My Custom Service..." /usr/bin/myservice -D } ---- + In this example, the `/usr/bin/myservice` command is the custom service command set to daemonize with the `-D` option. Set the `ExecStart` parameter to use this command: + ---- [Service] ExecStart=/usr/bin/myservice -D ---- . Check the SysVinit script to see if the service uses a special command to restart the service. For example, the script might contain a `reboot` function that reloads the service: + [source,bash] ---- reboot() { echo "Reloading My Custom Service..." /usr/bin/myservice reload } ---- + In this example, the `/usr/bin/myservice` command is the custom service command and reloads the service using the `reload` subcommand. Set the `ExecReload` parameter to use this command: + ---- [Service] ExecReload=/usr/bin/myservice reload ---- + Alternatively, you can omit `ExecReload` and use the default behavior, which kills the service and starts it again. . Check the SysVinit script to see if the service uses a special command to stop the service. For example, the script might contain a `stop` function that reloads the service: + [source,bash] ---- reboot() { echo "Stopping My Custom Service..." /usr/bin/myservice shutdown } ---- + In this example, the `/usr/bin/myservice` command is the custom service command and stop the service gracefully using the `shutdown` subcommand. Set the `ExecStop` parameter to use this command: + ---- [Service] ExecStop=/usr/bin/myservice shutdown ---- + Alternatively, you can omit `ExecStop` and use the default behavior, which kills the service. . Review the SysVinit script and identify any additional parameters or functions. Use _systemd_ parameters to replicate any identified SysVinit functions that might be relevant to your service. [discrete] === Related Information * See link:#common-service-parameters[Common service parameters] for more information about the parameters used in this procedure. == Common service parameters === Unit Parameters This section contains parameters you can use in the `[Unit]` section of a service. These parameters are common to other _systemd_ units. This list is a summarized version. For a full list of these parameters and their descriptions, run `man systemd.unit`. Description:: A free-form string describing the service. Documentation:: A space-separated list of URIs referencing documentation for this service or its configuration. Accepted are only URIs of the following types: `http://`, `https://`, `file:`, `info:`, `man:`. Requires:: Configures requirement dependencies on other services. If this service gets activated, the units listed here are activated too. If one of the dependent services fails to activate, _systemd_ does not start this service. This option may be specified more than once or you can specify multiple space-separated units. Wants:: Similar to `Requires`, except failed units do not have any effect on the service. BindsTo:: Similar to `Requires`, except stopping the dependent units also stops the service. PartOf:: Similar to `Requires`, except the stopping and restarting dependent units also stop and restart the service. Conflicts:: A space-separated list of unit names that, if running, cause the service not to run. Before, After:: A space-separated list of unit names that configures the ordering of dependencies between services. OnFailure:: A space-separated list of unit names that are activated when this service enters a failed state. === Install Parameters This section contains parameters you can use in the `[Install]` section of a service. These parameters are common to other _systemd_ units. This list is a summarized version. For a full list of these parameters and their descriptions, run `man systemd.unit`. Alias:: A space-separated list of additional names this service shall be installed under. The names listed here must have the same suffix (i.e. type) as the service filename. RequiredBy, WantedBy:: Defines the service as dependent of another service. This usually define the target to trigger an enabled service to run. These options are analogous to the `Requires` and `Wants` in the `[Units]` section. Also:: Additional units to install or uninstall when this service is installed or uninstalled. === Service Parameters This section contains parameters you can use in the `[Service]` section of a service unit. These parameters are specific only to _systemd_ service units. This list is a summarized version. For a full list of these parameters and their descriptions, run `man systemd.unit`. Type:: Configures the process start-up type for this service service: + * `simple` - The service starts as the main process. This is the default. * `forking` - The service calls forked processes and run as part of the main daemon. * `oneshot` - Similar to `simple`, except the process must exit before _systemd_ starts follow-up services. * `dbus` - Similar to `simple`, except the daemon acquires a name of the D-Bus bus. * `notify` - Similar to `simple`, except the daemon sends a notification message using `sd_notify` or an equivalent call after starting up. * `idle` - Similar to `simple`, except the execution of the service is delayed until all active jobs are dispatched. RemainAfterExit:: A boolean value that specifies whether the service shall be considered active even if all its processes exited. Defaults to no. GuessMainPID:: A boolean value that specifies whether _systemd_ should guess the main PID of a service if it cannot be determined reliably. This option is ignored unless `Type=forking` is set and `PIDFile` is not set. Defaults to yes. PIDFile:: An absolute filename pointing to the PID file of this daemon. Use of this option is recommended for services where `Type=forking`. _Systemd_ reads the PID of the main process of the daemon after start-up of the service. _Systemd_ does not write to the file configured here, although it removes the file after the service has shut down. BusName:: A D-Bus bus name to reach this service. This option is mandatory for services where `Type=dbus`. ExecStart:: The commands and arguments executed when the service starts. ExecStartPre, ExecStartPost:: Additional commands that are executed before or after the command in `ExecStart`. ExecReload:: The commands and arguments to execute when the service reloads. ExecStop:: The commands and arguments to execute when the service stops. ExecStopPost:: Additional commands to execute after the service stops. RestartSec:: The time in seconds to sleep before restarting a service. TimeoutStartSec:: The time in seconds to wait for the service to start. TimeoutStopSec:: The time in seconds to wait for the service to stop. TimeoutSec:: A shorthand for configuring both `TimeoutStartSec` and `TimeoutStopSec` simultaneously. RuntimeMaxSec:: A maximum time in seconds for the service to run. Pass `infinity` (the default) to configure no runtime limit. Restart:: Configures whether to restart the service when the service's process exits, is killed, or reaches a timeout: + * `no` - The service will not be restarted. This is the default. * `on-success` - Restart only when the service process exits cleanly (exit code 0). * `on-failure` - Restart only when the service process does not exit cleanly (node-zero exit code). * `on-abnormal` - Restart if the process terminates with a signal or when a timeout occurs. * `on-abort` - Restart if the process exits due to an uncaught signal not specified as a clean exit status. * `always` - Always restart. == Mapping runlevels to targets _Systemd_ targets serve a similar purpose to SysVinit runlevels but act a little differently. Each target has a name instead of a number and each serves a specific purpose. _Systemd_ implements some targets by inheriting all of the services of another target and adding additional services to it. Some _systemd_ targets mimic the common sysvinit runlevels, which means you can switch targets with the familiar `telinit RUNLEVEL` command. The runlevels assigned a specific purpose on vanilla Fedora installs (0, 1, 3, 5, and 6) have a 1:1 mapping with a specific _systemd_ target. However, this is not the case for user-defined runlevels 2 and 4. To make use of those runlevels, create a new named _systemd_ target such as `/etc/systemd/system/$YOURTARGET` that takes one of the existing runlevels as a base, make a directory `/etc/systemd/system/$YOURTARGET.wants`, and then symlink the additional services to enable into that directory. The following is a mapping of SysVinit runlevels to _systemd_ targets. [cols="2,5,5",options="header"] .Runlevel to target mapping |=== |Sysvinit Runlevel |systemd Target |Notes |0 |runlevel0.target, poweroff.target |Halt the system. |1, s, single |runlevel1.target, rescue.target |Single user mode. |2, 4 |runlevel2.target, runlevel4.target, multi-user.target |User-defined/Site-specific runlevels. By default, identical to 3. |3 |runlevel3.target, multi-user.target |Multi-user, non-graphical. Users can usually login via multiple consoles or via the network. |5 |runlevel5.target, graphical.target |Multi-user, graphical. Usually has all the services of runlevel 3 plus a graphical login. |6 |runlevel6.target, reboot.target |Reboot |emergency |emergency.target |Emergency shell |=== == Mapping service commands The following table demonstrates the _systemd_ equivalent of SysVinit commands. NOTE: All recent versions of `systemctl` assume the `.service` suffix if left off the service name. For example, `systemctl start frobozz.service` is the same as `systemctl start frobozz`. [cols=",,",options="header",] |=== |Sysvinit Command |systemd Command |Notes |`service frobozz start`|`systemctl start frobozz`|Used to start a service (not reboot persistent) |`service frobozz stop`|`systemctl stop frobozz`|Used to stop a service (not reboot persistent) |`service frobozz restart`|`systemctl restart frobozz`|Used to stop and then start a service |`service frobozz reload`|`systemctl reload frobozz`|When supported, reloads the config file without interrupting pending operations. |`service frobozz condrestart`|`systemctl condrestart frobozz`|Restarts if the service is already running. |`service frobozz status`|`systemctl status frobozz`|Tells whether a service is currently running. |`ls /etc/rc.d/init.d/`|`systemctl` or `systemctl list-unit-files --type=service` or + `ls /lib/systemd/system/\*.service /etc/systemd/system/*.service`|Used to list the services that can be started or stopped + Used to list all the services and other units |`chkconfig frobozz on`|`systemctl enable frobozz`|Turn the service on, for start at next boot, or other trigger. |`chkconfig frobozz off`|`systemctl disable frobozz`|Turn the service off for the next reboot, or any other trigger. |`chkconfig frobozz`|`systemctl is-enabled frobozz`|Used to check whether a service is configured to start or not in the current environment. |`chkconfig --list`|`systemctl list-unit-files --type=service` or `ls /etc/systemd/system/*.wants/`|Print a table of services that lists which runlevels each is configured on or off |`chkconfig --list \| grep 5:on`|`systemctl list-dependencies graphical.target`|Print a table of services that will be started when booting into graphical mode |`chkconfig frobozz --list`|`ls /etc/systemd/system/*.wants/frobozz.service`|Used to list what levels this service is configured on or off |`chkconfig frobozz --add`|`systemctl daemon-reload`|Used when you create a new service file or modify any configuration |=== NOTE: All `/sbin/service` and `/sbin/chkconfig` commands listed in the table continue to work on _systemd_-based systems and are translated to native equivalents as necessary. The only exception is `chkconfig --list`. == Additional resources * http://www.freedesktop.org/wiki/Software/systemd[Project homepage] * http://0pointer.de/blog/[Lennart Poettering's blog] with lots of information about _systemd_. Lennart is the primary _systemd_ developer * http://www.freedesktop.org/wiki/Software/systemd/FrequentlyAskedQuestions[freedesktop.org's _systemd_ FAQ] * http://www.freedesktop.org/wiki/Software/systemd/TipsAndTricks[freedesktop.org's _systemd_ Tips & Tricks] * http://fosdem.org/2011/interview/lennart-poettering.html[Interview with the developer]