0% found this document useful (0 votes)
3 views26 pages

Understanding Systemd

The document explains Systemd units and unit files, which are essential for managing system resources and services in a standardized manner. Key features include socket-based activation for faster startup, various activation methods, and a flexible configuration system. It also details the locations of unit files, types of units, and the structure of unit files, emphasizing the advantages of Systemd over traditional init systems.
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
3 views26 pages

Understanding Systemd

The document explains Systemd units and unit files, which are essential for managing system resources and services in a standardized manner. Key features include socket-based activation for faster startup, various activation methods, and a flexible configuration system. It also details the locations of unit files, types of units, and the structure of unit files, emphasizing the advantages of Systemd over traditional init systems.
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd

Understanding Systemd Units and Unit Files

What do Systemd Units Give You?


Units are the objects that systemd knows how to manage. These are basically a
standardized representation of system resources that can be managed by the suite
of daemons and manipulated by the provided utilities.

Units in some ways can be said to similar to services or jobs in other init systems.

The new Systemd starts daemons at same time and this parallel running of daemons
means a very fast startup. How come? Well, systemd uses sockets for all services. It
sets up sockets for daemons and coordinates between them as they start up. So,
when a daemon requires support from another daemon, systemd coordinate the
data from their sockets . For example, daemon A starts and it needs a support from
daemon B, however, daemon B has not started yet . Therefore, systemd writes
daemon A’s request to daemon B’s socket(buffering) and it continues. So daemon A
doesn’t need to wait for daemon B. As soon as daemon B starts, it will read its
socket. This means parallel processing and system boots very fast. The socket
activation was designed by Apple’s OS X system.

Some features that units are able implement easily are:


● socket-based activation: Sockets associated with a service are best broken
out of the daemon itself in order to be handled separately. This provides a
number of advantages, such as delaying the start of a service until the
associated socket is first accessed. This also allows the system to create all
sockets early in the boot process, making it possible to boot the associated
services in parallel.
● bus-based activation: Units can also be activated on the bus interface
provided by D-Bus. A unit can be started when an associated bus is published.
● path-based activation: A unit can be started based on activity on or the
availability of certain filesystem paths. This utilizes inotify.
● device-based activation: Units can also be started at the first availability of
associated hardware by leveraging udev events.
● implicit dependency mapping: Most of the dependency tree for units can be
built by systemd itself. You can still add dependency and ordering
information, but most of the heavy lifting is taken care of for you.
● instances and templates: Template unit files can be used to create multiple
instances of the same general unit. This allows for slight variations or sibling
units that all provide the same general function.
● easy security hardening: Units can implement some fairly good security
features by adding simple directives. For example, you can specify no or read-
only access to part of the filesystem, limit kernel capabilities, and assign
private /tmp and network access.
● drop-ins and snippets: Units can easily be extended by providing snippets
that will override parts of the system's unit file. This makes it easy to switch
between vanilla and customized unit implementations.
There are many other advantages that systemd units have over other init systems'
work items, but this should give you an idea of the power that can be leveraged
using native configuration directives.

What is the advantage of moving to systemd from init system?


The main advantages are:
1. systemd reduces system startup time in parallelizing startup of services.
2. systemd uses Cgroups for better tracking of processes, also allowing control
of the execution environment.
3. systemd has a better logging mechanism as it is tightly coupled with journald,
which is a logging mechanism that was introduced with Red Hat Enterprise
Linux 7.
4. systemd can handle dynamic system configuration changes.

Where are Systemd Unit Files Found?


The files that define how systemd will handle a unit can be found in many different
locations, each of which have different priorities and implications.

The system's copy of unit files are generally kept in the /lib/systemd/system
directory. When software installs unit files on the system, this is the location where
they are placed by default.
Unit files stored here are able to be started and stopped on-demand during a
session. This will be the generic, vanilla unit file, often written by the upstream
project's maintainers that should work on any system that deploys systemd in its
standard implementation. You should not edit files in this directory. Instead you
should override the file, if necessary, using another unit file location which will
supersede the file in this location.

If you wish to modify the way that a unit functions, the best location to do so is
within the /etc/systemd/system directory. Unit files found in this directory location
take precedence over any of the other locations on the filesystem. If you need to
modify the system's copy of a unit file, putting a replacement in this directory is the
safest and most flexible way to do this.
If you wish to override only specific directives from the system's unit file, you can
actually provide unit file snippets within a subdirectory. These will append or
modify the directives of the system's copy, allowing you to specify only the options
you want to change.

The correct way to do this is to create a directory named after the unit file with .d
appended on the end. So for a unit called [Link], a subdirectory called
[Link].d could be created. Within this directory a file ending with .conf can
be used to override or extend the attributes of the system's unit file.

There is also a location for run-time unit definitions at /run/systemd/system. Unit


files found in this directory have a priority landing between those in
/etc/systemd/system and /lib/systemd/system. Files in this location are given less
weight than the former location, but more weight than the latter.

The systemd process itself uses this location for dynamically created unit files
created at runtime. This directory can be used to change the system's unit behavior
for the duration of the session. All changes made in this directory will be lost when
the server is rebooted.

Types of Units
Systemd categories units according to the type of resource they describe. The
easiest way to determine the type of a unit is with its type suffix, which is appended
to the end of the resource name. The following list describes the types of units
available to systemd:

.service: A service unit describes how to manage a service or application on the


