read 20 minutes

How to Use Systemctl for Managing Systemd Services and Units


systemd is an initialization system and service manager that has emerged as the new standard for Linux distributions. Though the learning curve for systemd can be steep due to its intricate adoption, mastering it can greatly streamline server administration tasks. Familiarizing yourself with the tools and daemons comprised within systemd will enable you to unlock its potential and flexibility, or at the very least, perform tasks more seamlessly.

In this guide, we will look at the systemctl command, a vital management instrument for governing the initialization system. We will explore techniques for managing services, checking statuses, modifying system states, and interacting with configuration files.

It's important to note that not all Linux distributions have implemented systemd as their default initialization system. If you encounter the error bash: systemctl is not installed when following this guide, it is probable that your machine employs a different initialization system.

Managing Services

The main function of an initialization system is to launch components that need to be initialized following the booting of the Linux kernel (commonly referred to as "userland" components). Additionally, the initialization system is responsible for managing services and daemons while the system is operating. With this context, we will commence with several basic service management procedures.

Within systemd, the primary subjects of most actions are "units," which signify resources that systemd can oversee. Units are categorized by the kind of resource they embody and are defined using files called unit files. The category of each unit can be deduced from the suffix appended to the file.

For service management operations, the target units will be service units, which possess unit files with a .service suffix. Nevertheless, in the majority of service management commands, you can exclude the .service suffix, as systemd can easily discern that you likely intend to interact with a service utilizing service management commands.

Starting and Stopping Services

To start a systemd service with the instructions in the service unit file, use the start command. If operating as a non-root user, sudo will be necessary, as this action impacts the state of the operating system:

sudo systemctl start application.service

As previously noted, systemd will search for *.service files for service management commands, permitting the command to be input like this:

sudo systemctl start application

While this format is suitable for general administration, we will utilize the .service suffix for the subsequent commands to explicitly denote the target being worked with.

To halt an active service, apply the stop command:

sudo systemctl stop application.service

Restarting and Reloading

To restart a functioning service, employ the restart command:

sudo systemctl restart application.service

If the application concerned can reload configuration files (without restarting), initiate this process using the reload command:

sudo systemctl reload application.service

If uncertain whether the service can reload its configuration, issue the reload-or-restart command. This will lead to the configuration being reloaded if possible. If not, the service will restart to apply the updated configuration:

sudo systemctl reload-or-restart application.service

Enabling and Disabling Services

The aforementioned commands are helpful for initiating or terminating services during the present session. To instruct systemd to automatically start services at boot, they must be enabled.

To start a service at boot, utilize the enable command:

sudo systemctl enable application.service

This action generates a symbolic link from a system copy of the service file (typically in /lib/systemd/system or /etc/systemd/system) to the location on disk where systemd searches for files to autorun (usually /etc/systemd/system/some_target.target.wants). We will look at what a target is later in this manual).

To disable automatic start of a service, input:

sudo systemctl disable application.service

This will eliminate the symbolic link that signified the service should initiate automatically.

Keep in mind that enabling the service will not activate it in the current session. To both start the service and enable it at boot, you must provide both commands, start and enable.

Checking the status of services

To check the status of a service on your system, utilize the status command:

systemctl status application.service

This provides information on the service's status, control group hierarchy, and initial log entries.

For instance, when verifying the status of a Nginx server, the following output might be displayed:

● 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 offers a comprehensive overview of the application's current status and alerts you to any issues or necessary actions.

There are also methods to check for specific statuses. For instance, to determine whether a module is presently active, use the is-active command:

systemctl is-active application.service

This returns the module's current status, typically active or inactive. If active, the exit code will be "0," making the result easier to parse in shell scripts.

To see if a module is enabled, apply the is-enabled command:

systemctl is-enabled application.service

This displays whether the service is enabled or disabled and sets the output code to "0" or "1" based on the command's inquiry.

The third check involves determining if the module is in a failed state, indicating an issue with starting the unit:

systemctl is-failed application.service

This returns active if functioning correctly or failed in case of an error. If the module was deliberately stopped, it may return unknown or inactive. An output status of "0" signifies a failure, while an output status of "1" represents a different status.

System State Overview

While the previous commands are useful for managing single services, they offer limited insight into the overall system state. Several systemctl commands can help provide this information.

Listing Current Units

To display a list of all active units recognized by systemd, use the list-units command:

systemctl list-units

This reveals a list of all units currently active within the system. The output may appear as follows:

UNIT                                      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
[email protected]                        loaded active running Getty on tty1 . . .

