Systemd-Ziele erklärt: Boot-Zustände und Runlevel effektiv verwalten

Verstehen Sie systemd-Ziele, Runlevel-Äquivalente, Standard-Boot-Zustände, Isolieren, Rettungs- und Grafikmodi.

Systemd-Ziele erklärt: Boot-Zustände und Runlevel effektiv verwalten

Systemd-Ziele sind benannte Systemzustände. Ein Ziel kann einen normalen Server-Boot, einen grafischen Desktop, eine Rettungsshell, ein Herunterfahren oder eine benutzerdefinierte Gruppe von Diensten darstellen, die Sie gemeinsam starten möchten. Wenn Sie von älteren Linux-Systemen kommen, sind Ziele der systemd-Ersatz für die Teile von Runleveln, die tatsächlich genutzt wurden, aber sie sind flexibler, da sie auf Abhängigkeiten statt nur auf Zahlen basieren.

Normalerweise begegnen Ihnen Ziele, wenn ein Server in den falschen Modus bootet, ein Desktop-Display-Manager nicht startet oder ein Wiederherstellungsleitfaden Ihnen sagt, Sie sollen rescue.target eingeben. Die Kenntnis einiger Befehle macht solche Situationen viel weniger rätselhaft.

Die Entwicklung von Runleveln zu systemd-Zielen

Historisch gesehen verwendeten Linux-Systeme ein Konzept namens Runlevel, um den Betriebszustand des Systems während des Bootvorgangs und zur Laufzeit zu definieren. Ein Runlevel war ein numerischer Identifikator (0-6), der festlegte, welche Dienste gestartet oder gestoppt wurden. Beispielsweise bedeutete Runlevel 3 typischerweise einen Mehrbenutzer-Textmodus, während Runlevel 5 eine grafische Mehrbenutzer-Umgebung anzeigte. Dieses System war zwar funktional, hatte aber Einschränkungen:

  • Starrheit: Runlevel wurden oft auf eine feste oder distributionsspezifische Weise definiert, was die Anpassung der genauen Gruppe von Diensten, die für einen bestimmten Zustand aktiv sind, umständlich machte.
  • Implizite Abhängigkeiten: Abhängigkeiten zwischen Diensten wurden oft indirekt durch Runlevel-Zuweisungen verwaltet, was zu potenziellen Konflikten oder fehlenden Diensten führte.
  • Mangel an Granularität: Das numerische System mangelte an beschreibender Klarheit, was es schwieriger machte, den beabsichtigten Zustand des Systems zu verstehen.

Systemd-Ziele adressieren diese Einschränkungen, indem sie einen expliziteren, abhängigkeitsgesteuerten und beschreibenden Ansatz bieten. Anstelle abstrakter Zahlen haben Ziele aussagekräftige Namen (z.B. multi-user.target, graphical.target), die den beabsichtigten Systemzustand klar anzeigen. Abhängigkeiten werden explizit in Unit-Dateien definiert, was sicherstellt, dass alle notwendigen Komponenten in der richtigen Reihenfolge gestartet werden.

Die grobe Zuordnung sieht auf vielen systemd-Systemen wie folgt aus:

Traditionelles Runlevel Übliches systemd-Äquivalent Bedeutung
0 poweroff.target Herunterfahren und ausschalten
1 rescue.target Einzelbenutzer-Rettungsmodus
3 multi-user.target Mehrbenutzer-Text/Server-Modus
5 graphical.target Mehrbenutzermodus plus grafischer Anmeldung
6 reboot.target Neustart

Behandeln Sie dies als Übersetzungshilfe, nicht als Gesetz. Das Runlevel-Verhalten variierte zwischen den Distributionen, und systemd-Ziele können Beziehungen ausdrücken, die alte Runlevel nicht konnten.

Systemd-Ziele verstehen

Ein systemd-Ziel ist selbst ein Unit-Typ. Wenn eine Ziel-Unit aktiviert wird, versucht systemd, alle Units zu aktivieren, die als Abhängigkeiten in der Unit-Datei dieses Ziels aufgeführt sind. Dies erzeugt einen Kaskadeneffekt, der sicherstellt, dass alle notwendigen Dienste, Geräte und anderen Komponenten online gebracht werden, um den gewünschten Systemzustand zu erreichen.

