1. Introduction

A service is a unit in the SystemD utility that represents any resource that our operating system can recognize and manage. It could be software components, devices, etc.

Due to the widespread adoption of SystemD as an init system and system manager in Linux distributions, we see more of its usage in service management. Although this makes running services smoother, it raises many questions regarding system security and access control.

In this article, we’ll explore the systemctl command tool we use to control this init system. We’ll look at how we use this tool to manage a running service as well as determine its user.

2. Understanding systemctl

As previously mentioned, systemctl is a command-line tool that allows us to manage and interact with SystemD. It aims to replace the older System V init (SysVInit) system.

It consists of a range of system management utilities and libraries that help us control the service manager.

Let’s look at the basic syntax for using systemctl:

$ systemctl [OPTIONS...] COMMAND [UNIT...]

If we run this command without any argument, it displays all the loaded units on our system:

$ systemctl
UNIT                                                                                     LOAD   ACTIVE     SUB       DESCRIPTION
proc-sys-fs-binfmt_misc.automount                                                        loaded active     running   Arbitrary Executable File...
dev-fuse.device                                                                          loaded activating tentative /dev/fuse
sys-devices-pci0000:00-0000:00:01.1-ata2-host1-target1:0:0-1:0:0:0-block-sr0.device      loaded active     plugged   VBOX_CD-ROM VBox_GAs_7.0.8
sys-devices-pci0000:00-0000:00:03.0-net-enp0s3.device                                    loaded active     plugged   82540EM Gigabit Ethernet...
sys-devices-pci0000:00-0000:00:05.0-sound-card0.device                                   loaded active     plugged   82801AA AC97 Audio...
sys-devices-pci0000:00-0000:00:0d.0-ata3-host2-target2:0:0-2:0:0:0-block-sda-sda1.device loaded active     plugged   VBOX_HARDDISK 1
sys-devices-pci0000:00-0000:00:0d.0-ata3-host2-target2:0:0-2:0:0:0-block-sda-sda2.device loaded active     plugged   VBOX_HARDDISK 2
sys-devices-pci0000:00-0000:00:0d.0-ata3-host2-target2:0:0-2:0:0:0-block-sda-sda5.device loaded active     plugged   VBOX_HARDDISK 5
sys-devices-pci0000:00-0000:00:0d.0-ata3-host2-target2:0:0-2:0:0:0-block-sda.device      loaded active     plugged   VBOX_HARDDISK
sys-devices-platform-serial8250-tty-ttyS0.device                                         loaded active     plugged   /sys/devices/platform/...
sys-devices-platform-serial8250-tty-ttyS1.device                                         loaded active     plugged   /sys/devices/platform/...

Let’s break down what this means:

  • UNIT: the name of the units SystemD currently has in memory
  • LOAD: indicates if the unit’s configuration is properly loaded
  • ACTIVE: displays the status of the unit, if active or not
  • SUB: provides more detailed information about the unit based on the unit type or state
  • DESCRIPTION: displays a short description of what a unit is or does

For the purpose of this article, we’ll be using the mysql service to illustrate the commands.

2.1. Common systemctl Commands

The most common commands that help us manage running services on our system are the start, stop, restart, and reload commands. Additionally, we can use this tool to check the status of a service to see if it’s loaded and running on our system.

To check the status of our MySQL service, we use the systemctl status command:

$ systemctl status mysql
● mysql.service - MySQL Community Server
     Loaded: loaded (/lib/systemd/system/mysql.service; enabled; vendor preset: enabled)
     Active: active (running) since Wed 2024-02-07 19:26:16 WAT; 2 weeks 3 days ago
    Process: 846 ExecStartPre=/usr/share/mysql/mysql-systemd-start pre (code=exited, status=0/SUCCESS)
   Main PID: 1012 (mysqld)
     Status: "Server is operational"
      Tasks: 39 (limit: 4614)
     Memory: 443.0M
     CGroup: /system.slice/mysql.service
             └─1012 /usr/sbin/mysqld

Feb 07 19:25:08 user systemd[1]: Starting MySQL Community Server...
Feb 07 19:26:16 user systemd[1]: Started MySQL Community Server.

This gives us valuable insight into the state of the service and other information. We can break down the output into:

  • Loaded: shows if the unit is loaded into memory
  • Active: shows the active state of the unit
  • PID: process ID
  • CGroup: the cgroup of the service

This output shows that our mysql service has been loaded and is running on our system. We can now go ahead and extract further information about this service.

3. systemctl show

Although the systemctl status command displays the state of a service as well as other information in a human-readable format, it encapsulates some necessary information. For a more detailed, computer-parsable output, we use systemctl show.