server. This will include how to start or stop the service, under which circumstances
it should be automatically started, and the dependency and ordering information for
related software.
● .socket: A socket unit file describes a network or IPC socket, or a FIFO buffer
that systemd uses for socket-based activation. These always have an
associated .service file that will be started when activity is seen on the socket
that this unit defines.
● .device: A unit that describes a device that has been designated as needing
systemd management by udev or the sysfs filesystem. Not all devices will
have .device files. Some scenarios where .device units may be necessary are
for ordering, mounting, and accessing the devices.
● .mount: This unit defines a mountpoint on the system to be managed by
systemd. These are named after the mount path, with slashes changed to
dashes. Entries within /etc/fstab can have units created automatically.
● .automount: An .automount unit configures a mountpoint that will be
automatically mounted. These must be named after the mount point they
refer to and must have a matching .mount unit to define the specifics of the
mount.
● .swap: This unit describes swap space on the system. The name of these units
must reflect the device or file path of the space.
● .target: A target unit is used to provide synchronization points for other units
when booting up or changing states. They also can be used to bring the
system to a new state. Other units specify their relation to targets to become
tied to the target's operations.
● .path: This unit defines a path that can be used for path-based activation. By
default, a .service unit of the same base name will be started when the path
reaches the specified state. This uses inotify to monitor the path for changes.
● .timer: A .timer unit defines a timer that will be managed by systemd, similar
to a cron job for delayed or scheduled activation. A matching unit will be
started when the timer is reached.
● .snapshot: A .snapshot unit is created automatically by the systemctl
snapshot command. It allows you to reconstruct the current state of the
system after making changes. Snapshots do not survive across sessions and
are used to roll back temporary states.
● .slice: A .slice unit is associated with Linux Control Group nodes, allowing
resources to be restricted or assigned to any processes associated with the
slice. The name reflects its hierarchical position within the cgroup tree. Units
are placed in certain slices by default depending on their type.
● .scope: Scope units are created automatically by systemd from information
received from its bus interfaces. These are used to manage sets of system
processes that are created externally.
As you can see, there are many different units that systemd knows how to manage.
Many of the unit types work together to add functionality. For instance, some units
are used to trigger other units and provide activation functionality.

We will mainly be focusing on .service units due to their utility and the consistency
in which administrators need to managed these units.

Anatomy of a Unit File


The internal structure of unit files are organized with sections. Sections are denoted
by a pair of square brackets "[" and "]" with the section name enclosed within. Each
section extends until the beginning of the subsequent section or until the end of the
file.

General Characteristics of Unit Files


Section names are well defined and case-sensitive. So, the section [Unit] will not be
interpreted correctly if it is spelled like [UNIT]. If you need to add non-standard
sections to be parsed by applications other than systemd, you can add a X- prefix to
the section name.
Within these sections, unit behavior and metadata is defined through the use of
simple directives using a key-value format with assignment indicated by an equal
sign, like this:
[Section]
Directive1=value
Directive2=value

...

In the event of an override file (such as those contained in a [Link].d directory),


directives can be reset by assigning them to an empty string. For example, the
system's copy of a unit file may contain a directive set to a value like this:
Directive1=default_value

The default_value can be eliminated in an override file by referencing Directive1


without a value, like this:
Directive1=

In general, systemd allows for easy and flexible configuration. For example, multiple
boolean expressions are accepted (1, yes, on, and true for affirmative and 0, no off,
and false for the opposite answer). Times can be intelligently parsed, with seconds
assumed for unit-less values and combining multiple formats accomplished
internally.

[Unit] Section Directives


The first section found in most unit files is the [Unit] section. This is generally used
for defining metadata for the unit and configuring the relationship of the unit to
other units.
Although section order does not matter to systemd when parsing the file, this
section is often placed at the top because it provides an overview of the unit. Some
common directives that you will find in the [Unit] section are:
● Description=: This directive can be used to describe the name and basic
functionality of the unit. It is returned by various systemd tools, so it is good
to set this to something short, specific, and informative.
● Documentation=: This directive provides a location for a list of URIs for
documentation. These can be either internally available man pages or web
accessible URLs. The systemctl status command will expose this information,
allowing for easy discoverability.
● Requires=: This directive lists any units upon which this unit essentially
depends. If the current unit is activated, the units listed here must
successfully activate as well, else this unit will fail. These units are started in
parallel with the current unit by default.
● Wants=: This directive is similar to Requires=, but less strict. Systemd will
attempt to start any units listed here when this unit is activated. If these units
are not found or fail to start, the current unit will continue to function. This is
the recommended way to configure most dependency relationships. Again,
this implies a parallel activation unless modified by other directives.
● BindsTo=: This directive is similar to Requires=, but also causes the current
unit to stop when the associated unit terminates.
● Before=: The units listed in this directive will not be started until the current
unit is marked as started if they are activated at the same time. This does not
imply a dependency relationship and must be used in conjunction with one of
the above directives if this is desired.
● After=: The units listed in this directive will be started before starting the
current unit. This does not imply a dependency relationship and one must be
established through the above directives if this is required.
● Conflicts=: This can be used to list units that cannot be run at the same time
as the current unit. Starting a unit with this relationship will cause the other
units to be stopped.
● Condition...=: There are a number of directives that start with Condition
which allow the administrator to test certain conditions prior to starting the
unit. This can be used to provide a generic unit file that will only be run when
on appropriate systems. If the condition is not met, the unit is gracefully
skipped.
● Assert...=: Similar to the directives that start with Condition, these directives
check for different aspects of the running environment to decide whether the
unit should activate. However, unlike the Condition directives, a negative
result causes a failure with this directive.
Using these directives and a handful of others, general information about the unit
and its relationship to other units and the operating system can be established.