Wesentliche Merkmale von systemd-Zielen:

  • Abhängigkeitsverwaltung: Ziele definieren, welche anderen Units aktiv sein müssen, damit das Ziel als erreicht gilt. Dies ist der Kern ihrer Leistungsfähigkeit.
  • Synchronisationspunkte: Sie fungieren als Synchronisationspunkte während des Bootvorgangs. Das System fährt erst mit der nächsten Stufe fort, wenn das aktuelle Ziel vollständig initialisiert ist.
  • Beschreibende Benennung: Ziele werden beschreibend benannt, was es einfach macht, den beabsichtigten Zustand des Systems zu verstehen (z.B. rescue.target, poweroff.target).

Ziele führen normalerweise selbst keinen langlebigen Code aus. Sie gruppieren andere Units. Sie können diese Gruppierung überprüfen mit:

systemctl list-dependencies multi-user.target
systemctl list-dependencies graphical.target

Dies ist eine gute Möglichkeit, die Frage zu beantworten: "Warum startet dieser Dienst beim Booten?" Wenn die Unit im Abhängigkeitsbaum für das Standardziel erscheint, wird sie irgendwo eingebunden.

Häufige systemd-Ziele

Systemd wird mit einer Reihe vordefinierter Ziele ausgeliefert, die gängige Systemzustände abdecken. Das Verständnis dieser Ziele ist der Schlüssel zur Verwaltung Ihres Systems.

multi-user.target

Dies ist eines der grundlegendsten Ziele. Es repräsentiert ein voll funktionsfähiges Mehrbenutzersystem mit aktiviertem Netzwerk, aber ohne grafischen Anmeldemanager oder Desktop-Umgebung. Dies ist typischerweise das Standardziel für Server.

  • Zweck: Bereitstellung einer stabilen Umgebung zum Ausführen von Diensten und Ermöglichen mehrerer Benutzer, sich über textbasierte Konsolen oder SSH anzumelden.
  • Abhängigkeiten: Enthält normalerweise Units für Netzwerk, Systemdienste und Konsolen-Anmeldeaufforderungen.

Für kopflose Server ist multi-user.target normalerweise die richtige Voreinstellung. Es bietet SSH und normale Dienste, ohne Ressourcen für einen Display-Manager zu verschwenden.

graphical.target

Dieses Ziel repräsentiert ein voll funktionsfähiges Mehrbenutzersystem mit einer grafischen Desktop-Umgebung, die für die Benutzerinteraktion bereit ist. Es ist typischerweise eine Abhängigkeit von multi-user.target und fügt die notwendigen Komponenten für eine grafische Sitzung hinzu.

  • Zweck: Starten eines grafischen Display-Managers (wie GDM, LightDM, SDDM) und der zugehörigen Desktop-Umgebung.
  • Abhängigkeiten: Zieht normalerweise das Verhalten von multi-user.target ein und fügt Units für einen Display-Manager und grafische Sitzungskomponenten hinzu.

Wenn ein Arbeitsplatz zu einem schwarzen Bildschirm bootet, SSH aber noch funktioniert, vergleichen Sie diese:

systemctl get-default
systemctl status display-manager.service
journalctl -u display-manager.service -b

Das Standardziel sagt Ihnen, was das System zu erreichen versuchte. Die Display-Manager-Protokolle sagen Ihnen, warum die grafische Schicht hochkam oder nicht.

rescue.target

Dieses Ziel bietet eine minimale Einzelbenutzer-Umgebung. Es wird hauptsächlich für Systemwartung und -wiederherstellung verwendet. Es bringt das Basissystem und eine Root-Shell hoch, startet aber typischerweise kein Netzwerk oder Mehrbenutzerdienste.

  • Zweck: Bereitstellung einer sicheren Umgebung für Systemadministratoren, um Wartungsaufgaben ohne Störungen durch andere Dienste durchzuführen.
  • Abhängigkeiten: Minimale Menge wesentlicher Systemkomponenten und eine Root-Shell. Netzwerk ist oft nicht verfügbar, es sei denn, Sie starten es manuell.

emergency.target

Dies ist noch minimaler als rescue.target. Es bringt das System auf ein einziges schreibgeschütztes Dateisystem und eine Root-Shell. Es ist für ernste Notfälle gedacht, in denen selbst grundlegende Dienste problematisch sein könnten.

  • Zweck: Für kritische Systemwiederherstellung, wenn selbst das rescue.target möglicherweise nicht geeignet ist.
  • Abhängigkeiten: Nur die wesentlichsten Systemkomponenten und eine Root-Shell. Das Root-Dateisystem kann je nach Fehler und Distribution schreibgeschützt eingehängt sein.

reboot.target, poweroff.target, halt.target

