Fehlerbehebung bei Systemd-Dienstfehlern: Eine Schritt-für-Schritt-Anleitung
Systemd hat sich zum De-facto-System- und Dienstmanager für die meisten modernen Linux-Distributionen entwickelt und spielt eine entscheidende Rolle bei der Verwaltung von Diensten, Daemons und Prozessen. Obwohl leistungsstark und effizient, können von systemd verwaltete Dienste manchmal nicht starten, was zu Anwendungs-Ausfallzeiten oder Systeminstabilität führt. Die Diagnose dieser Fehler erfordert einen systematischen Ansatz, der die robusten Protokollierungs- und Introspektionsfunktionen von systemd nutzt.
Diese Anleitung bietet eine umfassende, Schritt-für-Schritt-Methodik zur Fehlerbehebung bei häufigen Startfehlern von systemd-Diensten. Wir behandeln alles von anfänglichen Statusprüfungen und tiefen Einblicken in Protokolle bis hin zur Überprüfung von Unit-Dateien und der Lösung komplexer Abhängigkeitsprobleme. Am Ende dieses Artikels verfügen Sie über das praktische Wissen und die Werkzeuge, um die meisten systemd-Dienstfehler effizient zu diagnostizieren und zu beheben und so sicherzustellen, dass Ihre Anwendungen und Dienste reibungslos laufen.
Die erste Verteidigungslinie: systemctl status
Wenn ein Dienst nicht startet, ist der allererste Befehl, den Sie ausführen sollten, systemctl status <Dienstname>. Dieser Befehl liefert eine Momentaufnahme des aktuellen Zustands des Dienstes, einschließlich, ob er aktiv und geladen ist, und, entscheidend, einen Ausschnitt seiner letzten Protokolle. Dies liefert oft genügend Informationen, um das Problem schnell zu identifizieren.
Nehmen wir an, Ihr Webanwendungsdienst, mywebapp.service, startet nicht:
systemctl status mywebapp.service
Beispiel für die Ausgabe-Interpretation:
● mywebapp.service - My Web Application
Loaded: loaded (/etc/systemd/system/mywebapp.service; enabled; vendor preset: disabled)
Active: failed (Result: exit-code) since Mon 2023-10-26 10:30:05 UTC; 10s ago
Process: 12345 ExecStart=/usr/local/bin/mywebapp-start.sh (code=exited, status=1/FAILURE)
Main PID: 12345 (code=exited, status=1/FAILURE)
CPU: 10ms
Oct 26 10:30:05 hostname systemd[1]: Started My Web Application.
Oct 26 10:30:05 hostname mywebapp-start.sh[12345]: Error: Port 8080 already in use
Oct 26 10:30:05 hostname systemd[1]: mywebapp.service: Main process exited, code=exited, status=1/FAILURE
Oct 26 10:30:05 hostname systemd[1]: mywebapp.service: Failed with result 'exit-code'.
Aus dieser Ausgabe können wir sofort erkennen:
* Der Dienst mywebapp.service ist failed (fehlgeschlagen).
* Er schlug mit Result: exit-code fehl, was bedeutet, dass der ExecStart-Befehl mit einem Status ungleich Null beendet wurde.
* Die Process-Zeile zeigt, dass der Befehl mywebapp-start.sh mit status=1/FAILURE fehlgeschlagen ist.
* Entscheidend ist, dass die Protokollzeilen anzeigen: Error: Port 8080 already in use. Dies ist ein klarer Hinweis auf das Problem.
Dieser Befehl ist Ihr erstes Diagnosetool, das oft direkt auf die Ursache hinweist oder den Bereich für die weitere Untersuchung eingrenzt.
Tiefgreifende Analyse mit journalctl
Während systemctl status eine schnelle Zusammenfassung liefert, ist journalctl Ihr Befehl für detaillierte Protokollierung. Er fragt das systemd-Journal ab, das Protokolle aus allen Teilen des Systems, einschließlich Diensten, sammelt.
Grundlegende Protokollprüfung
Um alle Protokolle für einen bestimmten Dienst anzuzeigen, einschließlich historischer Einträge:
journalctl -u mywebapp.service
Dies zeigt alle Protokolleinträge an, die mit mywebapp.service verknüpft sind. Wenn der Dienst wiederholt fehlschlägt, sehen Sie Einträge von jedem fehlgeschlagenen Versuch.
Filtern und zeitbasierte Abfragen
Um die Ergebnisse einzugrenzen, insbesondere nach einem kürzlichen Fehler, können Sie Flags wie --since und --priority verwenden:
- Protokolle seit einer bestimmten Zeit anzeigen:
bash journalctl -u mywebapp.service --since "10 minutes ago" journalctl -u mywebapp.service --since "2023-10-26 10:00:00" - Nur Fehlermeldungen oder höher anzeigen:
bash journalctl -u mywebapp.service -p err - Kombinieren Sie mit
-xefür erweiterte Erklärungen und ausführliche Ausgabe:
bash journalctl -u mywebapp.service -xe --since "5 minutes ago"
Dies ist unglaublich nützlich, dajournalctl -xezusätzlichen Kontext liefert, einschließlich Erklärungen für bestimmte Protokollmeldungen und Stack-Traces, falls verfügbar.
Protokollmeldungen verstehen
Suchen Sie nach Schlüsselwörtern wie Error, Failed, Warning oder anwendungsspezifischen Meldungen, die angeben, was schief gelaufen ist. Achten Sie auf Zeitstempel, um die Abfolge der Ereignisse zu verstehen, die zum Fehler geführt haben.
Tipp: Wenn das ExecStart-Skript Ihres Dienstes auf Standardausgabe oder Standardfehler ausgibt, werden diese Meldungen normalerweise von journalctl erfasst. Stellen Sie sicher, dass Ihre Skripte aussagekräftige Fehlermeldungen protokollieren.
Überprüfen der Unit-Datei: Der Bauplan Ihres Dienstes
Jeder systemd-Dienst wird durch eine Unit-Datei (z. B. mywebapp.service) definiert. Fehlkonfigurationen in dieser Datei sind eine häufige Ursache für Startfehler. Sie müssen verstehen, was der Dienst versucht zu tun.
Abrufen der Unit-Datei
Um die aktive Unit-Datei für Ihren Dienst anzuzeigen:
systemctl cat mywebapp.service
Dieser Befehl zeigt die exakte Unit-Datei an, die systemd verwendet, einschließlich aller Überschreibungen.
Wichtige zu prüfende Direktiven
Konzentrieren Sie sich auf den Abschnitt [Service] für ausführungsbezogene Probleme und [Unit] für Abhängigkeiten.
ExecStart: Dies ist der Befehl, den systemd ausführt, um Ihren Dienst zu starten. Überprüfen Sie, ob der Pfad korrekt ist und der Befehl selbst ausführbar ist und erfolgreich ausgeführt wird, wenn er manuell (z. B. als der angegebeneUser) aufgerufen wird.
ini ExecStart=/usr/local/bin/mywebapp-start.shType: Definiert den Starttyp des Prozesses. Gängige Typen sind:simple(Standard):ExecStartist der Hauptprozess.forking:ExecStartforkt einen Kindprozess, und der Elternprozess beendet sich. Systemd wartet, bis der Elternprozess beendet ist.oneshot:ExecStartläuft und beendet sich; systemd betrachtet den Dienst als aktiv, solange der Befehl läuft.notify: Der Dienst sendet eine Benachrichtigung an systemd, wenn er bereit ist.- Ein falscher
Typekann dazu führen, dass systemd einen Dienst für fehlgeschlagen hält, obwohl er tatsächlich gestartet ist, oder umgekehrt.
User/Group: Der Benutzer und die Gruppe, unter denen der Dienst ausgeführt wird. Berechtigungsprobleme entstehen oft, wenn der Dienst versucht, auf Dateien oder Ressourcen zuzugreifen, für die er unter diesem Benutzer keine Rechte hat.
ini User=mywebappuser Group=mywebappgroupWorkingDirectory: Das Verzeichnis, aus dem der Dienst ausgeführt wird. Relative Pfade inExecStartoder anderen Befehlen hängen davon ab.Restart: Definiert, wann der Dienst neu gestartet werden soll. Wenn aufon-failureoderalwaysgesetzt, könnte ein fehlerhafter Dienst ständig neu starten, was es schwieriger macht, den ursprünglichen Fehler zu erkennen.TimeoutStartSec/TimeoutStopSec: Wie lange systemd wartet, bis der Dienst startet oder stoppt. Wenn ein Dienst länger zum Initialisieren benötigt alsTimeoutStartSec, wird systemd ihn beenden und einen Fehler melden.
Häufige Probleme mit Unit-Dateien
- Falsche Pfade: Tippfehler in
ExecStartoder anderen Dateipfaden. - Fehlende
Environment-Variablen: Dienste benötigen oft spezifische Umgebungsvariablen (z. B.PATH), die in der sauberen Umgebung von systemd möglicherweise nicht vorhanden sind (siehe unten). - Berechtigungen: Der angegebene
Userhat keine Ausführungsberechtigung für das Skript oder Lese-/Schreibberechtigungen für notwendige Datendateien. - Syntaxfehler: Einfache Tippfehler in der Unit-Datei selbst.
ExecStart manuell testen:
Wechseln Sie zum Benutzer des Dienstes und versuchen Sie, den Befehl direkt auszuführen:
sudo -u mywebappuser /usr/local/bin/mywebapp-start.sh
Dies reproduziert oft den in journalctl sichtbaren Fehler direkt in Ihrem Terminal, was die Fehlersuche erleichtert.
Abhängigkeitsverwaltung: Wenn Dienste nicht alleine starten können
Dienste sind oft auf andere Dienste oder Systemkomponenten angewiesen, die aktiv sein müssen, bevor sie selbst starten können. Systemd verwendet die Direktiven Wants, Requires, After und Before, um diese Abhängigkeiten zu verwalten.
Abhängigkeiten identifizieren
Verwenden Sie systemctl list-dependencies <Dienstname>, um zu sehen, was ein Dienst explizit zum Ausführen benötigt oder wünscht.
systemctl list-dependencies mywebapp.service
Häufige Direktiven im Abschnitt [Unit]:
After=: Gibt an, dass dieser Dienst nach den gelisteten Units starten soll. Wenn die gelistete Unit fehlschlägt, wird dieser Dienst trotzdem versuchen zu starten (es sei denn,Requires=wird ebenfalls verwendet).Requires=: Gibt an, dass dieser Dienst die gelisteten Units benötigt. Wenn eine der erforderlichen Units nicht startet, wird dieser Dienst nicht starten.Wants=: Eine schwächere Form vonRequires=. Wenn eine gewünschte Unit fehlschlägt, wird dieser Dienst trotzdem versuchen zu starten.
Beispiel:
[Unit]
Description=My Web Application
After=network.target mysql.service
Requires=mysql.service
Hier startet mywebapp.service nur, nachdem network.target und mysql.service gestartet sind, und es benötigt, dass mysql.service erfolgreich ist. Wenn mysql.service fehlschlägt, startet mywebapp.service nicht.
Abhängigkeitskonflikte lösen
Wenn ein Dienst aufgrund eines Abhängigkeitsproblems fehlschlägt, zeigt journalctl normalerweise an, welche Abhängigkeit nicht erfüllt werden konnte. Es könnte beispielsweise Dependency failed for My Web Application gefolgt von Details zum Fehler von mysql.service anzeigen.
Schritte zur Behebung:
1. Überprüfen Sie den abhängigen Dienst: Führen Sie systemctl status <abhängiger_Dienst> (z. B. systemctl status mysql.service) und journalctl -u <abhängiger_Dienst> aus, um dessen Fehler zuerst zu beheben.
2. Überprüfen Sie die Direktiven After= und Requires=: Stellen Sie sicher, dass sie die gewünschte Startreihenfolge und Strenge korrekt widerspiegeln. Manchmal muss ein Dienst auf einen bestimmten Port warten, der geöffnet ist, nicht nur darauf, dass der Dienst aktiv ist. Für komplexe Fälle können systemd-socket-activate oder benutzerdefinierte ExecStartPre-Skripte nützlich sein.
Umgebungsvariablen und Pfade: Die versteckten Fallstricke
Systemd-Dienste laufen in einer sehr sauberen und minimalen Umgebung. Dies führt oft zu Problemen, bei denen Befehle, die in der Shell eines Benutzers perfekt funktionieren, fehlschlagen, wenn sie von systemd ausgeführt werden, weil wichtige Umgebungsvariablen (wie PATH) fehlen.
Systemds saubere Umgebung
Wenn systemd einen Dienst startet, erbt es nicht die vollständige Umgebung des Benutzers, der systemctl start initiiert hat. Die PATH-Variable zum Beispiel wird oft gekürzt, was bedeutet, dass Befehle wie python oder node möglicherweise nicht gefunden werden, wenn sie sich nicht an Standardorten wie /usr/bin oder /bin befinden.
Symptom: ExecStart=/usr/local/bin/myscript.sh schlägt fehl mit "