[Install] Section Directives


Unit file may include an "[Install]" section, which carries installation information for
the unit. This section is not interpreted by systemd(1) during runtime. It is used
exclusively by the enable and disable commands of the systemctl(1) tool during
installation of a unit:

On the opposite side of unit file, the last section is often the [Install] section. This
section is optional and is used to define the behavior or a unit if it is enabled or
disabled. Enabling a unit marks it to be automatically started at boot. In essence, this
is accomplished by latching the unit in question onto another unit that is
somewhere in the line of units to be started at boot.
Because of this, only units that can be enabled will have this section. The directives
within dictate what should happen when the unit is enabled:

● WantedBy=: The WantedBy= directive is the most common way to specify


how a unit should be enabled. This directive allows you to specify a
dependency relationship in a similar way to the Wants= directive does in the
[Unit] section. The difference is that this directive is included in the ancillary
unit allowing the primary unit listed to remain relatively clean. When a unit
with this directive is enabled, a directory will be created within
/etc/systemd/system named after the specified unit with .wants appended to
the end. Within this, a symbolic link to the current unit will be created,
creating the dependency. For instance, if the current unit has
WantedBy=[Link], a directory called [Link] will
be created within /etc/systemd/system (if not already available) and a
symbolic link to the current unit will be placed within. Disabling this unit
removes the link and removes the dependency relationship.
● RequiredBy=: This directive is very similar to the WantedBy= directive, but
instead specifies a required dependency that will cause the activation to fail if
not met. When enabled, a unit with this directive will create a directory
ending with .requires.
● Alias=: This directive allows the unit to be enabled under another name as
well. Among other uses, this allows multiple providers of a function to be
available, so that related units can look for any provider of the common
aliased name.
● Also=: This directive allows units to be enabled or disabled as a set.
Supporting units that should always be available when this unit is active can
be listed here. They will be managed as a group for installation tasks.
● DefaultInstance=: For template units (covered later) which can produce unit
instances with unpredictable names, this can be used as a fallback value for
the name if an appropriate name is not provided.

Unit Type-Specific Section Directives


Sandwiched between the previous two sections, you will likely find unit type-
specific sections. Most unit types offer directives that only apply to their specific
type. These are available within sections named after their type. We will cover those
briefly here.
The device, target, snapshot, and scope unit types have no unit-specific directives,
and thus have no associated sections for their type.

The [Service] Section


The [Service] section is used to provide configuration that is only applicable for
services.
One of the basic things that should be specified within the [Service] section is the
Type= of the service. This categorizes services by their process and daemonizing
behavior. This is important because it tells systemd how to correctly manage the
servie and find out its state.
The Type= directive can be one of the following:
● simple: The main process of the service is specified in the start line. This is
the default if the Type= and Busname= directives are not set, but the
ExecStart= is set. Any communication should be handled outside of the unit
through a second unit of the appropriate type (like through a .socket unit if
this unit must communicate using sockets).
● forking: This service type is used when the service forks a child process,
exiting the parent process almost immediately. This tells systemd that the
process is still running even though the parent exited.
● oneshot: This type indicates that the process will be short-lived and that
systemd should wait for the process to exit before continuing on with other
units. This is the default Type= and ExecStart= are not set. It is used for one-
off tasks.
● dbus: This indicates that unit will take a name on the D-Bus bus. When this
happens, systemd will continue to process the next unit.
● notify: This indicates that the service will issue a notification when it has
finished starting up. The systemd process will wait for this to happen before
proceeding to other units.
● idle: This indicates that the service will not be run until all jobs are
dispatched.
Some additional directives may be needed when using certain service types. For
instance:
● RemainAfterExit=: This directive is commonly used with the oneshot type. It
indicates that the service should be considered active even after the process
exits.
● PIDFile=: If the service type is marked as "forking", this directive is used to
set the path of the file that should contain the process ID number of the main
child that should be monitored.
● BusName=: This directive should be set to the D-Bus bus name that the
service will attempt to acquire when using the "dbus" service type.
● NotifyAccess=: This specifies access to the socket that should be used to
listen for notifications when the "notify" service type is selected This can be
"none", "main", or "all. The default, "none", ignores all status messages. The
"main" option will listen to messages from the main process and the "all"
option will cause all members of the service's control group to be processed.
So far, we have discussed some pre-requisite information, but we haven't actually
defined how to manage our services. The directives to do this are:
● ExecStart=: This specifies the full path and the arguments of the command to
be executed to start the process. This may only be specified once (except for
"oneshot" services). If the path to the command is preceded by a dash "-"
character, non-zero exit statuses will be accepted without marking the unit
activation as failed.
● ExecStartPre=: This can be used to provide additional commands that should
be executed before the main process is started. This can be used multiple
times. Again, commands must specify a full path and they can be preceded by
"-" to indicate that the failure of the command will be tolerated.
● ExecStartPost=: This has the same exact qualities as ExecStartPre= except
that it specifies commands that will be run after the main process is started.
● ExecReload=: This optional directive indicates the command necessary to
reload the configuration of the service if available.
● ExecStop=: This indicates the command needed to stop the service. If this is
not given, the process will be killed immediately when the service is stopped.
● ExecStopPost=: This can be used to specify commands to execute following
the stop command.
● RestartSec=: If automatically restarting the service is enabled, this specifies
the amount of time to wait before attempting to restart the service.
● Restart=: This indicates the circumstances under which systemd will attempt
to automatically restart the service. This can be set to values like "always",
"on-success", "on-failure", "on-abnormal", "on-abort", or "on-watchdog".
These will trigger a restart according to the way that the service was stopped.
● TimeoutSec=: This configures the amount of time that systemd will wait
when stopping or stopping the service before marking it as failed or forcefully
killing it. You can set separate timeouts with TimeoutStartSec= and
TimeoutStopSec= as well.