Dies sind spezielle Ziele, die zum Herunterfahren oder Neustarten des Systems verwendet werden. Wenn systemd eines dieser Ziele aktiviert, stoppt es alle laufenden Dienste und führt dann die angegebene Aktion aus (Neustarten, Ausschalten oder Anhalten).

  • Zweck: Graceful Herunterfahren oder Neustarten des Systems.
  • Abhängigkeiten: Sie hängen typischerweise von Diensten ab, die gestoppt werden müssen, bevor das System heruntergefahren werden kann.

Systemd-Ziele verwalten

Systemd bietet mehrere Befehlszeilenwerkzeuge zur Interaktion mit Zielen. Das primäre Werkzeug ist systemctl.

Aktuelle und Standardziele anzeigen

Um zu sehen, welches Ziel das System derzeit ausführt und auf welches Ziel es beim Booten standardmäßig zurückgreift, verwenden Sie:

systemctl status

Dieser Befehl liefert eine Fülle von Informationen, einschließlich des aktiven Ziels. Um speziell das Standardziel abzufragen:

systemctl get-default

Um alle verfügbaren Ziele anzuzeigen:

systemctl list-unit-files --type=target

Um aktive Ziel-Units anzuzeigen, verwenden Sie:

systemctl list-units --type=target

Der Unterschied ist derselbe wie bei Diensten: list-unit-files zeigt Zieldateien, die systemd kennt, während list-units Ziele zeigt, die derzeit im laufenden System geladen oder aktiv sind.

Das Standardziel ändern

Wenn Sie möchten, dass Ihr System standardmäßig in ein anderes Ziel bootet (z.B. von grafisch zu Mehrbenutzer oder umgekehrt), können Sie systemctl set-default verwenden:

Um das Standardziel auf grafisches Ziel zu setzen (üblich für Desktop-Systeme):

sudo systemctl set-default graphical.target

Um das Standardziel auf Mehrbenutzer-Ziel zu setzen (üblich für Server):

sudo systemctl set-default multi-user.target

Wichtig: Das Ändern des Standardziels wird erst beim nächsten Neustart wirksam.

Im Hintergrund ändert dies den Symlink default.target. Sie können ihn direkt überprüfen, wenn Sie ein defektes Boot-Image debuggen:

systemctl get-default
ls -l /etc/systemd/system/default.target

Zu einem Ziel wechseln (ohne Neustart)

Sie können das System sofort zu einem anderen Ziel wechseln, ohne neu zu starten. Dies ist nützlich zum Testen oder zum vorübergehenden Ändern des Systemzustands. Verwenden Sie den Befehl systemctl isolate:

Um zum grafischen Ziel zu wechseln:

sudo systemctl isolate graphical.target

Um zum Mehrbenutzer-Ziel zu wechseln:

sudo systemctl isolate multi-user.target

Vorsicht: systemctl isolate ist ein mächtiger Befehl. Das Isolieren zu einem Ziel wie rescue.target oder emergency.target wird die meisten laufenden Dienste stoppen. Stellen Sie sicher, dass Sie die Auswirkungen verstehen, bevor Sie es verwenden. Sie könnten die Netzwerkkonnektivität oder Ihre grafische Sitzung verlieren.

Seien Sie auf einem entfernten Server besonders vorsichtig mit isolate rescue.target oder isolate emergency.target. Sie könnten SSH verlieren und benötigen Konsolenzugriff über Ihren Cloud-Anbieter, Hypervisor oder die physische Maschine. Wenn Sie nur den grafischen Desktop auf einem Arbeitsplatz stoppen müssen, ist das Isolieren zu multi-user.target weniger drastisch, als direkt in den Rettungsmodus zu springen.

Wie Ziele mit Unit-Dateien zusammenhängen

Ziele werden als Unit-Dateien implementiert, die sich typischerweise in /usr/lib/systemd/system/ oder /etc/systemd/system/ befinden. Eine Ziel-Unit-Datei (z.B. graphical.target) spezifiziert Abhängigkeiten von anderen Units, einschließlich anderer Ziele und Dienste.

Eine typische graphical.target-Unit-Datei könnte wie folgt aussehen (vereinfacht):

[Unit]
Description=Graphical multi-user system
Documentation=man:systemd.special(7)
# This target is intended to be a prerequisite for the graphical login manager.
# It's the target that the system will boot into if not otherwise specified.
Wants=display-manager.service
Before=shutdown.target

[Install]
Alias=default.target

