systemctl und journalctl in der Praxis (2)


Im zweiten Teil meiner Serie zu gehe ich ausführlich auf Service Units und das Journal von systemd ein. Diese beiden Komponenten bilden quasi das Grundgerüst des Bootvorgangs und die Verwaltung der Dienste eines Linuxsystems.

Was sind Targets

Targets bieten ein Konzept das ähnlich der Runlevel des Sysvinit ist. In SysVinit wurden die Funktionalitäten (Dienste, Prozesse usw.) in sieben Run-Levels (0-6) organisiert. systemd verwaltet seine Target-Units in wesentlich mehr Stufen.

systemd verwendet Targets, um Einheiten über Abhängigkeiten und als standardisierte Synchronisationspunkte zu gruppieren.

Das Listing zeit alle aktiven Targets eines Systems. Um auch noch die inaktiven zu sehen hängt an das Kommando noch die Option –all an.

$ systemctl --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                
graphical.target       loaded active active 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 active active Network is Online            
network.target         loaded active active Network                      
nfs-client.target      loaded active active NFS client services          
nss-lookup.target      loaded active active Host and Network Name Lookups
nss-user-lookup.target loaded active active 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          
rpcbind.target         loaded active active RPC Port Mapper              
slices.target          loaded active active Slices                       
sockets.target         loaded active active Sockets                      
sound.target           loaded active active Sound Card                   
swap.target            loaded active active Swap                         
sysinit.target         loaded active active System Initialization        
time-sync.target       loaded active active System Time Synchronized     
timers.target          loaded active active Timers


Um die Abwärtskompatibilität sicherzustellen wurden bestimmte Targets auf die ehemaligen Runlevel mit Hilfe von Links abgebildet. Zum Beispiel bildet das graphical.target den Runlevel 5 von SysVinit ab, also der Betrieb des Systems mit gestarteten X-Windows.

$ ls -l /lib/systemd/system/runlevel?.target
lrwxrwxrwx 1 root root 15 Feb  6 16:00 /lib/systemd/system/runlevel0.target -> poweroff.target
lrwxrwxrwx 1 root root 13 Feb  6 16:00 /lib/systemd/system/runlevel1.target -> rescue.target
lrwxrwxrwx 1 root root 17 Feb  6 16:00 /lib/systemd/system/runlevel2.target -> multi-user.target
lrwxrwxrwx 1 root root 17 Feb  6 16:00 /lib/systemd/system/runlevel3.target -> multi-user.target
lrwxrwxrwx 1 root root 17 Feb  6 16:00 /lib/systemd/system/runlevel4.target -> multi-user.target
lrwxrwxrwx 1 root root 16 Feb  6 16:00 /lib/systemd/system/runlevel5.target -> graphical.target
lrwxrwxrwx 1 root root 13 Feb  6 16:00 /lib/systemd/system/runlevel6.target -> reboot.target


Einen Wechsel des Targets erreicht man mit dem Schlüsselwort isolate. Hier im Beispiel wird in das multi-user.target (System ohne gestartetes X-Windows) gewechselt.

# systemctl isolate muli-user.target

Die Anzeige des Standard-Targets wird der Option get-default gelistet.

$ systemctl get-default
graphical.target


Was sind Units

Units verwalten das System nach Aufgaben, davon gibt es zahlreiche unterschiedliche Typen von Units. Die wichtigsten Typen sind service, socket, device, mount, swap, target, timer und path.

Systemd Service Units dienen dazu Dienste zu starten und zu stoppen. Der Befehl zur Steuerung ist systemctl.

Stoppen und starten erfolgt jeweils mit dem gleichlautenden Schlüsselwort. Beim Restart einer Unit wird der Service auf jeden Fall neu gestartet, auch wenn er vorher nicht lief. Der Reload, wird zum Unterschied zum Restart, mit neu eingelesenen Konfigurationsdateien neu gestart. Wenn der Dienst nicht lief wird er durch den Reload nicht neu gestartet.

 # systemctl stop ssh.service
 # systemctl start ssh.service
 # systemctl restart ssh.service
 # systemctl reload ssh.service


Will man einfach nur sehen welchen Status ein Service hat, erreicht man das mit dem Schlüsselwort status.

$ systemctl status ssh.service
● ssh.service - OpenBSD Secure Shell server
   Loaded: loaded (/lib/systemd/system/ssh.service; enabled; vendor preset: enabled)
   Active: active (running) since Fri 2020-05-01 10:20:43 CEST; 9h ago
  Process: 1263 ExecStartPre=/usr/sbin/sshd -t (code=exited, status=0/SUCCESS)
 Main PID: 1267 (sshd)
    Tasks: 1 (limit: 4915)
   CGroup: /system.slice/ssh.service
           └─1267 /usr/sbin/sshd -D