The [Socket] Section


Socket units are very common in systemd configurations because many services
implement socket-based activation to provide better parallelization and flexibility.
Each socket unit must have a matching service unit that will be activated when the
socket receives activity.
By breaking socket control outside of the service itself, sockets can be initialized
early and the associated services can often be started in parallel. By default, the
socket name will attempt to start the service of the same name upon receiving a
connection. When the service is initialized, the socket will be passed to it, allowing it
to begin processing any buffered requests.
To specify the actual socket, these directives are common:
● ListenStream=: This defines an address for a stream socket which supports
sequential, reliable communication. Services that use TCP should use this
socket type.
● ListenDatagram=: This defines an address for a datagram socket which
supports fast, unreliable communication packets. Services that use UDP
should set this socket type.
● ListenSequentialPacket=: This defines an address for sequential, reliable
communication with max length datagrams that preserves message
boundaries. This is found most often for Unix sockets.
● ListenFIFO: Along with the other listening types, you can also specify a FIFO
buffer instead of a socket.
There are more types of listening directives, but the ones above are the most
common.
Other characteristics of the sockets can be controlled through additional directives:
● Accept=: This determines whether an additional instance of the service will
be started for each connection. If set to false (the default), one instance will
handle all connections.
● SocketUser=: With a Unix socket, specifies the owner of the socket. This will
be the root user if left unset.
● SocketGroup=: With a Unix socket, specifies the group owner of the socket.
This will be the root group if neither this or the above are set. If only the
SocketUser= is set, systemd will try to find a matching group.
● SocketMode=: For Unix sockets or FIFO buffers, this sets the permissions on
the created entity.
● Service=: If the service name does not match the .socket name, the service
can be specified with this directive.

The [Mount] Section


Mount units allow for mount point management from within systemd. Mount points
are named after the directory that they control, with a translation algorithm applied.
For example, the leading slash is removed, all other slashes are translated into
dashes "-", and all dashes and unprintable characters are replaced with C-style
escape codes. The result of this translation is used as the mount unit name. Mount
units will have an implicit dependency on other mounts above it in the hierarchy.
Mount units are often translated directly from /etc/fstab files during the boot
process. For the unit definitions automatically created and those that you wish to
define in a unit file, the following directives are useful:
● What=: The absolute path to the resource that needs to be mounted.
● Where=: The absolute path of the mount point where the resource should be
mounted. This should be the same as the unit file name, except using
conventional filesystem notation.
● Type=: The filesystem type of the mount.
● Options=: Any mount options that need to be applied. This is a comma-
separated list.
● SloppyOptions=: A boolean that determines whether the mount will fail if
there is an unrecognized mount option.
● DirectoryMode=: If parent directories need to be created for the mount
point, this determines the permission mode of these directories.
● TimeoutSec=: Configures the amount of time the system will wait until the
mount operation is marked as failed.

The [Automount] Section


This unit allows an associated .mount unit to be automatically mounted at boot. As
with the .mount unit, these units must be named after the translated mount point's
path.
The [Automount] section is pretty simple, with only the following two options
allowed:
● Where=: The absolute path of the automount point on the filesystem. This
will match the filename except that it uses conventional path notation instead
of the translation.
● DirectoryMode=: If the automount point or any parent directories need to be
created, this will determine the permissions settings of those path
components.

The [Swap] Section


Swap units are used to configure swap space on the system. The units must be
named after the swap file or the swap device, using the same filesystem translation
that was discussed above.
Like the mount options, the swap units can be automatically created from /etc/fstab
entries, or can be configured through a dedicated unit file.
The [Swap] section of a unit file can contain the following directives for
configuration:
● What=: The absolute path to the location of the swap space, whether this is a
file or a device.
● Priority=: This takes an integer that indicates the priority of the swap being
configured.
● Options=: Any options that are typically set in the /etc/fstab file can be set
with this directive instead. A comma-separated list is used.
● TimeoutSec=: The amount of time that systemd waits for the swap to be
activated before marking the operation as a failure.

The [Path] Section


A path unit defines a filesystem path that systmed can monitor for changes. Another
unit must exist that will be be activated when certain activity is detected at the path
location. Path activity is determined thorugh inotify events.
The [Path] section of a unit file can contain the following directives:
● PathExists=: This directive is used to check whether the path in question
exists. If it does, the associated unit is activated.
● PathExistsGlob=: This is the same as the above, but supports file glob
expressions for determining path existence.
● PathChanged=: This watches the path location for changes. The associated
unit is activated if a change is detected when the watched file is closed.
● PathModified=: This watches for changes like the above directive, but it
activates on file writes as well as when the file is closed.
● DirectoryNotEmpty=: This directive allows systemd to activate the
associated unit when the directory is no longer empty.
● Unit=: This specifies the unit to activate when the path conditions specified
above are met. If this is omitted, systemd will look for a .service file that
shares the same base unit name as this unit.
● MakeDirectory=: This determines if systemd will create the directory
structure of the path in question prior to watching.
● DirectoryMode=: If the above is enabled, this will set the permission mode of
any path components that must be created.

