systemd
systemd
is an init system and system manager that has widely become the new standard for Linux distributions. Due to its heavy adoption, familiarizing yourself with systemd
is well worth the trouble, as it will make administering servers considerably easier. Learning about and using 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 less 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 basic 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 of .service
. However, for most service management commands, you can actually leave off the .service
suffix, 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 application.service
As we mentioned above, systemd
knows to look for *.service
files for service management commands, so the command could be typed like this:
sudo systemctl start application
Although you may use the above format for general administration, for clarity, we will use the .service
suffix 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 application.service
Restarting and Reloading
To restart a running service, you can use the restart
command:
sudo systemctl restart application.service
If the application in question is able to reload its configuration files (without restarting), you can issue the reload
command to initiate that process:
sudo systemctl reload application.service
If you are unsure whether the service has the functionality to reload its configuration, you can issue the reload-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 application.service
Enabling and Disabling Services
The above commands are useful for starting or stopping services during the current session. To tell systemd
to start services automatically at boot, you must enable them.
To start a service at boot, use the enable
command:
sudo systemctl enable application.service
This will create a symbolic link from the system’s copy of the service file (usually in /lib/systemd/system
or /etc/systemd/system
) into the location on disk where systemd
looks for autostart files (usually /etc/systemd/system/some_target.target.wants
. 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 application.service
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 also enable it at boot, you will have to issue both the start
and enable
commands.
View the Status of Services
Listing Current Units
To see a list of all of the a ctive units that systemd
knows about, we can use the list-units
command:
# Show all running services:
$ systemctl status
# or
$ systemctl list-units --type=service --state=active
# List failed units:
$ systemctl --failed
# Show the status of a service:
$ systemctl status <service_nma>
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:
OutputUNIT LOAD ACTIVE SUB DESCRIPTION
atd.service loaded active running ATD daemon
avahi-daemon.service loaded active running Avahi mDNS/DNS-SD Stack
dbus.service loaded active running D-Bus System Message Bus
dcron.service loaded active running Periodic Command Scheduler
dkms.service loaded active exited Dynamic Kernel Modules System
getty@tty1.service 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.
For instance, when checking the status of an Nginx server, you may see output like this:
$ systemctl status nginx.service
Output● nginx.service - A high performance web server and a reverse proxy server
Loaded: loaded (/usr/lib/systemd/system/nginx.service; enabled; vendor preset: disabled)
Active: active (running) since Tue 2015-01-27 19:41:23 EST; 22h ago
Main PID: 495 (nginx)
CGroup: /system.slice/nginx.service
├─495 nginx: master process /usr/bin/nginx -g pid /run/nginx.pid; 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.
Check is active or not
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 application.service
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 in shell scripts.
Check is enabled or not
To see if the unit is enabled, you can use the is-enabled
command:
systemctl is-enabled application.service
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.
Check is failed or not
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 application.service
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.
Reload changed Units
# Reload systemd, scanning for new or changed units:
$ systemctl daemon-reload
View Service Logs
Just use the journalctl
command, as in:
$ journalctl -u <service-name.service>
Or, to see only log messages for the current boot:
$ journalctl -u <service-name.service> -b
# [f]ollow new messages (like tail -f for traditional syslog):
$ journalctl -f -u <service-name.service>
Unit Management
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 atd.service
Output[Unit]
Description=ATD daemon
[Service]
Type=forking
ExecStart=/usr/bin/atd
[Install]
WantedBy=multi-user.target
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 sshd.service
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.
Outputsshd.service
├─system.slice
└─basic.target
├─microcode.service
├─rhel-autorelabel-mark.service
├─rhel-autorelabel.service
├─rhel-configure.service
├─rhel-dmesg.service
├─rhel-loadmodules.service
├─paths.target
├─slices.target
. . .
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.
Editing Unit Files
While the specific format for unit files is outside of the scope of this tutorial, systemctl
provides built-in 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 nginx.service
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 .d
appended. For instance, for the nginx.service
, a directory called nginx.service.d
will be created.
Within this directory, a snippet will be created called override.conf
. When the unit is loaded, systemd
will, 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 nginx.service
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/nginx.service.d
To remove a full modified unit file, we would type:
sudo rm /etc/systemd/system/nginx.service
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
Config File
sample
Create the unit file for my_proxy
:
$ sudo vim /etc/systemd/system/my_proxy.service
[Unit]
Description=SW Socks5 Proxy
After=network.target
[Service]
Type=simple
ExecStart=/usr/local/bin/microsocks
[Install]
WantedBy=multi-user.target
[Unit]
This section usually contains the Description, Documentation, After, Before, Wants, and Require statements.
Description: - This statement provides a brief description of the unit.
Documentation: - This statement provides the location of the man (help document) page and the command to access the man page.
After: - This statement lists the units which should be activated before this unit.
Before: - This statement lists the units which should be activated after this unit.
Wants: - This statement lists the units/services which should be started before this unit.
Requires: - This statement lists the units/services which must be started before this unit.
Conflicts: - This statement lists the units/services which must be stopped before starting this unit.
Key points
- Systemd starts all units of the system.
- The After/Before statements of a unit define the order in which the unit should be started.
- The Wants/ Requires statements of a unit define the dependencies of the unit.
- Systemd automatically resolves the dependencies and activates the units/services listed in the Wants/Requires statements.
- When activating/starting a unit, systemd first activates/starts the services/units listed in the Wants/Requires statements.
- If the systemd fails to activate the services listed in the Wants statement, it does not stop the process of activating the main unit. It simply starts the unit ignoring the failed services.
- But, if the systemd fails to activate the services listed in the Requires statement, it does not start the main unit.
[Type]
The heading of this section (the keyword between the square brackets) shows the type of the unit. For example, if the unit type is the Service then this section uses the heading [Service] and if the unit type is the Socket then this section uses the heading [Socket]. Statements of this section contain the control operations/commands of the unit.
The common statements that you can find in this section are the following.
ExecStart: - This command starts the unit.
ExecStop: - This command stops the unit.
ExecReload: - This command reloads the unit.
EnvironmentFile: - This statement lists the location of the main configuration file of the unit.
[Install]
This section contains information about the target unit. The most common option that you may see in this section is the following.
WantedBy: - Name of the target unit which starts this unit automatically. For example, if you see the multi-user.target in this statement, then it means when the system enters into the “multi-user.target” target level, this unit is started automatically.
In systemd, a target level is a specific state of the system. In the next part of this article, I will explain the target levels in detail. That’s all for this tutorial. If you like this tutorial, please don’t forget to share it with friends.
Reference
- https://www.digitalocean.com/community/tutorials/how-to-use-systemctl-to-manage-systemd-services-and-units
- https://man7.org/linux/man-pages/man1/systemctl.1.html