Mai 01 17:20:03 neonlight sshd[16013]: pam_unix(sshd:session): session opened for user root by (uid=0)
Mai 01 17:20:04 neonlight sshd[16013]: Received disconnect from 192.168.22.10 port 42532:11: disconnected by user
Mai 01 17:20:04 neonlight sshd[16013]: Disconnected from user root 192.168.22.10 port 42532
Mai 01 17:20:04 neonlight sshd[16013]: pam_unix(sshd:session): session closed for user root
Mai 01 19:30:01 neonlight sshd[29309]: pam_unix(sshd:auth): authentication failure; logname= uid=0 euid=0 tty=ssh ruser= rhost=192.168.19… user=root
Mai 01 19:30:02 neonlight sshd[29309]: Accepted publickey for root from 192.168.22.10 port 42780 ssh2: RSA SHA256:E9b5pJ/zNTE3BxBFcrel0x…uVeiGpGkIQ
Mai 01 19:30:02 neonlight sshd[29309]: pam_unix(sshd:session): session opened for user root by (uid=0)
Mai 01 19:30:03 neonlight sshd[29309]: Received disconnect from 192.168.22.10 port 42780:11: disconnected by user
Mai 01 19:30:03 neonlight sshd[29309]: Disconnected from user root 192.168.22.10 port 42780
Mai 01 19:30:03 neonlight sshd[29309]: pam_unix(sshd:session): session closed for user root
Hint: Some lines were ellipsized, use -l to show in full.


Wie sieht nun so eine Service Unit aus? Am Beispiel vom der cups.service will ich das zeigen. Das Schlüsselwort cat zeigt den Inhalt einer angegebenen Service Unit an. Der Inhalt gliedert sich in drei Haupteile Unit, Service und Install.

In der Sektion Unit wird der Dienst näher beschrieben, wo die Doku zu finden ist und das nach die Unit nach dem sssd.service gestartet werden soll.

In der Sektion Service wird das zu startende Programm inklusive Pfad angegebenen und evtl. die Optionsparameter. Im Type wird Typ das der Service haben soll angegebenen. Ein Restart soll immer wieder erfolgen wenn sich der Prozess beendet oder einen Timeout erreicht hat.

Die Direktive Also erlaubt es, Einheiten als Satz zu aktivieren oder zu deaktivieren. WantedBy bedeutet eine Abhängigkeit von der aufgelisteten Einheit zur aktuellen Einheit. Das Ergebnis soll sein, dass die aktuelle Einheit gestartet wird, wenn die aufgelistete Einheit gestartet wird.

$ systemctl cat cups.service

[Unit]
Description=CUPS Scheduler
Documentation=man:cupsd(8)
After=sssd.service

[Service]
ExecStart=/usr/sbin/cupsd -l
Type=simple
Restart=always

[Install]
Also=cups.socket cups.path
WantedBy=printer.target


Will oder muss man eine beliebige Service Datei verändern vereinfacht das Kommando systemctl mit der Option edit das erheblich.

 # systemctl edit --full cups.service

Sind die Änderungen abgespeichert schickt man noch einen Reload hinterher damit sie wirksam werden.

 # systemctl daemon-reload


Auch der Zustand eines Dateisystems beim Einhängen im Bootvorgang und und in der Zwischenzeit aufgelaufene Meldungen kann man abfragen (hier im Beispiel am Filesystem /var).

$ systemctl status /var
● var.mount - /var
   Loaded: loaded (/etc/fstab; generated)
   Active: active (mounted) since Mon 2020-05-04 07:14:10 CEST; 5h 31min ago
    Where: /var
     What: /dev/mapper/VGsys-LVvar
     Docs: man:fstab(5)
           man:systemd-fstab-generator(8)
  Process: 1018 ExecMount=/bin/mount /dev/disk/by-label/VAR /var -t ext4 (code=exited, status=0/SUCCESS)
    Tasks: 0 (limit: 4915)
   CGroup: /system.slice/var.mount

Mai 04 07:14:10 neonlight systemd[1]: Mounting /var...
Mai 04 07:14:10 neonlight systemd[1]: Mounted /var.


Detailinformationen aus dem Journal

