【Linux】systemctl

Posted by 西维蜀黍 on 2022-03-22, Last Modified on 2023-05-02

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

# Show all running services:
$ systemctl status

# List failed units:
$ systemctl --failed
    
# Show the status of a unit:
$ systemctl status <unit>

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.

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 a ctive 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:

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.

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