The [Timer] Section


Timer units are used to schedule tasks to operate at a specific time or after a certain
delay. This unit type replaces or supplements some of the functionality of the cron
and at daemons. An associated unit must be provided which will be activated when
the timer is reached.
The [Timer] section of a unit file can contain some of the following directives:
● OnActiveSec=: This directive allows the associated unit to be activated
relative to the .timer unit's activation.
● OnBootSec=: This directive is used to specify the amount of time after the
system is booted when the associated unit should be activated.
● OnStartupSec=: This directive is similar to the above timer, but in relation to
when the systemd process itself was started.
● OnUnitActiveSec=: This sets a timer according to when the associated unit
was last activated.
● OnUnitInactiveSec=: This sets the timer in relation to when the associated
unit was last marked as inactive.
● OnCalendar=: This allows you to activate the associated unit by specifying an
absolute instead of relative to an event.
● AccuracySec=: This unit is used to set the level of accuracy with which the
timer should be adhered to. By default, the associated unit will be activated
within one minute of the timer being reached. The value of this directive will
determine the upper bounds on the window in which systemd schedules the
activation to occur.
● Unit=: This directive is used to specify the unit that should be activated when
the timer elapses. If unset, systemd will look for a .service unit with a name
that matches this unit.
● Persistent=: If this is set, systemd will trigger the associated unit when the
timer becomes active if it would have been triggered during the period in
which the timer was inactive.
● WakeSystem=: Setting this directive allows you to wake a system from
suspend if the timer is reached when in that state.

The [Slice] Section


The [Slice] section of a unit file actually does not have any .slice unit specific
configuration. Instead, it can contain some resource management directives that are
actually available to a number of the units listed above.
Some common directives in the [Slice] section, which may also be used in other
units can be found in the [Link]-control man page. These are valid in the
following unit-specific sections:

● [Slice]
● [Scope]
● [Service]
● [Socket]
● [Mount]
● [Swap]

Creating Instance Units from Template Unit Files


We mentioned earlier in this guide the idea of template unit files being used to
create multiple instances of units. In this section, we can go over this concept in
more detail.
Template unit files are, in most ways, no different than regular unit files. However,
these provide flexibility in configuring units by allowing certain parts of the file to
utilize dynamic information that will be available at runtime.

Template and Instance Unit Names


Template unit files can be identified because they contain an @ symbol after the
base unit name and before the unit type suffix. A template unit file name may look
like this:
example@.service
When an instance is created from a template, an instance identifier is placed
between the @ symbol and the period signifying the start of the unit type. For
example, the above template unit file could be used to create an instance unit that
looks like this:
example@[Link]

An instance file is usually created as a symbolic link to the template file, with the
link name including the instance identifier. In this way, multiple links with unique
identifiers can point back to a single template file. When managing an instance unit,
systemd will look for a file with the exact instance name you specify on the
command line to use. If it cannot find one, it will look for an associated template file.

Template Specifiers
The power of template unit files is mainly seen through its ability to dynamically
substitute appropriate information within the unit definition according to the
operating environment. This is done by setting the directives in the template file as
normal, but replacing certain values or parts of values with variable specifiers.
The following are some of the more common specifiers will be replaced when an
instance unit is interpreted with the relevant information:
● %n: Anywhere where this appears in a template file, the full resulting unit
name will be inserted.
● %N: This is the same as the above, but any escaping, such as those present in
file path patterns, will be reversed.
● %p: This references the unit name prefix. This is the portion of the unit name
that comes before the @ symbol.
● %P: This is the same as above, but with any escaping reversed.
● %i: This references the instance name, which is the identifier following the @
in the instance unit. This is one of the most commonly used specifiers because
it will be guaranteed to be dynamic. The use of this identifier encourages the
use of configuration significant identifiers. For example, the port that the
service will be run at can be used as the instance identifier and the template
can use this specifier to set up the port specification.
● %I: This specifier is the same as the above, but with any escaping reversed.
● %f: This will be replaced with the unescaped instance name or the prefix
name, prepended with a /.
● %c: This will indicate the control group of the unit, with the standard parent
hierarchy of /sys/fs/cgroup/ssytemd/ removed.
● %u: The name of the user configured to run the unit.
● %U: The same as above, but as a numeric UID instead of name.
● %H: The host name of the system that is running the unit.
● %%: This is used to insert a literal percentage sign.
By using the above identifiers in a template file, systemd will fill in the correct
values when interpreting the template to create an instance unit.

Conclusion
When working with systemd, understanding units and unit files can make
administration simple. Unlike many other init systems, you do not have to know a
scripting language to interpret the init files used to boot services or the system. The
unit files use a fairly simple declarative syntax that allows you to see at a glance the
purpose and effects of a unit upon activation.

Breaking functionality such as activation logic into separate units not only allows
the internal systemd processes to optimize parallel initialization, it also keeps the
configuration rather simple and allows you to modify and restart some units
without tearing down and rebuilding their associated connections. Leveraging these
abilities can give you more flexibility and power during administration.

How To Use Systemctl to Manage SystemHow to Manage Services and Units


and Target

