Skip to content

Understand Systemd - demo and explanation

homepage-banner

Introduction

Systemd is a system and session manager for Linux. It is used to manage the boot process, system services, and user sessions. Systemd is now the default system and session manager for many Linux distributions. In this blog post, we will discuss how to use systemd in Linux.

What is systemd?

Systemd is a system and service manager that was designed to replace the traditional init system used in Linux distributions. It was created to provide a faster and more efficient way to manage services and processes on a Linux system. Systemd is responsible for starting and stopping system services, tracking processes, and managing system resources.

Types of unit files

  • service: These are the configuration files for services. They replace the old-fashioned init scripts that we had on the old System V (SysV) systems.
  • socket: Sockets can either enable communication between different system services or they can automatically wake up a sleeping service when it receives a connection request.
  • slice: Slice units are used when configuring cgroups.
  • mount and automount: These contain mount point information for filesystems that are controlled by systemd. Normally, they get created automatically, so you shouldn’t have to do too much with them.
  • target: Target units are used during system startup, for grouping units and for providing well-known synchronization points.
  • timer: Timer units are for scheduling jobs that run on a schedule. They replace the old cron system.
  • path: Path units are for services that can be started via path-based activation.
  • swap: Swap units contain information about your swap partitions.

Useful commands

man systemd-system.conf

ls /lib/systemd
ls /lib/systemd/system

systemctl list-units
## see units that are not active
systemctl list-units --all
## view specific types of units
systemctl list-units -t service
systemctl list-unit-files
systemctl list-unit-files -t swap

systemctl list-sockets
systemctl list-timers
systemctl list-jobs
systemctl list-dependencies
systemctl list-dependencies --reverse

## see the actual running configuration
systemctl show

## To see if just one individual unit is either enabled or active
systemctl is-enabled systemd-timesyncd
systemctl is-active systemd-timesyncd

sudo systemctl start httpd
sudo systemctl status httpd
sudo systemctl stop httpd
sudo systemctl enable httpd
sudo systemctl disable httpd
sudo systemctl kill httpd
sudo systemctl kill -s SIGKILL httpd
## If  you have a service that you never want to start, either manually or automatically.
## You can accomplish this by masking the service.
sudo systemctl mask httpd
sudo systemctl unmask httpd

## checking the overall security profile for the services
systemd-analyze security
systemd-analyze security chrony.service

Understanding service units

man systemd.directives
man systemd.unit

Example 1

[Unit]
Description=The Apache HTTP Server
After=network.target remote-fs.target nss-lookup.target
Documentation=https://httpd.apache.org/docs/2.4/
  • Description=: Okay, this one should be fairly self-explanatory. All it does is tell the human user what the service is. The systemctl status command pulls its description information from this line.
  • After=: This is a list of other units that this unit should start after. This is useful for services that need to wait for a network connection to be established or for a filesystem to be mounted before they can start.
  • Documentation=: This is a list of URLs that contain documentation for the service. The systemctl help command pulls its documentation information from this line.
[Service]
Type=forking
Environment=APACHE_STARTED_BY_SYSTEMD=true
ExecStart=/usr/sbin/apachectl start
ExecStop=/usr/sbin/apachectl stop
ExecReload=/usr/sbin/apachectl graceful
PrivateTmp=true
Restart=on-abort
  • Type=: There are several different service types that you’ll see described in the systemd.service man page. In this case, we have the forking type, which means that the first Apache process that starts will spawn a child process. When Apache startup is complete and the proper communication channels have been set up, the original process—the parent process—will exit and the child process will carry on as the main service process. When the parent process exits, the systemd service manager will finally recognize the service as having fully started. According to the man page, this is the traditional behavior for Unix services, and systemd just carries on the tradition.
  • Environment=: This sets an environmental variable that affects the behavior of the service. In this case, it tells Apache that it was started by systemd.
  • ExecStart=, ExecStop=, and ExecReload=: These three lines just point the way to the Apache executable file, and specify the command arguments for starting, stopping, and reloading the service.
  • PrivateTmp=: Many services write temporary files for various reasons, and you’re probably used to seeing them in the /tmp/ directory that everyone can access. Here though, we see a cool systemd security feature. When set to true, this parameter forces the Apache service to write its temporary files to a private /tmp/ directory that nobody else can access.
  • Restart=: Sometimes, you might want a service to automatically restart if it stops. In this case, we’re using the on-abort parameter, which just means that if the Apache service were to crash with an unclean signal, systemd would automatically restart it.

Example 2

[Service]
EnvironmentFile=-/etc/default/ssh
ExecStartPre=/usr/sbin/sshd -t
ExecStart=/usr/sbin/sshd -D $SSHD_OPTS
ExecReload=/usr/sbin/sshd -t
ExecReload=/bin/kill -HUP $MAINPID
KillMode=process
Restart=on-failure
RestartPreventExitStatus=255
Type=notify
RuntimeDirectory=sshd
RuntimeDirectoryMode=0755