Im Journal des systemd werden die Log-Informationen, in binärer Form, persistent unter /var/log/journal abgelegt. Das Kommando journalctl kann die binären Informationen für den Anwender entsprechend aufbereiten. Die Anzeige kann auf bestimmte Dienste beschränkt werden oder auf gewünschte Zeiträume. Ebenso können Logmeldungen des Kernels, ähnlich dem Befehl dmesg, aufgelistet werden. Eine fortlaufende Anzeige, wie zB. beim tail -f Kommando ist gleichfalls möglich.

Unabhängig von der eingestellten Zeitzone kann man journalctl anweisen alle Zeitstempel in UTC auszugeben, das erledigt die Option utc.

 # journalctl --utc

Um ab einen bestimmten Datum die Logeinträge zu sehen ist mit der Option since möglich. Der genaue Zeitpunkt im Format “JJJJ-MM-TT HH:MM:SS” in doppelten Hochkommatas anzugeben.

 # systemctl --since="2020-05-02 12:25:00"

Auch ein definierter Zeitraum von bis ist möglich mit der zusätzlichen Option until. Hier im Beispiel werden ale Logeinträge vom 03.05.2020 18:25 Uhr bis 18:36 Uhr angezeigt.

 # journalctl –since=“2020-05-03 18:25:00” –until=“2020-05-03 18:36:00”

Um von einem bestimmten Zeitpunkt bis jetzt alle Logeinträge aufzulisten genügen folgende Kommandos.

 # journalctl --since="2020-05-03 18:25:00" --until="now"
 # journalctl --since="09:00" --until "1 hour ago"

Will man einfach nur die gesamten Einträge von gestern oder heute sehen, kann man das mit nachfolgenden Kommandos tun.

 # journalctl --since="yesterday"
 # journalctl --since="today"

Systemd verwaltet die Logeinträge im Journal pro Bootvorgang ab. Diese Liste kann man sich per Option list-boots anzeigen lassen (hier im Beispiel gekürzt).

 # journalctl --list-boots
-91 f3e24309cde741aea40b3b2a554e3c9d Sat 2020-02-22 09:35:47 CET—Sat 2020-02-22 21:46:50 CET
-90 9da955be08864cd995a234bff21afd55 Sun 2020-02-23 10:52:36 CET—Sun 2020-02-23 22:32:12 CET
-89 25ff3b61e8bd4ccea3bc0e10b40acf0c Mon 2020-02-24 17:36:09 CET—Mon 2020-02-24 22:01:54 CET
 
[...]
 
 -4 f1b422899434444c8757a1da28c5d298 Thu 2020-04-30 07:06:56 CEST—Thu 2020-04-30 21:46:56 CEST
 -3 6fda0805dd8f4c6dbfe6461d6c3963d1 Fri 2020-05-01 10:20:42 CEST—Fri 2020-05-01 22:29:52 CEST
 -2 0cfe627aaa4a4cfe94ed5e84b126be03 Sun 2020-05-03 12:35:27 CEST—Sun 2020-05-03 21:17:09 CEST
 -1 fdb5a2e2fa1f4bd38edce59838ba7980 Sun 2020-05-03 21:37:18 CEST—Sun 2020-05-03 22:24:20 CEST
  0 1432c467054a4f3ebabb4f55985b3566 Mon 2020-05-04 07:14:09 CEST—Mon 2020-05-04 08:45:01 CEST


Einen einzelnen Eintrag zu einem bestimmten Tag kann man sich auf zweierlei Arten anzeigen lassen. Erstere ist mit der Angabe der ID (zweite Spalte) oder mit der fortlaufenden Nummer aus der ersten Spalte. Wobei mit dem Wert “0” immer der aktuelle Bootvorgang definiert ist. Die Anzahl der gespeicherten Eintäge ist abhängig von konfiguierten Journalgröße in der Datei /etc/systemd/journald.conf (Variable SystemMaxUse).

Die nachfolgenden Kommandos zeigen jeweils den gleichen Satz der Logeinträge vom 30.04.2020 an.

 # journalctl -b f1b422899434444c8757a1da28c5d298
 # journalctl -b-4

Alle Logmeldungen zu einem bestimmten Service lassen ebenso anzeigen.

 # journalctl -u smartd.service

Zwei oder mehrere Services in Kombination können jeweils mit der Option -u abgefragt werden.

 # journalctl -u postfix.service -u thermald.service --since="today"