Hier:

  • Wants=display-manager.service: Zeigt an, dass display-manager.service (der eigentliche Anmeldemanager wie GDM oder LightDM) nach Möglichkeit gestartet werden sollte. Dies ist eine schwächere Abhängigkeit als Requires=.
  • Before=shutdown.target: Stellt sicher, dass die grafische Umgebung gestoppt wird, bevor das System in den Herunterfahrprozess eintritt.
  • Alias=default.target: Dies bewirkt, dass graphical.target als Standard fungiert, wenn default.target darauf verlinkt ist (was bei Desktop-Systemen normalerweise der Fall ist).

Benutzerdefinierte Ziele erstellen

Obwohl für den täglichen Gebrauch weniger üblich, können Sie Ihre eigenen benutzerdefinierten Ziele erstellen, um spezifische Systemzustände mit einzigartigen Dienstgruppen zu definieren.

Schritte zum Erstellen eines benutzerdefinierten Ziels:

  1. Erstellen Sie eine .target-Unit-Datei: Platzieren Sie sie in /etc/systemd/system/ (z.B. my-custom.target).
    [Unit]
    Description=My Custom Target
    
    [Install]
    WantedBy=multi-user.target # Or another appropriate target
    
  2. Erstellen Sie .service- oder andere Unit-Dateien: Definieren Sie die Dienste und anderen Units, die für Ihr benutzerdefiniertes Ziel aktiv sein sollen.
  3. Fügen Sie Abhängigkeiten hinzu: Verwenden Sie in der Unit-Datei Ihres benutzerdefinierten Ziels Requires= oder Wants=, um anzugeben, welche Units gestartet werden müssen oder sollen.
    [Unit]
    Description=My Custom Target
    Wants=service1.service
    Wants=service2.service
    After=service1.service service2.service
    
    [Install]
    WantedBy=multi-user.target
    
  4. Laden Sie systemd neu:
    
    

sudo systemctl daemon-reload 5. **Aktivieren/Starten Sie Ihr Ziel:** bash sudo systemctl start my-custom.target # Or to make it bootable sudo systemctl enable my-custom.target ```

Anwendungsfall: Stellen Sie sich eine Entwicklungsumgebung vor, in der Sie spezifische Datenbank- und Anwendungsserver benötigen. Sie könnten ein dev-env.target erstellen, das diese Dienste startet.

Benutzerdefinierte Ziele sind auch für geräteähnliche Systeme nützlich. Beispielsweise könnte eine Kiosk-Maschine ein Ziel haben, das Netzwerk, einen Browser, einen lokalen Watchdog und einen Protokollierungsagenten startet, aber nicht den Rest einer normalen Desktop-Sitzung. Ein Lab-Server könnte separate Ziele für einen Test-Stack und einen Demo-Stack haben, sodass Betreiber eine bekannte Gruppe von Diensten gemeinsam starten können.

Best Practices und Tipps

  • Verstehen Sie das Standardziel: Kennen Sie das Standardziel Ihres Systems (graphical.target oder multi-user.target), da es das anfängliche Boot-Erlebnis bestimmt.
  • Verwenden Sie isolate mit Vorsicht: Seien Sie vorsichtig bei der Verwendung von systemctl isolate, insbesondere auf Produktionssystemen, da es laufende Dienste stören kann.
  • Überprüfen Sie Abhängigkeiten: Wenn ein Dienst nicht startet, untersuchen Sie die Abhängigkeiten des Ziels, mit dem er verbunden ist, mit systemctl list-dependencies <Zielname>.
  • Server vs. Desktop: Auf Servern wird multi-user.target fast immer aus Sicherheits- und Ressourceneffizienzgründen bevorzugt. Auf Desktops ist graphical.target Standard.
  • Systemwartung: Für Aufgaben, die minimale Störungen erfordern, ist rescue.target nützlich. Für kritische Wiederherstellung steht emergency.target zur Verfügung.

Eine praktische Denkweise über Ziele

Für die meisten Verwaltungsarbeiten benötigen Sie nur ein kurzes mentales Modell:

systemctl get-default
systemctl set-default multi-user.target
systemctl isolate graphical.target
systemctl list-dependencies graphical.target

get-default sagt Ihnen, wohin die Maschine booten soll. set-default ändert den nächsten Bootvorgang. isolate ändert den aktuellen Zustand und kann Dienste außerhalb dieses Zustands stoppen. list-dependencies erklärt, was ein Ziel einbindet.

Ziele sind nicht nur umbenannte Runlevel. Sie sind Abhängigkeitsgruppen. Sobald Sie sie so behandeln, werden Boot-Probleme leichter zu durchschauen: Finden Sie das Ziel, das das System zu erreichen versuchte, überprüfen Sie die Dienste, die es wollte, und beheben Sie dann die Unit oder Abhängigkeit, die fehlgeschlagen ist.