systemctl show displays the properties of a specified unit or service. It retrieves and displays detailed information about a service, including the user, group, etc.

Let’s look at the common syntax for this command:

$ systemctl show [PATTERN...|JOB...]

By default, executing this command without arguments will display the properties of the service manager.

3.1. Practical Examples

Let’s still use the mysql service for illustration. Assuming we want to find out more about this service, we use:

$ systemctl show mysql

This displays key-value pair property information for the mysql service that is running on our system. We can see that the User, Group, and UID information are also present in this output.

Generally, properties that are empty are ignored in this output. To display service information with those included, we use the –all flag.

3.2. Additional Options and Flags

Evidently, we see that the output of this command is quite extensive, as this gives us all the properties of a running service. But we’re only interested in a few properties.

Alternatively, we can achieve this by using the –property or -p flag to fetch and display only the properties we want. In this case, we want to see details of the user behind a running service:

$ systemctl show --property=User,DynamicUser,MainPID,Group mysql

Using this flag, we’re able to extract the properties we need about the running service. As shown in our example, we use a comma to separate the multiple properties we want to extract.

As a result, we can now identify the User, Group, and MainPID for the mysql service.

4. Usage

Knowing how to determine the user of a running service is crucial in areas of access control, troubleshooting issues, and security considerations on a system or server.

Previously, our illustrations were on the mysql service, which has the capacity to run system-wide. But let’s look at some services that are user-dependent. For this new example, we’d use the syncthing service.

Syncthing is an open-source, peer-to-peer synchronization application used to sync files between devices over a network. Let’s install it on our device:

$ sudo apt-get install syncthing
Reading package lists... Done
Building dependency tree       
Reading state information... Done
Preparing to unpack .../syncthing_1.1.4~ds1-4ubuntu1.2_amd64.deb ...
Unpacking syncthing (1.1.4~ds1-4ubuntu1.2) ...
Setting up syncthing (1.1.4~ds1-4ubuntu1.2) ...
Created symlink /etc/systemd/system/sleep.target.wants/syncthing-resume.service → /lib/systemd/system/syncthing-resume.service.
Processing triggers for mime-support (3.64ubuntu1) ...
Rules updated for profile 'Apache'
Firewall reloaded

Next, let’s check the status of our service without specifying the user:

$ sudo systemctl status syncthing
Unit syncthing.service could not be found.

We see that this service isn’t equipped to run system-wide on our system or server.

Next, let’s enable it to run peculiarly for a certain user:

$ sudo systemctl enable --now syncthing@baeldung
Created symlink /etc/systemd/system/multi-user.target.wants/[email protected] → /lib/systemd/system/[email protected].

Consequently, this creates a symbolic link that enables our service to start whenever we boot our system.

Let’s check the status of the running service now with the user specified:

$ sudo systemctl status syncthing@baeldung
● [email protected] - Syncthing - Open Source Continuous File Synchronization for baledung
     Loaded: loaded (/lib/systemd/system/[email protected]; enabled; vendor preset: enabled)
     Active: active (running) since Mon 2024-02-26 10:53:36 WAT; 7s ago
       Docs: man:syncthing(1)
   Main PID: 9442 (syncthing)
      Tasks: 11 (limit: 4614)
     Memory: 22.1M
     CGroup: /system.slice/system-syncthing.slice/[email protected]
             └─9442 /usr/bin/syncthing -no-browser -no-restart -logflags=0
Feb 26 10:53:38 baeldung syncthing[9442]: [INFPV] INFO: TCP listener ([::]:22000) starting

We can see now that the service runs as specified by the user baeldung. We can also try checking the status of the service by specifying another user, in this case, root:

$ systemctl status syncthing@root
● [email protected] - Syncthing - Open Source Continuous File Synchronization for root
     Loaded: loaded (/lib/systemd/system/[email protected]; disabled; vendor preset: enabled)
     Active: inactive (dead)
       Docs: man:syncthing(1)

Here, we can see that all the previous configurations we did for the syncthing service running as baeldung don’t reflect for root.

This is important as we can now start, stop, reload, and perform other actions on running services peculiar to one user without affecting the activities of another user on the same service on our server or system.

5. Conclusion

In this article, we discussed how we use systemctl to manage running services on our system or server. We looked at the different commands, such as start, stop, reload, and status. Furthermore, we explored ways we can determine the user of a running service using systemctl show. Lastly, we saw practical examples of how this knowledge is necessary for effective system administration.

Inline Feedbacks
View all comments
Comments are open for 30 days after publishing a post. For any issues past this date, use the Contact form on the site.