-- Logs begin at Sat 2020-02-22 09:35:47 CET, end at Mon 2020-05-04 12:03:01 CEST. --
Mai 04 07:14:12 neonlight systemd[1]: Starting Thermal Daemon Service...
Mai 04 07:14:12 neonlight thermald[1172]: 13 CPUID levels; family:model:stepping 0x6:3a:9 (6:58:9)
Mai 04 07:14:12 neonlight thermald[1172]: Polling mode is enabled: 4
Mai 04 07:14:12 neonlight systemd[1]: Started Thermal Daemon Service.
Mai 04 07:14:16 neonlight systemd[1]: Starting Postfix Mail Transport Agent...
Mai 04 07:14:16 neonlight systemd[1]: Started Postfix Mail Transport Agent.

In Kombination mit einem bestimmten Datum und/oder Uhrzeit lässt sich es sich weiter eingrenzen.

 # journalctl -u smartd.service --since="today"
 # journalctl -u smartd.service --since="2020-05-04 09:25:00"
 # journalctl -u smartd.service --since="2020-05-04 09:25:00" --until "2020-05-04 09:45:00"


Über den Programmpfad, den man mit dem Befehl which ermittelt, lassen sich alle Meldungen zur Anwendung selektieren (hier im Beispiel von smartd).

 # which smartd
 /usr/sbin/smartd
 
 # journalctl /usr/sbin/smartd
 Mai 04 10:14:13 neonlight smartd[1200]: Device: /dev/sdb [SAT], SMART Usage Attribute: 194 Temperature_Celsius changed from 112 to 113
Mai 04 10:44:13 neonlight smartd[1200]: Device: /dev/sda [SAT], SMART Usage Attribute: 190 Airflow_Temperature_Cel changed from 66 to 64
Mai 04 10:44:14 neonlight smartd[1200]: Device: /dev/sdb [SAT], SMART Usage Attribute: 194 Temperature_Celsius changed from 113 to 112


Alle Kernelmeldungen vom letzten Reboot können wie nachfolgend gelistet werden (im Beispiel gekürzt).

 # journalctl -k
 -- Logs begin at Sat 2020-02-22 09:35:47 CET, end at Mon 2020-05-04 12:09:01 CEST. --
Mai 04 07:14:09 neonlight kernel: microcode: microcode updated early to revision 0x21, date = 2019-02-13
Mai 04 07:14:09 neonlight kernel: Linux version 5.3.0-51-generic (buildd@lgw01-amd64-018) (gcc version 7.5.0 (Ubuntu 7.5.0-3ubuntu1~18.04)) #44~18.04.2-Ubuntu SMP Thu Apr 23 14:27:18 U
Mai 04 07:14:09 neonlight kernel: Command line: BOOT_IMAGE=/boot/vmlinuz-5.3.0-51-generic root=/dev/mapper/VGsys-LVroot ro quiet splash vt.handoff=1 3
Mai 04 07:14:09 neonlight kernel: KERNEL supported cpus:
Mai 04 07:14:09 neonlight kernel:   Intel GenuineIntel
Mai 04 07:14:09 neonlight kernel:   AMD AuthenticAMD
Mai 04 07:14:09 neonlight kernel:   Hygon HygonGenuine
Mai 04 07:14:09 neonlight kernel:   Centaur CentaurHauls
Mai 04 07:14:09 neonlight kernel:   zhaoxin   Shanghai  
Mai 04 07:14:09 neonlight kernel: x86/fpu: Supporting XSAVE feature 0x001: 'x87 floating point registers'
Mai 04 07:14:09 neonlight kernel: x86/fpu: Supporting XSAVE feature 0x002: 'SSE registers'
Mai 04 07:14:09 neonlight kernel: x86/fpu: Supporting XSAVE feature 0x004: 'AVX registers'
[...]


Die Meldungsausgabe nach Klassen des Syslog ist mit der Option -p mit Angabe der ID oder Namen möglich. Folgende Ausgaben der Fehlerklasse “Err” bzw. “3” liefern das gleiche Ergebnis.

 # journalctl -p 3 --since="today"
 # journalctl -p err --since="today"

Meldungsklassen (ID, Name)

0: emerg
1: alert
2: crit
3: err
4: warning
5: notice
6: info
7: debug


Fazit


Mit dem Journal von systemd und seinen Werkzeugen journalctl bzw. systemctl ist man in der Lage schnell und effizient die benötigten Information zu Fehlern bzw. den Zustand der jeweiligen Services, Dateisystemen und Blockdevies zur Anzeige zu bringen. Man erhält mit einem zentralen Werkzeug Zugriff auf alle möglichen Log-Quellen und muss nicht mit vielen einzelnen Logdateien wie bei SysVinit hantieren.


Weiterführende Informationen


Teil 1: systemctl und journalctl in der Praxis (1)

Understanding Systemd Units and Unit Files

ubuntuusers.de - Units