The output consists of the following columns:

  • UNIT: The systemd unit name
  • LOAD: Indicates if the unit’s configuration has been parsed by systemd. The configuration of loaded units is stored in memory.
  • ACTIVE: A summary state indicating whether the unit is active. This typically reveals whether the unit has started successfully.
  • SUB: A more detailed state providing additional information about the unit. This often varies depending on the unit type, state, and how the unit operates.
  • DESCRIPTION: A brief description of what the unit is/does.

By default, the list-units command only shows active units. Thus, all entries will display loaded in the LOAD column and active in the ACTIVE column. Executing systemctl without additional commands produces the same display:


To obtain different information, add extra flags. For example, use the --all flag to see all units systemd has loaded (or attempted to load), irrespective of their current activity:

systemctl list-units --all

This displays any unit that systemd loaded or tried to load, regardless of its system state. Some units become inactive after running, while others may not be found on disk after systemd attempts to load them.

You can use other flags to filter the results. For example, the --state= flag specifies the LOAD, ACTIVE, or SUB states to display. Keep the --all flag so that systemctl shows non-active units:

systemctl list-units --all --state=inactive

Another common filter is the --type= filter. To display only units of a particular type, use:

systemctl list-units --type=service

Listing All Unit Files

The list-units command only displays units that systemd has tried to parse and load into memory. Since systemd only reads the units it deems necessary, this list may not include all available units. To view every unit file within systemd paths, including those not attempted to load, use the list-unit-files command:

systemctl list-unit-files

Units represent resources known to systemd. As not all unit definitions are necessarily read in this view, it only presents information about the files themselves. The output features two columns: the unit file and its state.

UNIT FILE                                  STATE   
proc-sys-fs-binfmt_misc.automount          static  
dev-hugepages.mount                        static  
dev-mqueue.mount                           static  
proc-fs-nfsd.mount                         static  
proc-sys-fs-binfmt_misc.mount              static  
sys-fs-fuse-connections.mount              static  
sys-kernel-config.mount                    static  
sys-kernel-debug.mount                     static  
tmp.mount                                  static  
var-lib-nfs-rpc_pipefs.mount               static  
org.cups.cupsd.path                        enabled
. . .

States are typically enabled, disabled, static, or masked. In this context, static means the unit file lacks an install section required to enable a unit. As such, these units cannot be enabled. This usually implies that the unit carries out a one-time action or serves as a dependency for another unit and should not be run independently.

Next, we'll discuss the meaning of masked.

Unit Management

We've been working with services and displaying unit and unit file information that systemd recognizes. To learn more specific information about units, we can use additional commands.

Displaying a Unit File

To display the unit file that systemd has loaded into its system, utilize the cat command (introduced in systemd version 209). For example, to display the unit file for the atd scheduling daemon, enter:

systemctl cat atd.service Output
Description=ATD daemon