Introduction
Systemd is an init system and system manager that is widely becoming the new
standard for Linux machines. While there are considerable opinions about whether
systemd is an improvement over the traditional SysV init systems it is replacing, the
majority of distributions plan to adopt it or have already done so.
Due to its heavy adoption, familiarizing yourself with systemd is well worth the
trouble, as it will make administrating these servers considerably easier. Learning
about and utilizing the tools and daemons that comprise systemd will help you
better appreciate the power, flexibility, and capabilities it provides, or at least help
you to do your job with minimal hassle.
In this guide, we will be discussing the systemctl command, which is the central
management tool for controlling the init system. We will cover how to manage
services, check statuses, change system states, and work with the configuration files.

Service Management
The fundamental purpose of an init system is to initialize the components that must
be started after the Linux kernel is booted (traditionally known as “userland”
components). The init system is also used to manage services and daemons for the
server at any point while the system is running. With that in mind, we will start with
some simple service management operations.
In systemd, the target of most actions are “units”, which are resources that systemd
knows how to manage. Units are categorized by the type of resource they represent
and they are defined with files known as unit files. The type of each unit can be
inferred from the suffix on the end of the file.
For service management tasks, the target unit will be service units, which have unit
files with a suffix [Link]. However, for most service management commands, you
can actually leave off the .servicesuffix, as systemd is smart enough to know that you
probably want to operate on a service when using service management commands.

Starting and Stopping Services


To start a systemd service, executing instructions in the service’s unit file, use the
start command. If you are running as a non-root user, you will have to use sudo
since this will affect the state of the operating system:
sudo systemctl start [Link]

As we mentioned above, systemd knows to look for *.service files for service
management commands, so the command could just as easily be typed like this:
sudo systemctl start application

Although you may use the above format for general administration, for clarity, we
will use the .servicesuffix for the remainder of the commands to be explicit about
the target we are operating on.
To stop a currently running service, you can use the stop command instead:
sudo systemctl stop [Link]

Restarting and Reloading


To restart a running service, you can use the restart command:
sudo systemctl restart [Link]

If the application in question is able to reload its configuration files (without


restarting), you can issue thereload command to initiate that process:
sudo systemctl reload [Link]

If you are unsure whether the service has the functionality to reload its
configuration, you can issue thereload-or-restart command. This will reload the
configuration in-place if available. Otherwise, it will restart the service so the new
configuration is picked up:
sudo systemctl reload-or-restart [Link]

Enabling and Disabling Services


The above commands are useful for starting or stopping commands during the
current session. To tellsystemd to start services automatically at boot, you must
enable them.
To start a service at boot, use the enable command:
sudo systemctl enable [Link]

This will create a symbolic link from the system’s copy of the service file (usually
in /lib/systemd/systemor /etc/systemd/system) into the location on disk where
systemd looks for autostart files
(usually/etc/systemd/system/some_target.[Link]. We will go over what a
target is later in this guide).
To disable the service from starting automatically, you can type:
sudo systemctl disable [Link]

This will remove the symbolic link that indicated that the service should be started
automatically.
Keep in mind that enabling a service does not start it in the current session. If you
wish to start the service and enable it at boot, you will have to issue both the start
and enable commands.

Checking the Status of Services


To check the status of a service on your system, you can use the status command:
systemctl status [Link]

This will provide you with the service state, the cgroup hierarchy, and the first few
log lines.
For instance, when checking the status of an Nginx server, you may see output like
this:
● [Link] - A high performance web server and a reverse proxy server
Loaded: loaded (/usr/lib/systemd/system/[Link]; enabled; vendor preset:
disabled)
Active: active (running) since Tue 2015-01-27 19:41:23 EST; 22h ago
Main PID: 495 (nginx)
CGroup: /[Link]/[Link]
├─495 nginx: master process /usr/bin/nginx -g pid /run/[Link]; error_log
stderr;
└─496 nginx: worker process

Jan 27 19:41:23 desktop systemd[1]: Starting A high performance web server and a
reverse proxy server...
Jan 27 19:41:23 desktop systemd[1]: Started A high performance web server and a
reverse proxy server.

This gives you a nice overview of the current status of the application, notifying you
of any problems and any actions that may be required.
There are also methods for checking for specific states. For instance, to check to see
if a unit is currently active (running), you can use the is-active command:
systemctl is-active [Link]

This will return the current unit state, which is usually active or inactive. The exit
code will be “0” if it is active, making the result simpler to parse programatically.
To see if the unit is enabled, you can use the is-enabled command:
systemctl is-enabled [Link]

This will output whether the service is enabled or disabled and will again set the
exit code to “0” or “1” depending on the answer to the command question.
A third check is whether the unit is in a failed state. This indicates that there was a
problem starting the unit in question:
systemctl is-failed [Link]

This will return active if it is running properly or failed if an error occurred. If the
unit was intentionally stopped, it may return unknown or inactive. An exit status of
“0” indicates that a failure occurred and an exit status of “1” indicates any other
status.

System State Overview


The commands so far have been useful for managing single services, but they are
not very helpful for exploring the current state of the system. There are a number of
systemctl commands that provide this information.

Listing Current Units


To see a list of all of the active units that systemd knows about, we can use the list-
units command:
systemctl list-units