[Install]
WantedBy=multi-user.target
Alias=sshd.service
  • EnvironmentFile=: This parameter causes systemd to read a list of environmental variables from the specified file. The minus sign (-) in front of the path to the file tells systemd that if the file doesn’t exist, don’t worry about it and start the service anyway.
  • ExecStartPre=: This tells systemd to run a specified command before it starts the service with the ExecStart= parameter. In this case, we want to run the sshd -t command, which tests the Secure Shell configuration to ensure that it’s valid.
  • KillMode=: That’s the default behavior if you don’t include this parameter in your service file. Sometimes though, you might not want that. By setting this parameter to process, a kill signal will only kill the main process for the service. All other associated processes will remain running.
  • Restart=: This time, instead of automatically restarting a stopped service on-abort, it will now restart it on-failure. So, in addition to restarting the service because of an unclean signal, systemd will also restart this service because of an unclean exit code, a timeout, or a watchdog event.
  • RestartPreventExitStatus=: This prevents the service from automatically restarting if a certain exit code is received. In this case, we don’t want the service to restart if the exit code is 255.
  • Type=: For this service, the type is notify, instead of forking as we saw in the previous example. This means that the service will send a notification message when the service has finished starting. After it sends the notification message, systemd will continue loading the follow-up units.
  • RuntimeDirectory= and RuntimeDirectoryMode=: These two directives create a runtime directory under the /run/ directory, and then set the permissions value for that directory. In this case, we’re setting the 0755 permission on the directory, which means that it will have read, write, and execute permissions for the directory’s owner. Everyone else will only have read and execute permissions.

Understanding socket units

ls -l /lib/systemd/system/*.socket

Example 3

[Unit]
Description=OpenBSD Secure Shell server socket
Before=ssh.service
Conflicts=ssh.service
ConditionPathExists=!/etc/ssh/sshd_not_to_be_run

[Socket]
ListenStream=22
Accept=yes

[Install]
WantedBy=sockets.target
  • Before=ssh.service: This tells systemd to start the socket before starting the Secure Shell service.
  • Conflicts=ssh.service: This tells systemd to not allow the Secure Shell service to run normally if this socket is enabled. If you were to enable this socket, the normal SSH service would get shut down.
sudo systemctl is-active ssh
## active

sudo systemctl enable --now ssh.socket

sudo systemctl is-active ssh
## inactive
  • the Conflicts= line automatically shuts down the ssh service.

Understanding path units

You can use a path unit to have systemd monitor a certain file or directory to see when it changes. When systemd detects that the file or directory has changed, it will activate the specified service.

[Unit]
Description=CUPS Scheduler
PartOf=cups.service

[Path]
PathExists=/var/cache/cups/org.cups.cupsd

[Install]
WantedBy=multi-user.target
  • The PathExists= line tells systemd to monitor a specific file for changes, which in this case is the /var/cache/cups/org.cups.cupsd file. If systemd detects any changes to this file, it will activate the printing service.

Creating and Editing Services

## Creating a partial edit
sudo systemctl edit apache2
systemctl cat apache2
sudo systemctl daemon-reload

## Creating a full edit
sudo systemctl edit --full ssh.service

## Creating a new service
sudo systemctl edit --force --full XXXX.service

## Changing the default editor
sudo EDITOR=vim systemctl edit --full sshd

Understanding systemd Targets

The legacy SysVinit system has runlevels. In systemd, we have targets instead of runlevels. Several of these targets perform the same function that runlevels used to.

systemctl list-units -t target
cat sockets.target
[Unit]
Description=Sockets
Documentation=man:systemd.special(7)
ls /etc/systemd/system/sockets.target.wants
systemctl list-dependencies graphical.target
systemctl list-dependencies --after network.target

systemctl get-default
sudo systemctl set-default multi-user

## Temporarily changing the target
sudo systemctl isolate multi-user
SysV runlevel systemd target What it does
runlevel 0 poweroff.target It shuts down the operating system.
runlevel 1 rescue.target It prevents all services from running and prevents all users except for the root user from logging in to the system. All filesystems are mounted normally. It’s just a root shell for performing maintenance operations.
runlevel 2 - 4 multi-user.target The operating system is fully operational, without a graphical interface.
runlevel 5 graphical.target The operating system is fully operational, with a graphical interface.
runlevel 6 reboot.target This is for rebooting the system.

Understanding systemd Timers

systemctl list-unit-files -t timer
systemctl list-timers

Conclusion

Systemd has become a standard feature of many popular Linux distributions, and it has both benefits and drawbacks. While it has been criticized for being too complex and tightly integrated with the Linux kernel, it provides faster boot times, better control over system resources, and many other features that make it a valuable tool for Linux administrators. As Linux continues to evolve, it will be interesting to see how systemd develops and whether it remains the default init system for Linux distributions.

Reference

  • Linux Service Management Made Easy with systemd - Advanced techniques to effectively manage, control, and monitor Linux systems and services (Donald A. Tevault)
Leave a message