The output reveals the unit file as recognized by the currently running systemd process. This is important if you've recently modified unit files or if you're overriding specific options in a unit file fragment (we'll discuss this later).

Displaying Dependencies

To view a unit's dependency tree, use the list-dependencies command:

systemctl list-dependencies sshd.service

This shows a hierarchy outlining the dependencies that must be addressed to start the given unit. Dependencies include units either required or wanted by the units above them.

. . .

The recursive dependencies are only displayed for .target units, which indicate system states. To recursively list all dependencies, include the --all flag.

To display reverse dependencies (units depending on the specified unit), include the --reverse flag. The --before and --after flags are also helpful, showing units that depend on the specified unit starting before or after themselves, respectively.

Checking Unit Properties

To view a unit's low-level properties, use the show command. This displays a list of properties set for the specified unit in a key=value format:

systemctl show sshd.service Output
Before=shutdown.target multi-user.target
After=syslog.target network.target auditd.service systemd-journald.socket basic.target system.slice
Description=OpenSSH server daemon
. . .

To display a single property, use the -p flag with the property name. For example, to see conflicts related to the sshd.service unit, enter:

systemctl show sshd.service -p Conflicts Output

Masking and Unmasking Units

We've seen how to stop or disable a service, but systemd also enables marking a unit as entirely unstartable, either automatically or manually, by linking it to /dev/null. This is called masking the unit and can be accomplished with the mask command:

sudo systemctl mask nginx.service

This prevents the Nginx service from starting, either automatically or manually, as long as it remains masked.

When checking the list-unit-files, the service now appears as masked:

systemctl list-unit-files Output
. . .
kmod-static-nodes.service              static  
ldconfig.service                       static  
mandb.service                          static  
messagebus.service                     static  
nginx.service                          masked
quotaon.service                        static  
rc-local.service                       static  
rdisc.service                          disabled
rescue.service                         static
. . .

Attempting to start the service produces the following message:

sudo systemctl start nginx.service Output
Failed to start nginx.service: Unit nginx.service is masked.

To unmask a unit and make it available for use again, use the unmask command:

sudo systemctl unmask nginx.service

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

Editing Unit Files

The specific format for unit files falls outside the scope of this guide, but systemctl includes built-in tools for editing and modifying unit files when adjustments are required. This feature was introduced in systemd version 218.

By default, the edit command opens a snippet for the specified unit:

sudo systemctl edit nginx.service

This blank file allows you to override or add directives to the unit definition. A directory is created in the /etc/systemd/system directory, with the unit's name appended with .d. For example, a directory called nginx.service.d is created for the nginx.service.

Inside this directory, an override.conf snippet is created. When the unit is loaded, systemd merges the override snippet with the full unit file in memory. The snippet's directives take precedence over those in the original unit file.

If you prefer to edit the entire unit file instead of creating a snippet, use the --full flag:

sudo systemctl edit --full nginx.service

This command opens the current unit file in the editor, where you can make modifications. Upon exiting the editor, the modified file is saved to /etc/systemd/system, overriding the system's unit definition (typically found in /lib/systemd/system).

To remove any changes you've made, delete the unit's .d configuration directory or the modified service file from /etc/systemd/system. For example, to remove a snippet, enter:

sudo rm -r /etc/systemd/system/nginx.service.d

To remove a fully modified unit file, enter:

sudo rm /etc/systemd/system/nginx.service

After deleting the file or directory, reload the systemd process so it no longer references these files and reverts to using the system copies. This can be done by entering:

sudo systemctl daemon-reload

Adjusting the System State (Runlevel) with Targets

Targets represent unique 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. Although they don't do much on their own, targets are utilized to group other units together.

Targets help bring the system to certain states, similar to runlevels in other init systems. They serve as a reference for when specific functions are accessible, allowing the desired state to be specified instead of the individual units needed to achieve that state.

For example, a swap.target indicates that swap is ready to be used. Units involved in this process can synchronize with this target by specifying in their configuration that they are WantedBy= or RequiredBy= the swap.target. 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

Systemd has a default target that it utilizes when booting the system. Satisfying the dependencies of that single target brings the system to the desired state. To identify your system's default target, enter:

systemctl get-default Output

To set a different default target, use the set-default command. For example, if you have a graphical desktop installed and want the system to boot into it by default, change your default target accordingly:

sudo systemctl set-default graphical.target

Listing Available Targets

To view a list of available targets on your system, enter:

systemctl list-unit-files --type=target

Multiple targets can be active simultaneously. An active target signifies that systemd has attempted to start all units linked to the target and has not tried to stop them again. To view all active targets, enter:

systemctl list-units --type=target

Isolating Targets

Starting all units associated with a target and stopping all units not part of the dependency tree is possible. The command to achieve this is called isolate, which is akin to changing the runlevel in other initialization systems.

For example, if operating in a graphical environment with an active graphical.target, you can shut down the graphical system and transition the system into a multi-user command line state by isolating the multi-user.target. Since graphical.target depends on multi-user.target but not vice versa, all graphical units will be stopped.

Before isolating a target, you might want to review its dependencies to ensure you're not stopping essential services:

systemctl list-dependencies multi-user.target

Once you're satisfied with the units that will remain active, isolate the target by entering:

sudo systemctl isolate multi-user.target

Using Shortcuts for Important Events

Targets are designed for significant events like powering off or rebooting. However, systemctl also offers shortcuts that provide extra functionality.

For example, to enter rescue (single-user) mode, use the rescue command instead of isolate rescue.target:

sudo systemctl rescue

This adds the benefit of notifying all logged-in users about the event.

To halt the system, use the halt command:

sudo systemctl halt

For a complete shutdown, employ the poweroff command:

sudo systemctl poweroff

To restart, use the reboot command:

sudo systemctl reboot

These commands inform logged-in users of the event, which running or isolating the target alone won't do. Note that most machines link the shorter, more conventional commands for these operations to work correctly with systemd.

For instance, to reboot the system, you can typically type:

sudo reboot

Wrapping Up

By now, you should be acquainted with the fundamental features and capabilities of the systemctl command, allowing you to interact with and manage a systemd instance. The systemctl utility serves as the primary interaction point for service and system state management.

While systemctl primarily works with the main systemd process, other components in the systemd ecosystem are controlled by different utilities. Other functionalities, like log management and user sessions, are managed by separate daemons and management utilities (journald/journalctl and logind/loginctl, respectively). Taking the time to familiarize yourself with these other tools and daemons will make management tasks easier.

30 April 202404/30/2024
Product digest quarter 1
5 April 202404/05/2024
read 1 minuteread 1 min
Introducing Our New Location in Kazakhstan
28 March 202403/28/2024
read 1 minuteread 1 min
3HCloud Brings GPU Servers to Miami