This will show you a list of all of the units that systemd currently has active on the
system. The output will look something like this:
UNIT LOAD ACTIVE SUB DESCRIPTION
[Link] loaded active running ATD daemon
[Link] loaded active running Avahi mDNS/DNS-SD Stack
[Link] loaded active running D-Bus System Message Bus
[Link] loaded active running Periodic Command Scheduler
[Link] loaded active exited Dynamic Kernel Modules System
getty@[Link] loaded active running Getty on tty1

...
The output has the following columns:
● UNIT: The systemd unit name
● LOAD: Whether the unit’s configuration has been parsed by systemd. The
configuration of loaded units is kept in memory.
● ACTIVE: A summary state about whether the unit is active. This is usually a
fairly basic way to tell if the unit has started successfully or not.
● SUB: This is a lower-level state that indicates more detailed information
about the unit. This often varies by unit type, state, and the actual method in
which the unit runs.
● DESCRIPTION: A short textual description of what the unit is/does.
Since the list-units command shows only active units by default, all of the entries
above will show “loaded” in the LOAD column and “active” in the ACTIVE column.
This display is actually the default behavior of systemctl when called without
additional commands, so you will see the same thing if you call systemctl with no
arguments:
systemctl

We can tell systemctl to output different information by adding additional flags. For
instance, to see all of the units that systemd has loaded (or attempted to load),
regardless of whether they are currently active, you can use the --all flag, like this:
systemctl list-units --all

This will show any unit that systemd loaded or attempted to load, regardless of its
current state on the system. Some units become inactive after running, and some
units that systemd attempted to load may have not been found on disk.
You can use other flags to filter these results. For example, we can use the --state=
flag to indicate the LOAD, ACTIVE, or SUB states that we wish to see. You will have to
keep the --all flag so thatsystemctl allows non-active units to be displayed:
systemctl list-units --all --state=inactive

Another common filter is the --type= filter. We can tell systemctl to only display
units of the type we are interested in. For example, to see only active service units,
we can use:
systemctl list-units --type=service

Listing All Unit Files


The list-units command only displays units that systemd has attempted to parse and
load into memory. Since systemd will only read units that it thinks it needs, this will
not necessarily include all of the available units on the system. To see every available
unit file within the systemd paths, including those that systemd has not attempted
to load, you can use the list-unit-files command instead:
systemctl list-unit-files
Units are representations of resources that systemd knows about. Since systemd has
not necessarily read all of the unit definitions in this view, it only presents
information about the files themselves. The output has two columns: the unit file
and the state.
UNIT FILE STATE
proc-sys-fs-binfmt_misc.automount static
[Link] static
[Link] static
[Link] static
proc-sys-fs-binfmt_misc.mount static
[Link] static
[Link] static
[Link] static
[Link] static
var-lib-nfs-rpc_pipefs.mount static
[Link] enabled

...

The state will usually be “enabled”, “disabled”, “static”, or “masked”. In this context,
static means that the unit file does not contain an “install” section, which is used to
enable a unit. As such, these units cannot be enabled. Usually, this means that the
unit performs a one-off action or is used only as a dependency of another unit and
should not be run by itself.
We will cover what “masked” means momentarily.

Unit Management
So far, we have been working with services and displaying information about the
unit and unit files thatsystemd knows about. However, we can find out more specific
information about units using some additional commands.

Displaying a Unit File


To display the unit file that systemd has loaded into its system, you can use the cat
command (this was added in systemd version 209). For instance, to see the unit file
of the atd scheduling daemon, we could type:
systemctl cat [Link]

[Unit]
Description=ATD daemon

[Service]
Type=forking
ExecStart=/usr/bin/atd

[Install]
WantedBy=[Link]

The output is the unit file as known to the currently running systemd process. This
can be important if you have modified unit files recently or if you are overriding
certain options in a unit file fragment (we will cover this later).

Displaying Dependencies
To see a unit’s dependency tree, you can use the list-dependencies command:
systemctl list-dependencies [Link]

This will display a hierarchy mapping the dependencies that must be dealt with in
order to start the unit in question. Dependencies, in this context, include those units
that are either required by or wanted by the units above it.
[Link]
├─[Link]
└─[Link]
├─[Link]
├─[Link]
├─[Link]
├─[Link]
├─[Link]
├─[Link]
├─[Link]
├─[Link]

...

The recursive dependencies are only displayed for .target units, which indicate
system states. To recursively list all dependencies, include the --all flag.
To show reverse dependencies (units that depend on the specified unit), you can
add the --reverse flag to the command. Other flags that are useful are the --before
and --after flags, which can be used to show units that depend on the specified unit
starting before and after themselves, respectively.

Checking Unit Properties


To see the low-level properties of a unit, you can use the show command. This will
display a list of properties that are set for the specified unit using a key=value
format:
systemctl show [Link]

Id=[Link]
Names=[Link]
Requires=[Link]
Wants=[Link]
WantedBy=[Link]
Conflicts=[Link]
Before=[Link] [Link]
After=[Link] [Link] [Link] [Link]
[Link] [Link]
Description=OpenSSH server daemon

...

If you want to display a single property, you can pass the -p flag with the property
name. For instance, to see the conflicts that the [Link] unit has, you can type:
systemctl show [Link] -p Conflicts

Conflicts=[Link]

Masking and Unmasking Units


We saw in the service management section how to stop or disable a service, but
systemd also has the ability to mark a unit as completely unstartable, automatically
or manually, by linking it to /dev/null. This is called masking the unit, and is
possible with the mask command:
sudo systemctl mask [Link]

This will prevent the Nginx service from being started, automatically or manually,
for as long as it is masked.
If you check the list-unit-files, you will see the service is now listed as masked:
systemctl list-unit-files

