Understand Systemd - demo and explanation
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.
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.
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
[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.
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.
[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.
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
[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
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
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
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.
- Linux Service Management Made Easy with systemd - Advanced techniques to effectively manage, control, and monitor Linux systems and services (Donald A. Tevault)