Skip to content

systemd

(Written by Paul Cobbaut, https://github.com/paulcobbaut/, with contributions by: Alex M. Schapelle, https://github.com/zero-pytagoras/)

Many Unix and Linux distributions have been using init scripts to start daemons in the same way that Unix System V did back in 1983.

Starting 2015 this is considered legacy. Most Linux distributions, including Debian and Red Hat/CentOS, are in the process of migrating to systemd. They will however, remain somewhat compatible with init mainly, due to migration process might take a while. It is also need to be mentioned that majority of OpenSource software and applications, have already migrated to systemd, especially in case of RedHat and its derivitieves.

This chapter explains how to manage Linux with systemd.

systemd

systemd is a software suite that provides an array of system components for Linux operating systems. Its main aim is to unify service configuration and behavior across Linux distributions; systemd\'s primary component is a \"system and service manager\"---an init system used to bootstrap user space and manage user processes. It also provides replacements for various daemons and utilities, including device management, login management, network connection management, and event logging. The name systemd adheres to the Unix convention of naming daemons by appending the letter d. It also plays on the term \"System D\", which refers to a person\'s ability to adapt quickly and improvise to solve problems.

systemd has replaced all the standard init/runlevel/rc functionality. Both Red Hat and Debian and their deritives have decided in 2014 that systemd will be replacing init in current and future releases (RHEL7+/CentOS7+ and Debian 8+).

The screenshot below shows systemd running as pid 1 on RHEL8.

[root@linux ~]# ps fax | grep systemd | cut -c1-76
    1 ?        Ss     0:01 /usr/lib/systemd/systemd --switched-root --system
  505 ?        Ss     0:00 /usr/lib/systemd/systemd-journald
  545 ?        Ss     0:00 /usr/lib/systemd/systemd-udevd
  670 ?        Ss     0:00 /usr/lib/systemd/systemd-logind
  677 ?        Ssl    0:00 /bin/dbus-daemon --system --address=systemd: --no
 2662 pts/1    S+     0:00          \_ grep --color=auto systemd
[root@linux ~]#

Debian 10 uses parts of systemd, but still has init as pid 1.

root@linux:~# ps fax | grep systemd | cut -c1-76
  350 ?        Ss     0:00 /lib/systemd/systemd-udevd --daemon
 2206 ?        S      0:11 /sbin/cgmanager --daemon -m name=systemd
 2932 ?        S      0:04 /lib/systemd/systemd-logind
16353 pts/4    S+     0:00              \_ grep systemd
root@linux:~#

systemd targets

The first command to learn is systemctl list-units --type=target (or the shorter version systemctl -t target). It will show you the different targets on the system.

[root@linux1 ~]# systemctl -t target
UNIT                LOAD   ACTIVE SUB    DESCRIPTION
basic.target        loaded active active Basic System
cryptsetup.target   loaded active active Encrypted Volumes
getty.target        loaded active active Login Prompts
local-fs-pre.target loaded active active Local File Systems (Pre)
local-fs.target     loaded active active Local File Systems
multi-user.target   loaded active active Multi-User System
network.target      loaded active active Network
paths.target        loaded active active Paths
remote-fs.target    loaded active active Remote File Systems
slices.target       loaded active active Slices
sockets.target      loaded active active Sockets
swap.target         loaded active active Swap
sysinit.target      loaded active active System Initialization
timers.target       loaded active active Timers

LOAD   = Reflects whether the unit definition was properly loaded.
ACTIVE = The high-level unit activation state, i.e. generalization of SUB.
SUB    = The low-level unit activation state, values depend on unit type.

14 loaded units listed. Pass --all to see loaded but inactive units, too.
To show all installed unit files use 'systemctl list-unit-files'.
[root@linux1 ~]#

Targets are the replacement of runlevels and define specific points to reach when booting the system. For example the graphical.target is reached when you get a graphical interface, and the nfs.target requires a running nfs server.

To switch to a target (for example multi-user.target), we now use systemctl isolate (instead of the equivalent init 3 to change the runlevel).

This screenshot shows a Red Hat Enterprise Linux 8 server switching from a graphical interface to command line (decreasing the number of running processes).

[root@linux ~]# ps fax | wc -l
169
[root@linux ~]# systemctl isolate multi-user.target
[root@linux ~]# ps fax | wc -l
129
[root@linux ~]#

To change the default target, we again use this systemctl command (instead of editing the /etc/inittab file).

[root@linux ~]# systemctl set-de
rm '/etc/systemd/system/default.target'
ln -s '/usr/lib/systemd/system/multi-user.target' '/etc/systemd/system/default\
.target'
[root@linux ~]#

This command removed the file /etc/systemd/system/default.target and replaced it with a symbolic link to the multi-user-.target target.

systemd dependencies

Dependencies are no longer defined by alfabetical order of running scripts, but by configuration in /etc/systemd/system/. For example here are the required services for the multi-user.target on Red Hat Enterprise 7.1.

[root@linux1 ~]# cat /etc/redhat-release
Red Hat Enterprise Linux Server release 7.1 (Maipo)
[root@linux1 ~]# ls /etc/systemd/system/multi-user.target.wants/
abrt-ccpp.service    auditd.service          postfix.service    sysstat.service
abrtd.service        chronyd.service         remote-fs.target   tuned.service
abrt-oops.service    crond.service           rhsmcertd.service
abrt-vmcore.service  irqbalance.service      rsyslog.service
abrt-xorg.service    NetworkManager.service  sshd.service
[root@linux1 ~]#

Below a screenshot from Debian (bullseye/sid is Debian 11). There is already a lot of systemd in Debian 8 and 9 (less than in RHEL7).

root@debian11:~# cat /etc/debian_version
stretch/sid
root@debian11:~# ls /etc/systemd/system/multi-user.target.wants/
anacron.service       binfmt-support.service  lm-sensors.service  rsyslog.service
atd.service           cron.service            pppd-dns.service    ssh.service
avahi-daemon.service  fancontrol.service      remote-fs.target
root@debian11:~#

Typical rc scripts are replaced with services. Issue the systemctl list-units -t service --all (or systemctl -at service) to get a list of all services on your system.

[root@linux ~]# systemctl -at service | head -5 | column -t | cut -c1-78
UNIT                 LOAD    ACTIVE    SUB      DESCRIPTION
abrt-ccpp.service    loaded  active    exited   Install      ABRT     coredump
abrt-oops.service    loaded  active    running  ABRT         kernel   log
abrt-vmcore.service  loaded  inactive  dead     Harvest      vmcores  for
abrt-xorg.service    loaded  active    running  ABRT         Xorg     log
[root@linux ~]#

service status

Below is a (truncated) screenshot showing how to see the status of the sshd service. (This RHEL server was attacked using brute force ssh on 2 August 2015.)

[root@linux1 ~]# systemctl status sshd.service

sshd.service - OpenSSH server daemon
 Loaded: loaded (/usr/lib/systemd/system/sshd.service; enabled)
 Active: active (running) since Wed 2015-07-29 12:00:10 CEST; 1 weeks 0 days ago
Main PID: 1123 (sshd)
  CGroup: /system.slice/sshd.service
          └─1123 /usr/sbin/sshd -D

Aug 02 16:45:24 rhel81 sshd[12704]: Failed password for root from 43.229.53.79 
Aug 02 18:15:28 rhel81 sshd[12872]: pam_unix(sshd:auth): authentication failur
Aug 02 18:15:28 rhel81 sshd[12872]: pam_succeed_if(sshd:auth): requirement "ui
Aug 02 18:15:30 rhel81 sshd[12872]: Failed password for root from 43.229.53.79
Aug 02 18:15:30 rhel81 sshd[12872]: pam_succeed_if(sshd:auth): requirement "ui
Aug 02 18:15:32 rhel81 sshd[12872]: Failed password for root from 43.229.53.79
Aug 02 18:15:32 rhel81 sshd[12872]: pam_succeed_if(sshd:auth): requirement "ui
Aug 02 18:15:34 rhel81 sshd[12872]: Failed password for root from 43.229.53.79
Aug 02 18:15:34 rhel81 sshd[12872]: Received disconnect from 43.229.53.79: 11:
Aug 03 10:21:11 rhel81 sshd[14616]: pam_unix(sshd:auth): authentication failur
Aug 03 10:21:11 rhel81 sshd[14616]: pam_succeed_if(sshd:auth): requirement "ui
Aug 03 10:21:13 rhel81 sshd[14616]: Failed password for root from 119.188.7.14
Aug 03 10:21:13 rhel81 sshd[14616]: Received disconnect from 119.188.7.143: 11
Aug 03 14:20:03 rhel81 sshd[15083]: Accepted password for root from 192.168.1.
Hint: Some lines were ellipsized, use -l to show in full.
[root@linux1 ~]#

This systemd feature does not work by default on Debian 8/9 because init has pid 1. It only works when the system is booted with systemd as pid 1.

root@linux:~# systemctl status sshd
Failed to get D-Bus connection: Operation not permitted
root@linux:~# systemctl status ssh
Failed to get D-Bus connection: Operation not permitted
root@linux:~# service ssh status
sshd is running.
root@linux:~#

systemd services configuration

The chkconfig and service commands are considered \'legacy\'. They are replaced with systemctl.

This screenshot shows the new way to start and stop a service.

[root@linux ~]# systemctl start crond.service
[root@linux ~]# systemctl show crond.service | grep State
LoadState=loaded
ActiveState=active
SubState=running
UnitFileState=enabled
[root@linux ~]# systemctl stop crond.service
[root@linux ~]# systemctl show crond.service | grep State
LoadState=loaded
ActiveState=inactive
SubState=dead
UnitFileState=enabled
[root@linux ~]#

And here is the new way to stop and disable a service.

[root@linux ~]# systemctl stop crond.service
[root@linux ~]# systemctl disable crond.service
rm '/etc/systemd/system/multi-user.target.wants/crond.service'
[root@linux ~]# systemctl show crond.service | grep State
LoadState=loaded
ActiveState=inactive
SubState=dead
UnitFileState=disabled
[root@linux ~]#

This screenshot shows how to enable and start the service again.

[root@linux ~]# systemctl enable crond.service
ln -s '/usr/lib/systemd/system/crond.service' '/etc/systemd/system/multi-user.\
target.wants/crond.service'
[root@linux ~]# systemctl start crond.service
[root@linux ~]# systemctl show crond.service | grep State
LoadState=loaded
ActiveState=active
SubState=running
UnitFileState=enabled
[root@linux ~]#

systemd signalling

You can also use systemd to kill problematic services.

[root@linux ~]# systemctl show crond.service | grep State
LoadState=loaded
ActiveState=active
SubState=running
UnitFileState=enabled
[root@linux ~]# systemctl kill -s SIGKILL crond.service
[root@linux ~]# systemctl show crond.service | grep State
LoadState=loaded
ActiveState=failed
SubState=failed
UnitFileState=enabled
[root@linux ~]#

systemd shutdown

The poweroff, halt and reboot commands are considered legacy now and are handeld by systemctl. The table below shows the legacy commands on the left and their new systemd equivalent on the right.


legacy command systemd command


poweroff systemctl poweroff

reboot systemctl reboot

halt systemctl halt

pm-suspend systemctl suspend

pm-hibernate systemctl hibernate


: systemd power management

remote systemd

The systemctl utility has a buil-in remote control providing there is an ssh daemon running on the remote system.

This screenshot shows how to use systemctl to verify a service on an other RHEL server.

[root@linux ~]# systemctl -H root@192.168.1.65 status sshd
root@192.168.1.65's password:
sshd.service - OpenSSH server daemon
   Loaded: loaded (/usr/lib/systemd/system/sshd.service; enabled)
   Active: active (running) since Thu 2014-09-11 13:04:10 CEST; 16min ago
  Process: 1328 ExecStartPre=/usr/sbin/sshd-keygen (code=exited, status=0/SUCCE\
SS)
 Main PID: 1363 (sshd)
   CGroup: /system.slice/sshd.service
[root@linux ~]#

there is more systemd

There are other tools...

systemd-analyze                 systemd-loginctl
systemd-ask-password            systemd-machine-id-setup
systemd-cat                     systemd-notify
systemd-cgls                    systemd-nspawn
systemd-cgtop                   systemd-run
systemd-coredumpctl             systemd-stdio-bridge
systemd-delta                   systemd-sysv-convert
systemd-detect-virt             systemd-tmpfiles
systemd-inhibit                 systemd-tty-ask-password-agent

For example systemd-analyze blame will give you an overview of the time it took for each service to boot.

[root@linux ~]# systemd-analyze blame | head
          1.977s firewalld.service
          1.096s tuned.service
           993ms postfix.service
           939ms iprinit.service
           925ms vboxadd-x11.service
           880ms firstboot-graphical.service
           839ms accounts-daemon.service
           829ms network.service
           822ms iprupdate.service
           795ms boot.mount
[root@linux ~]#

practice: systemd

1.determine on which target you are at the moment

2.list all systemctl units with type of service

3.check what is the status of cron service.

4.disable cron service

5.1 on RedHat based system, disable networkmanager and enable networking service.

5.2 on Debian based system, disable networkmanager and enable netconf serice

6.use one command, to eneable and start cron service

solution : systemd

1.determine on which target you are at the moment

systemctl get-default runlevel command should also work, but command above provides

2.list all systemctl units with type of service

systemctl -t service

3.check what is the status of cron service.

systemctl status cron.service

4.disable cron service

``

5.1 on RedHat based system, disable networkmanager and enable networking service.

systemctl disable NetworkManager systemctl enable networking

5.2 on Debian based system, disable networkmanager and enable netconf serice

systemctl disable NetworkManager systemctl enable netconf

6.use one command, to eneable and start cron service

systemctl enable --now cron