...

[Link] static
[Link] static
[Link] static
[Link] static
[Link] masked
[Link] static
[Link] static
[Link] disabled
[Link] static

...

If you attempt to start the service, you will see a message like this:
sudo systemctl start [Link]

Failed to start [Link]: Unit [Link] is masked.

To unmask a unit, making it available for use again, simply use the unmask
command:
sudo systemctl unmask [Link]

This will return the unit to its previous state, allowing it to be started or enabled.

Editing Unit Files


While the specific format for unit files is outside of the scope of this tutorial,
systemctl provides builtin mechanisms for editing and modifying unit files if you
need to make adjustments. This functionality was added in systemd version 218.
The edit command, by default, will open a unit file snippet for the unit in question:
sudo systemctl edit [Link]

This will be a blank file that can be used to override or add directives to the unit
definition. A directory will be created within the /etc/systemd/system directory
which contains the name of the unit with .dappended. For instance, for the
[Link], a directory called [Link].d will be created.
Within this directory, a snippet will be created called [Link]. When the unit is
loaded, systemdwill, in memory, merge the override snippet with the full unit file.
The snippet’s directives will take precedence over those found in the original unit
file.
If you wish to edit the full unit file instead of creating a snippet, you can pass the --
full flag:
sudo systemctl edit --full [Link]

This will load the current unit file into the editor, where it can be modified. When
the editor exits, the changed file will be written to /etc/systemd/system, which will
take precedence over the system’s unit definition (usually found somewhere in
/lib/systemd/system).
To remove any additions you have made, either delete the unit’s .d configuration
directory or the modified service file from /etc/systemd/system. For instance, to
remove a snippet, we could type:
sudo rm -r /etc/systemd/system/[Link].d

To remove a full modified unit file, we would type:

sudo rm /etc/systemd/system/[Link]

After deleting the file or directory, you should reload the systemd process so that it
no longer attempts to reference these files and reverts back to using the system
copies. You can do this by typing:

sudo systemctl daemon-reload

Adjusting the System State (Runlevel) with Targets


Targets are special unit files that describe a system state or synchronization point.
Like other units, the files that define targets can be identified by their suffix, which
in this case is .target. Targets do not do much themselves, but are instead used to
group other units together.
This can be used in order to bring the system to certain states, much like other init
systems use runlevels. They are used as a reference for when certain functions are
available, allowing you to specify the desired state instead of the individual units
needed to produce that state.
For instance, there is a [Link] that is used to indicate that swap is ready for
use. Units that are part of this process can sync with this target by indicating in their
configuration that they are WantedBy= orRequiredBy= the [Link]. Units that
require swap to be available can specify this condition using the Wants=, Requires=,
and After= specifications to indicate the nature of their relationship.

Getting and Setting the Default Target


The systemd process has a default target that it uses when booting the system.
Satisfying the cascade of dependencies from that single target will bring the system
into the desired state. To find the default target for your system, type:
systemctl get-default

[Link]

If you wish to set a different default target, you can use the set-default. For instance,
if you have a graphical desktop installed and you wish for the system to boot into
that by default, you can change your default target accordingly:
sudo systemctl set-default [Link]

Listing Available Targets


You can get a list of the available targets on your system by typing:
systemctl list-unit-files --type=target

Unlike runlevels, multiple targets can be active at one time. An active target
indicates that systemd has attempted to start all of the units tied to the target and
has not tried to tear them down again. To see all of the active targets, type:
systemctl list-units --type=target

Isolating Targets
It is possible to start all of the units associated with a target and stop all units that
are not part of the dependency tree. The command that we need to do this is called,
appropriately, isolate. This is similar to changing the runlevel in other init systems.
For instance, if you are operating in a graphical environment with [Link]
active, you can shut down the graphical system and put the system into a multi-user
command line state by isolating [Link]. Since [Link] depends
on [Link] but not the other way around, all of the graphical units will be
stopped.
You may wish to take a look at the dependencies of the target you are isolating
before performing this procedure to ensure that you are not stopping vital services:
systemctl list-dependencies [Link]

When you are satisfied with the units that will be kept alive, you can isolate the
target by typing:
sudo systemctl isolate [Link]

Using Shortcuts for Important Events


There are targets defined for important events like powering off or rebooting.
However, systemctl also has some shortcuts that add a bit of additional
functionality.
For instance, to put the system into rescue (single-user) mode, you can just use the
rescue command instead of isolate [Link]:
sudo systemctl rescue

This will provide the additional functionality of alerting all logged in users about the
event.
To halt the system, you can use the halt command:
sudo systemctl halt

To initiate a full shutdown, you can use the poweroff command:


sudo systemctl poweroff

A restart can be started with the reboot command:


sudo systemctl reboot
These all alert logged in users that the event is occurring, something that simply
running or isolating the target will not do. Note that most machines will link the
shorter, more conventional commands for these operations so that they work
properly with systemd.
For example, to reboot the system, you can usually type:
sudo reboot

While systemctl operates mainly with the core systemd process, there are other
components to thesystemd ecosystem that are controlled by other utilities. Other
capabilities, like log management and user sessions are handled by separate
daemons and management utilities (journald/journalctl andlogind/loginctl
respectively). Taking time to become familiar with these other tools and daemons
will make management an easier task.

Source: [Link]
systemctl-to-manage-systemd-services-and-units

You might also like