Systemd/Syslog
Syslog
Besser protokolliert
Log-Meldungen verwaltet in den allermeisten Fällen ein Syslog-Server
- Das Fedora-Projekt will dieses jetzt ändern und in zukünftigen Releases neue Wege beschreiten
- Hier soll dann Journald aus dem Systemd-Paket zum Einsatz kommen
Wenn ich mich mit jemandem über das Thema System- und Service-Management unterhalte, stelle ich oft eine gewisse Verunsicherung fest, wenn wir auf das Thema "systemd" zu sprechen kommen
- Deshalb an dieser Stelle eine kleine Einführung und ein paar Gründe, die für ein neues Init-System sprechen
- Man ist es zwar irgendwie gewohnt, dass sich ein SysV-basierter Init-Prozess um den Systemstart kümmert, da dieses System aber in die Jahre gekommen ist und aktuelle Anforderungen nicht mehr wirklich gut erfüllt, wird es Zeit für einen Nachfolger
- Dieser existiert eigentlich bereits seit geraumer Zeit mit Upstart
Upstart ist zum größten Teil abwärtskompatibel mit dem alten SysV-System und löst viele der alten Probleme
- Anstatt eine vordefinierte Liste abzuarbeiten, welche Dienste zu starten sind, ist Upstart Event-basiert
- Auf Basis dieser Events finden dann Aktionen statt
- All diese Event-/Aktionsregeln definiert der Administrator beziehungsweise Entwickler eines Dienstes in den Upstart-Konfigurationsdateien
- Und hier liegt genau das Problem von Upstart
- Passt man nicht genau auf, welche Events von anderen Events abhängig sind, erhält man eine Reihe von Abhängigkeiten, die dann dafür sorgen, dass Dienste wieder aufeinander warten müssen, bevor sie starten können
- Und genau dies möchte man ja verhindern
Problem gelöst
Lennart Poettering und sein Team wollen mit ihrer Implementierung eines neuen Init-Systems dieses (und andere) Probleme lösen und gehen sogar noch einen Schritt weiter
- Die systemd genannte Software startet einfach alle Dienste parallel, ohne sich dabei um Abhängigkeiten zu kümmern
- Möchte ein Dienst auf einen anderen Dienst zugreifen, so landen die Anfragen einfach so lange in einer Warteschlange, bis der gewünschte Dienst verfügbar ist
- Dieser von Apples launchd bekannte Trick sorgt dafür, dass ein System extrem schnell hochfährt
- Neben dieser Funktion bietet systemd natürlich noch viele weitere Neuerungen
- Interessant ist auch, dass jeder durch systemd gestartete Prozess in einer eigenen Control-Group (Cgroup) landet und somit unter der Kontrolle des Kernels steht
- Eine sehr gute und sehr ausführliche Beschreibung des neuen Init-Systems findet sich unter [1]
An dieser Stelle geht es nun um eine Funktion von Systemd, die bereits seit der Version 38 zur Verfügung steht: das Journal
- Hierbei handelt es sich um ein neuartiges Logging-System, das, ähnlich wie Systemd selbst, radikale Änderungen mit sich bringt und einige grundlegende Probleme des alten Syslogd beheben möchte
- Davon gibt es in der Tat genügend
- So sieht das Syslog-Protokoll beispielsweise nicht vor, eine Log-Meldung zu authentifizieren
- Jeder ist in der Lage, Meldungen von einem bestimmten Prozess vorzutäuschen beziehungsweise zu verändern
Das Log-Format selbst sieht nur wenige Felder vor, die in jeder Nachricht zu verwenden sind, beispielsweise den Prozessnamen und die ID des Prozesses
- Der Inhalt der Nachricht wird zumeist so aufbereitet, dass er für einen Menschen gut leserlich ist
- Jedoch ist das manuelle Durchforsten von Log-Dateien nicht wirklich effektiv, sodass in den allermeisten Fällen doch wieder ein Log-Parser zum Einsatz kommt
- Dieser muss dann den umgekehrten Weg beschreiten und die Nachricht so zerlegen, dass ihre Informationen lesbar werden – alles nicht sehr effektiv
Hinzu kommt noch das Problem, dass die Syslog-Meldungen ja nicht die einzigen Logs auf einem System darstellen
- Es existieren auch noch Logs von anderen Subsystemen, die nicht auf Syslog zurückgreifen
- Die Audit- und Accounting-Subsysteme sind Beispiele hierfür
- Dann gibt es natürlich auch jede Menge Anwendungen, die ihre eigenen Logs verwenden
- Am Ende sind es also eine Vielzahl unterschiedlicher Log-Mechanismen, mit denen man sich auseinandersetzen muss
- Der in Systemd integrierte Journald versucht all diese Probleme zu lösen und stellt ein einheitliches Log für sämtliche Komponenten eines Systems zur Verfügung
Anwendungen und Services können beliebige Meta-Informationen an den Journald weiterreichen
- Dies erfolgt entweder mittels printk() , der regulären syslog() -Funktion, über die native API oder für Coredumps mittels /proc/proc/sys/kernel/core_pattern
- Die Informationen werden als Key-/Value- Paare übergeben und können einzeln abgefragt werden
- Log-Meldungen werden kryptografisch gesichert und sind somit vor Veränderungen geschützt
- Benutzerrelevante Meldungen können dabei von den Benutzern selbst eingesehen werden, Systemmeldungen sind root oder den Mitglieder der Gruppe adm vorbehalten
Um eine Übersicht sämtlicher Log-Meldungen, auch von bereits rotierten Logs, zu bekommen, reicht der Aufruf von journalctl
- Die Ausgabe und das Format sind nahezu identisch mit dem, was man von einer /var/log/messages -Datei gewohnt ist
- Auch die von tail bekannten Optionen -f und -n kann man verwenden, um lediglich die letzten Zeilen des Journals zu sehen
- Warnmeldungen stellt der journald fettgedruckt, Fehlermeldungen in Rot dar
- Wer lediglich die Meldungen seit des letzten Bootvorgangs sehen möchte, der ruft journalctl einfach mit der Option -b auf
- Nett, aber noch nicht sonderlich aufregend
Da das Journal für jedes Log-Feld einen Index besitzt, lassen sich die Meldungen recht schön filtern
- Möchte man eine Übersicht aller Meldungen eines Services innerhalb eines bestimmten Zeitfensters bekommen, so wäre dies mit folgendem Befehl möglich:
- journalctl -u vsftpd --since=yesterday --until '2013-11-05 11:00'
Keine Ahnung, welche Systemd-Units auf dem System vorhanden sind? Kein Problem: Der Befehl systemctl list-unit-files zeigt sie an
- Interessiert man sich lediglich für Services, grenzt die Option --type=service die Ausgabe entsprechend ein
- Insgesamt stellt Systemd aktuell zwölf verschiedene Unit-Types zur Verfügung
Doch woher weiß man, welche Felder zu einer Log-Meldung gehören? Hier hilft es weiter, die Option -o verbose an den Journald zu übergeben
- Alle Felder einer Meldung werden dann im Key-/Value-Format angezeigt
- Mit diesen Informationen gewappnet, kann man weiter auf Entdeckungsreise gehen
- Sie möchten etwa alle Meldungen eines bestimmten Nutzers sehen, die zu einem Fehler geführt haben? Kein Problem. Übergibt man das gewünschte Feld zusammen mit der Log-Priorität err , werden die beiden Optionen miteinander verknüpft und das passende Ergebnis angezeigt:
- journalctl -p err _UID=1000
Es wird noch besser
- Ich möchte vielleicht alle relevanten Fehlermeldungen einer bestimmten SELinux-Domäne sehen? Nun, der Aufruf hierfür wäre entsprechend:
- journalct -p err _SELINUX_CONTEXT=Kontext
Was aber, wenn ich nicht mehr genau weiß, wie denn der Kontext der entsprechenden SELinux-Domäne lautet? Dann lasse ich das Feld für den Kontext einfach leer und drücke zweimal die Tab-Taste, bekomme eine Liste aller bekannten Kontextinformationen aus den Logs und kann die richtige Domäne raussuchen
- Diese Auto-Completion funktioniert mit allen Feldern, die das Journal kennt.Datei:Bild7.png
Abbildung 1: Das Tool systemctl zeigt bei Status-Abfragen eines Dienstes die aktuellen Log-Meldungen für diesen Dienst an
Suche eingebaut
Abschließend sei noch erwähnt, dass die Journal-Meldungen für einen bestimmten Service in der Status-Ausgabe des Systemd verwendet werden (Abbildung 1)
- Somit sind alle relevanten Log-Meldungen für einen Dienst sofort sichtbar und man muss nicht erst umständlich in der passenden Log-Datei danach suchen
Infos# Systemd-Einführung: https://0pointer.de/blog/projects/systemd.html
systemd ist ein System- und Sitzungs-Manager (Init-System), der für die Verwaltung aller auf dem System laufenden Dienste über die gesamte Betriebszeit des Rechners, vom Startvorgang bis zum Herunterfahren, zuständig ist
- Prozesse werden dabei immer (soweit möglich) parallel gestartet, um den Bootvorgang möglichst kurz zu halten
Bei Ubuntu ist es der zweite Ansatz, das in die Jahre gekommene Init-System SysVinit abzulösen
- Während Canonical bis einschließlich Ubuntu 14.04 ausschließlich und exklusiv auf die Eigenentwicklung Upstart setzte, löst es dieses ab Ubuntu 14.10 nach und nach ab
- Ab Ubuntu 15.04 ist es bei Ubuntu und den offiziellen Varianten vorinstalliert
- Allerdings werden im Hintergrund viele Funktionen weiterhin an Upstart weitergereicht
- Wann Upstart endgültig aus Ubuntu entfernt wird, ist derzeit unbekannt
Die Verwendung von systemd ist nicht unumstritten
- Protokolldateien werden - in der Voreinstellung - im Binär-Format gespeichert und können daher nicht mit den üblichen Werkzeugen wie less oder grep angezeigt oder durchsucht werden
- Darüber hinaus setzt systemd spezielle Funktionen (wie cgroups) des Linux-Kernels voraus, wodurch es nicht auf andere unixoide Systeme portiert werden kann
Grundlagen
Units
Systemd wird über Dateien konfiguriert
- Man nennt so eine Datei "Unit"
- Bei Ubuntu vorinstallierte Units sind im Ordner /lib/systemd/system/ gespeichert
- Falls sich jedoch eine Unit mit gleichem Namen im Verzeichnis /etc/systemd/system/ befindet, so wird diese bevorzugt und jene in /lib ignoriert
- Damit hat man die Möglichkeit, eine Unit an eigene Gegebenheiten anzupassen, ohne dass man befürchten muss, dass sie bei einem Update überschrieben wird
- Es existieren verschiedene Typen von Units, die von systemd je nach Endung des Dateinamens unterschiedlich behandelt werden:
Typ | Beschreibung |
.device | Legt Gerätedateien an |
.mount | Ein- und Aushängen von Dateisystemen |
.path | Startet die Unit via inotify |
.service | Für Dienste |
.socket | Stellt Verbindungen zwischen Prozessen her |
.target | Definiert eine Gruppe von Units |
.timer | Für wiederkehrende Aufgaben, ähnlich cron-Jobs
|
Verwaltung
Grafische Werkzeuge
systemd bringt im Gegensatz zu Upstart ein grafisches Werkzeug mit, mit der Benutzer mit Root-Rechten [1] Einfluss auf das Verhalten nehmen können [2].* systemd-ui (universe)
mit apturl
Paketliste zum Kopieren: apt-get aptitude
sudo apt-get install systemd-ui
Um möglichst universell verwendet werden zu können, ist die Programmoberfläche allerdings komplett auf Englisch
- Gestartet wird das Programm aus dem Terminal mit diesem Befehl:
systemadm
Protokolle
Mit der GNOME-Anwendung Logs können die Protokolldateien von systemd grafisch angezeigt werden
- Ab Ubuntu 14.10 steht folgendes Paket zur Verfügung:* gnome-logs (universe)
mit apturl
Paketliste zum Kopieren: apt-get aptitude
sudo apt-get install gnome-logs
Kommandozeile
Das Werkzeug, um systemd auf der Kommandozeile bzw. in einem Terminal [3] zu verwalten, hört auf den Namen systemctl
- Um einzelne Dienste zu betrachten, muss die Unit explizit angegeben werden
- In den folgenden Beispielen wird das Wort "unit" als Platzhalter verwendet
Die meisten Befehle greifen tief ins System ein und benötigen daher Root-Rechte
- Diese werden bei Bedarf durch PolicyKit abgefragt
- Mman kann sie aber auch implizit durch ein vorangestelltes sudo gewähren
Befehl | Beschreibung |
systemctl | Listet alle units auf |
systemctl --failed | Listet alle Dienste auf, die nicht gestartet werden konnten |
systemctl status | Zeigt alle Units mit ihren Abhängigkeiten voneinander |
systemctl status unit | Zeigt den Status einer einzelnen Unit |
systemctl stop unit | Stoppt eine Unit |
systemctl start unit | Startet eine Unit |
systemctl restart unit | Stoppt eine Unit und startet sie sofort wieder |
systemctl reload unit | Erzwingt das erneute Einlesen der Konfiguration einer Unit, die Units wird nicht neu gestartet |
systemctl enable unit | Unit wird aktiviert und kann beim Booten gestartet werden |
systemctl disable unit | Unit wird deaktiviert und wird beim Booten nicht automatisch gestartet
|
systemctl reenable unit | Arbeitet die obigen Anweisung disable und dann enable nacheinander ab
|
systemctl mask unit | Starten einer Unit verbieten |
systemctl unmask unit | Starten einer Unit erlauben |
systemctl daemon-reload | systemd Units neu Einlesen |
Auch das Herunterfahren oder Neustarten des Rechners erfolgt mit systemctl:
Befehl | Beschreibung |
systemctl poweroff | Herunterfahren |
systemctl reboot | Neustarten
|
Logs
Logdateien sind nun über den Befehl journalctl abrufbar:
Befehl | Beschreibung |
journalctl | Listet alle Meldungen im Log auf |
journalctl -u unit | Listet nur die Meldungen einer bestimmten Unit auf |
journalctl -u unit -f | Listet nur die Meldungen einer bestimmten Unit auf, entspricht tail -f
|
Sonstiges
Befehl | Beschreibung |
hostnamectl | Rechnername anzeigen oder ändern |
timedatectl | Datum, Uhrzeit und Zeitzone anzeigen oder ändern |
localectl | Verwendeten Zeichensatz anzeigen oder ändern |
loginctl | Loginverwaltung
|
Analyse
Systemd kann zu Analysezwecken eine BootChart-ähnliche Grafik erzeugen, die den Bootvorgang detailliert darstellt
- Dazu verwendet man folgenden Befehl:
systemd-analyze plot > bootchart.svg
Problembehebung
/etc/modules
Die Datei /etc/modules wird zwar noch von systemd ausgewertet, nimmt aber keine Optionen für die aufgeführten Kernelmodule mehr entgegen
- Stattdessen müssen die Optionen in einer Datei unterhalb des Ordners /etc/modprobe.d/ übergeben werden
/etc/rc.local
Das entsprechende Unit* /lib/systemd/system/rc-local.service
zum Aufruf der Datei /etc/rc.local ist vorhanden und wird auch von systemd ausgewertet
Jedoch wird der entsprechende rc-local.service in der jetzigen Konfiguration nur von anderen Prozessen angestoßen, so dass das für eigene Zwecke nicht optimal sein kann (unkontrolliertes Timing)
- Dies kann durch ein "target" gelöste werden, z. B. durch "multi-user.target"
- Anzeigen der aktuellen Unit:
systemctl cat rc-local
Falls hier am Ende ein Install Abschnitt mit einem entsprechenden "target" fehlt, kann dieses ergänzt werden:
sudo systemctl edit --full rc-local
öffnet einen Texteditor im Terminal, am Ende ergänzt man
[Install] WantedBy=multi-user.target
Speichert und beendet den Editor
- Die geänderde Unit wird nun noch aktiviert:
sudo systemctl reenable rc-local
Die angepasste rc-local Unit liegt nun unter /etc/systemd/system/rc-local.service und hat z. B. folgenden Inhalt, anzuzeigen mit systemctl cat rc-local:
vergrößern
[Unit]
Description=/etc/rc.local Compatibility
ConditionFileIsExecutable=/etc/rc.local
After=network.target
[Service] Type=forking ExecStart=/etc/rc.local start TimeoutSec=0 RemainAfterExit=yes
[Install] WantedBy=multi-user.target