adds targets and dependencies to systemd

This commit is contained in:
waldek 2021-08-16 23:55:42 +02:00
parent a27d77bdcd
commit a1b6a13379
1 changed files with 486 additions and 0 deletions

View File

@ -565,3 +565,489 @@ Some things that are easy to do with cron are difficult to do with timer units a
* Emails: there is no built-in equivalent to cron's MAILTO for sending emails on job failure. See the next section for an example of setting up a similar functionality using OnFailure=.
Also note that user timer units will only run during an active user login session by default. However, lingering can enable services to run at boot even when the user has no active login session.
## A sidetrack into runlevels
The world of Linux has a concept called *runlevels* which determines a target state the machine is in, or to which you want the manche to go to.
It's a complicated way of saying fully operational with graphical interface, a root only rescue mode, a reboot, halted etc.
The official specification of the runlevels defines them as such.
* Runlevel 0 or Halt is used to shift the computer from one state to another. It shut down the system.
* Runlevel 1, s, S or Single-User Mode is used for administrative and recovery functions. It has only enough daemons to allow one user (the root user) to log in and perform system maintenance tasks. All local file systems are mounted. Some essential services are started, but networking remains disabled.
* Runlevel 2 or Multi-user Mode is used for most daemons running and allows multiple users the ability to log in and use system services but without networking. On Debian and its derivatives, a full multi-user mode with X running and a graphical login. Most other distributions leave this runlevel undefined.
* Runlevel 3 or Extended Multi-user Mode is used for a full multi-user mode with a console (without GUI) login screen with network services available
* Runlevel 4 is not normally used and undefined so it can be used for a personal customization
* Runlevel 5 or Graphical Mode is same as Runlevel 3 with graphical login _(such as GDN)_.
* Runlevel 6 or Reboot is a transitional runlevel to reboot the system.
You can inspect the runlevel your system is currenty at by ececuting the following command.
```
➜ ~ git:(master) ✗ sudo runlevel
N 5
➜ ~ git:(master) ✗
```
You can change your runlevel with the `sudo telinit`, followed by the level number, command.
You'll probably won't see that much difference between levels but try to change it to level `6` and see what happens.
If you change the runlevel to `1` your machine will probably freeze.
This has to do with the fact we haven't set a `root` password on most of our machines so the single user mode can't be accessed.
Try setting a root password and reset the level to one and see what happens.
## Systemd targets
Systemd take the concept of runlevels a bit further and they are renamed to **targets**.
The mapping of runlevels to targets is as follows.
* poweroff.target (runlevel 0): shutdown and power off the system
* rescue.target (runlevel 1): launch the rescue shell session
* multi-user.target (runlevel 2,3,4): set the system in non graphical (console) multi-user system
* graphical.target (runlevel 5): use a graphical multi-user system with network services
* reboot.target (runlevel 6): shutdown and reboot the system
But, there are a *lot* more targets available on a machine running systemd.
Luckily `systemctl` offers a nice way to inspect them.
```
➜ ~ git:(master) ✗ sudo systemctl list-units --type target
UNIT LOAD ACTIVE SUB DESCRIPTION
basic.target loaded active active Basic System
cryptsetup.target loaded active active Local 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
nfs-client.target loaded active active NFS client services
paths.target loaded active active Paths
remote-fs-pre.target loaded active active Remote File Systems (Pre)
remote-fs.target loaded active active Remote File Systems
rpcbind.target loaded active active RPC Port Mapper
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
time-set.target loaded active active System Time Set
time-sync.target loaded active active System Time Synchronized
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.
19 loaded units listed. Pass --all to see loaded but inactive units, too.
To show all installed unit files use 'systemctl list-unit-files'.
```
Notice how some of the mappings, such as rescue.target, are missing?
We can show the inactive ones as well if we add the `--all` argument.
```
➜ ~ git:(master) ✗ sudo systemctl list-units --type target --all --no-pager
UNIT LOAD ACTIVE SUB DESCRIPTION
basic.target loaded active active Basic System
blockdev@dev-disk-by\x2duuid-4a77d180\x2dfc64\x2d4057… loaded inactive dead Block Device Preparation for /dev/disk/by-uuid/4a77d18…
blockdev@dev-dm\x2d1.target loaded inactive dead Block Device Preparation for /dev/dm-1
blockdev@dev-mapper-deathstar\x2d\x2dvg\x2droot.target loaded inactive dead Block Device Preparation for /dev/mapper/deathstar--vg…
blockdev@dev-mapper-deathstar\x2d\x2dvg\x2dswap_1.tar… loaded inactive dead Block Device Preparation for /dev/mapper/deathstar--vg…
blockdev@dev-sda1.target loaded inactive dead Block Device Preparation for /dev/sda1
bluetooth.target loaded inactive dead Bluetooth
cryptsetup.target loaded active active Local Encrypted Volumes
emergency.target loaded inactive dead Emergency Mode
first-boot-complete.target loaded inactive dead First Boot Complete
getty-pre.target loaded inactive dead Login Prompts (Pre)
getty.target loaded active active Login Prompts
graphical.target loaded inactive dead Graphical Interface
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-online.target loaded inactive dead Network is Online
network-pre.target loaded inactive dead Network (Pre)
network.target loaded active active Network
nfs-client.target loaded active active NFS client services
nss-user-lookup.target loaded inactive dead User and Group Name Lookups
paths.target loaded active active Paths
remote-fs-pre.target loaded active active Remote File Systems (Pre)
remote-fs.target loaded active active Remote File Systems
rescue.target loaded inactive dead Rescue Mode
rpcbind.target loaded active active RPC Port Mapper
shutdown.target loaded inactive dead Shutdown
slices.target loaded active active Slices
sockets.target loaded active active Sockets
sound.target loaded inactive dead Sound Card
swap.target loaded active active Swap
sysinit.target loaded active active System Initialization
time-set.target loaded active active System Time Set
time-sync.target loaded active active System Time Synchronized
timers.target loaded active active Timers
umount.target loaded inactive dead Unmount All Filesystems
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.
36 loaded units listed.
To show all installed unit files use 'systemctl list-unit-files'.
➜ ~ git:(master) ✗
```
That's better but still, some other ones such as poweroff.target seem to be missing.
Those are both not active and not loaded, but still available.
We can list all unit files known to our system with a different command.
```
➜ ~ git:(master) ✗ sudo systemctl list-unit-files --type target --all --no-pager
UNIT FILE STATE VENDOR PRESET
basic.target static -
blockdev@.target static -
bluetooth.target static -
boot-complete.target static -
cryptsetup-pre.target static -
cryptsetup.target static -
ctrl-alt-del.target alias -
default.target alias -
emergency.target static -
exit.target disabled disabled
final.target static -
first-boot-complete.target static -
getty-pre.target static -
getty.target static -
graphical.target static -
halt.target disabled disabled
hibernate.target static -
hybrid-sleep.target static -
initrd-fs.target static -
initrd-root-device.target static -
initrd-root-fs.target static -
initrd-switch-root.target static -
initrd.target static -
kexec.target disabled disabled
local-fs-pre.target static -
local-fs.target static -
multi-user.target static -
network-online.target static -
network-pre.target static -
network.target static -
nfs-client.target enabled enabled
nss-lookup.target static -
nss-user-lookup.target static -
paths.target static -
poweroff.target disabled disabled
printer.target static -
reboot.target disabled enabled
remote-cryptsetup.target disabled enabled
remote-fs-pre.target static -
remote-fs.target enabled enabled
rescue-ssh.target static -
rescue.target static -
rpcbind.target static -
runlevel0.target alias -
runlevel1.target alias -
runlevel2.target alias -
runlevel3.target alias -
runlevel4.target alias -
runlevel5.target alias -
runlevel6.target alias -
shutdown.target static -
sigpwr.target static -
sleep.target static -
slices.target static -
smartcard.target static -
sockets.target static -
sound.target static -
suspend-then-hibernate.target static -
suspend.target static -
swap.target static -
sysinit.target static -
system-update-pre.target static -
system-update.target static -
time-set.target static -
time-sync.target static -
timers.target static -
umount.target static -
usb-gadget.target static -
68 unit files listed.
➜ ~ git:(master) ✗
```
That seems to be complete.
Now, how do we switch form one target to an other in a modern systemd-like fashion?
For this we use the `isolate` argument to `systemctl`.
A quick test of a this can be done as such, `sudo systemctl isolate reboot.target`.
On a Linux system where root has a password set you could try the `rescue.target` as well.
You can get and set the default runlevel of you system with the following commands.
```
➜ ~ git:(master) ✗ sudo systemctl get-default
graphical.target
➜ ~ git:(master) ✗ sudo systemctl set-default multi-user.target
Created symlink /etc/systemd/system/default.target → /lib/systemd/system/multi-user.target.
➜ ~ git:(master) ✗ sudo systemctl get-default
multi-user.target
➜ ~ git:(master) ✗
```
## A deeper look into targets
What is included in all of these targets?
We can inspect their dependencies by invoking the `list-dependencies` argument to `systemctl`.
Let's start with the most basic one, the `rescue.target`.
```
➜ ~ git:(master) ✗ sudo systemctl list-dependencies rescue.target --no-pager
rescue.target
● ├─rescue.service
● ├─systemd-update-utmp-runlevel.service
● └─sysinit.target
● ├─apparmor.service
● ├─blk-availability.service
● ├─dev-hugepages.mount
● ├─dev-mqueue.mount
● ├─keyboard-setup.service
● ├─kmod-static-nodes.service
● ├─lvm2-lvmpolld.socket
● ├─lvm2-monitor.service
● ├─proc-sys-fs-binfmt_misc.automount
● ├─sys-fs-fuse-connections.mount
● ├─sys-kernel-config.mount
● ├─sys-kernel-debug.mount
● ├─sys-kernel-tracing.mount
● ├─systemd-ask-password-console.path
● ├─systemd-binfmt.service
● ├─systemd-boot-system-token.service
● ├─systemd-hwdb-update.service
● ├─systemd-journal-flush.service
● ├─systemd-journald.service
● ├─systemd-machine-id-commit.service
● ├─systemd-modules-load.service
● ├─systemd-pstore.service
● ├─systemd-random-seed.service
● ├─systemd-sysctl.service
● ├─systemd-sysusers.service
● ├─systemd-timesyncd.service
● ├─systemd-tmpfiles-setup-dev.service
● ├─systemd-tmpfiles-setup.service
● ├─systemd-udev-trigger.service
● ├─systemd-udevd.service
● ├─systemd-update-utmp.service
● ├─cryptsetup.target
● ├─local-fs.target
● │ ├─-.mount
● │ ├─boot.mount
● │ ├─systemd-fsck-root.service
● │ └─systemd-remount-fs.service
● └─swap.target
● └─dev-mapper-deathstar\x2d\x2dvg\x2dswap_1.swap
➜ ~ git:(master) ✗
```
As you can see, it's quite basic.
All of these services and additional targets will try to be loaded and started when we enter rescue mode.
Now, let's compare it to the most elaborate runlevel, `5`.
```
➜ ~ git:(master) ✗ sudo systemctl list-dependencies graphical.target --no-pager
graphical.target
● ├─display-manager.service
● ├─systemd-update-utmp-runlevel.service
● ├─udisks2.service
● └─multi-user.target
● ├─avahi-daemon.service
● ├─binfmt-support.service
● ├─blueman-mechanism.service
● ├─chrony.service
● ├─console-setup.service
● ├─cron.service
● ├─cups-browsed.service
● ├─cups.path
● ├─dbus.service
● ├─e2scrub_reap.service
● ├─ModemManager.service
● ├─networking.service
● ├─rpcbind.service
● ├─rsyslog.service
● ├─ssh.service
● ├─systemd-ask-password-wall.path
● ├─systemd-logind.service
● ├─systemd-update-utmp-runlevel.service
● ├─systemd-user-sessions.service
● ├─wpa_supplicant.service
● ├─basic.target
● │ ├─-.mount
● │ ├─tmp.mount
● │ ├─paths.target
● │ ├─slices.target
● │ │ ├─-.slice
● │ │ └─system.slice
● │ ├─sockets.target
● │ │ ├─avahi-daemon.socket
● │ │ ├─cups.socket
● │ │ ├─dbus.socket
● │ │ ├─dm-event.socket
● │ │ ├─pcscd.socket
● │ │ ├─rpcbind.socket
● │ │ ├─systemd-initctl.socket
● │ │ ├─systemd-journald-audit.socket
● │ │ ├─systemd-journald-dev-log.socket
● │ │ ├─systemd-journald.socket
● │ │ ├─systemd-udevd-control.socket
● │ │ └─systemd-udevd-kernel.socket
● │ ├─sysinit.target
● │ │ ├─apparmor.service
● │ │ ├─blk-availability.service
● │ │ ├─dev-hugepages.mount
● │ │ ├─dev-mqueue.mount
● │ │ ├─keyboard-setup.service
● │ │ ├─kmod-static-nodes.service
● │ │ ├─lvm2-lvmpolld.socket
● │ │ ├─lvm2-monitor.service
● │ │ ├─proc-sys-fs-binfmt_misc.automount
● │ │ ├─sys-fs-fuse-connections.mount
● │ │ ├─sys-kernel-config.mount
● │ │ ├─sys-kernel-debug.mount
● │ │ ├─sys-kernel-tracing.mount
● │ │ ├─systemd-ask-password-console.path
● │ │ ├─systemd-binfmt.service
● │ │ ├─systemd-boot-system-token.service
● │ │ ├─systemd-hwdb-update.service
● │ │ ├─systemd-journal-flush.service
● │ │ ├─systemd-journald.service
● │ │ ├─systemd-machine-id-commit.service
● │ │ ├─systemd-modules-load.service
● │ │ ├─systemd-pstore.service
● │ │ ├─systemd-random-seed.service
● │ │ ├─systemd-sysctl.service
● │ │ ├─systemd-sysusers.service
● │ │ ├─systemd-timesyncd.service
● │ │ ├─systemd-tmpfiles-setup-dev.service
● │ │ ├─systemd-tmpfiles-setup.service
● │ │ ├─systemd-udev-trigger.service
● │ │ ├─systemd-udevd.service
● │ │ ├─systemd-update-utmp.service
● │ │ ├─cryptsetup.target
● │ │ ├─local-fs.target
● │ │ │ ├─-.mount
● │ │ │ ├─boot.mount
● │ │ │ ├─systemd-fsck-root.service
● │ │ │ └─systemd-remount-fs.service
● │ │ └─swap.target
● │ │ └─dev-mapper-deathstar\x2d\x2dvg\x2dswap_1.swap
● │ └─timers.target
● │ ├─apt-daily-upgrade.timer
● │ ├─apt-daily.timer
● │ ├─e2scrub_all.timer
● │ ├─logrotate.timer
● │ ├─man-db.timer
● │ └─systemd-tmpfiles-clean.timer
● ├─getty.target
● │ ├─getty-static.service
● │ └─getty@tty1.service
● ├─nfs-client.target
● │ ├─auth-rpcgss-module.service
● │ ├─nfs-blkmap.service
● │ └─remote-fs-pre.target
● └─remote-fs.target
● └─nfs-client.target
● ├─auth-rpcgss-module.service
● ├─nfs-blkmap.service
● └─remote-fs-pre.target
➜ ~ git:(master) ✗
```
You immediately see, and probably recognise a lot of very useful services that get launched when we enter the graphical target.
Mind you that the output above is from a pretty lean system running a minimal i3 graphical environment.
We can also use the `list-dependencies` to inspect services such as `sshd.service`.
The list below is everything sshd depends on to succesfully run as a systemd service.
```
sshd.service
● ├─-.mount
● ├─system.slice
● └─sysinit.target
● ├─apparmor.service
● ├─blk-availability.service
● ├─dev-hugepages.mount
● ├─dev-mqueue.mount
● ├─keyboard-setup.service
● ├─kmod-static-nodes.service
● ├─lvm2-lvmpolld.socket
● ├─lvm2-monitor.service
● ├─proc-sys-fs-binfmt_misc.automount
● ├─sys-fs-fuse-connections.mount
● ├─sys-kernel-config.mount
● ├─sys-kernel-debug.mount
● ├─sys-kernel-tracing.mount
● ├─systemd-ask-password-console.path
● ├─systemd-binfmt.service
● ├─systemd-boot-system-token.service
● ├─systemd-hwdb-update.service
● ├─systemd-journal-flush.service
● ├─systemd-journald.service
● ├─systemd-machine-id-commit.service
● ├─systemd-modules-load.service
● ├─systemd-pstore.service
● ├─systemd-random-seed.service
● ├─systemd-sysctl.service
● ├─systemd-sysusers.service
● ├─systemd-timesyncd.service
● ├─systemd-tmpfiles-setup-dev.service
● ├─systemd-tmpfiles-setup.service
● ├─systemd-udev-trigger.service
● ├─systemd-udevd.service
● ├─systemd-update-utmp.service
● ├─cryptsetup.target
● ├─local-fs.target
● │ ├─-.mount
● │ ├─boot.mount
● │ ├─systemd-fsck-root.service
● │ └─systemd-remount-fs.service
● └─swap.target
● └─dev-mapper-deathstar\x2d\x2dvg\x2dswap_1.swap
➜ ~ git:(master) ✗
```
A very clever *reverse dependency* list can be show by adding the `--reverse` argument.
The output below show the dependencies of the networking.service first.
You can see it *needs* the ifupdown-pre.service, system.slice and the network.target.
The second command shows the reverse, which services or targets *depend* on the networking.service to be up and running.
```
➜ ~ git:(master) ✗ sudo systemctl list-dependencies networking.service --no-pager
networking.service
● ├─ifupdown-pre.service
● ├─system.slice
● └─network.target
➜ ~ git:(master) ✗ sudo systemctl list-dependencies networking.service --no-pager --reverse
networking.service
● ├─multi-user.target
● │ └─graphical.target
● └─network-online.target
➜ ~ git:(master) ✗
```
The combination of both can give you a solid understanding of how all services and targets are interconnected.
Just as with services we can inspect *what* a target is doing by looking at it's unit file.
```
➜ ~ git:(master) ✗ sudo systemctl cat network-online.target
# /lib/systemd/system/network-online.target
# SPDX-License-Identifier: LGPL-2.1-or-later
#
# This file is part of systemd.
#
# systemd is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation; either version 2.1 of the License, or
# (at your option) any later version.
[Unit]
Description=Network is Online
Documentation=man:systemd.special(7)
Documentation=https://www.freedesktop.org/wiki/Software/systemd/NetworkTarget
After=network.target
➜ ~ git:(master) ✗
```
This might not tell you all that much on first sight, but I urge you to take the time out to really read the `man systemd.special`.
It will explain you all the intricacies of the different standard targets and how you can use them to your benefit.