2 Punkte von GN⁺ 2025-08-24 | Noch keine Kommentare. | Auf WhatsApp teilen
  • Nitro ist ein ultrakompakter Prozess-Supervisor und Init-System, das sich für Embedded-Systeme, Server, Desktops und Container gleichermaßen eignet
  • Es speichert den Systemzustand ausschließlich im RAM und funktioniert daher problemlos auch mit schreibgeschützten Dateisystemen; zugleich bietet es ein schnelles und effizientes ereignisbasiertes Design
  • Die Konfiguration erfolgt über eine einfache skriptbasierte Verzeichnisstruktur, sodass sich Dienste ohne komplexe Konfigurationsdateien oder zusätzliche Build-Schritte verwalten lassen
  • Es unterstützt parametrisierte Dienste, robuste Neustarts sowie zuverlässiges Logging pro Dienst und bietet damit für Container- und Embedded-Umgebungen optimierte Funktionen
  • Mit Remote-Steuerung über das Tool nitroctl und signalbasierter Ablaufsteuerung gewährleistet es hohe Flexibilität und Kontrolle

Überblick

Nitro ist ein ultrakompakter Prozess-Supervisor, der unter Linux auch als pid 1 verwendet werden kann

Wichtige Einsatzbereiche sind:

  • Init für Linux-Maschinen verschiedenster Art, etwa Embedded, Desktop und Server
  • Init für Linux-initramfs
  • Init für Container-Umgebungen wie Docker/Podman/LXC/Kubernetes
  • Ein Supervisions-Daemon für POSIX-Systeme, der ohne Privilegien läuft

Die Konfiguration verwendet eine verzeichnisbasierte Skriptstruktur; der Standardpfad ist /etc/nitro

Anforderungen

  • Unterstützung für Unix-Sockets im Kernel erforderlich
  • tmpfs oder ein beschreibbares /run-Verzeichnis erforderlich

Vorteile gegenüber anderen Systemen

  • Alle Statusinformationen bleiben ausschließlich im RAM, sodass es auch auf schreibgeschützten Root-Dateisystemen ohne besondere Tricks funktioniert
  • Ereignisbasiertes Arbeiten ohne Polling sorgt für Effizienz
  • Keine dynamische Speicherallokation zur Laufzeit
  • Datei-Deskriptoren werden nicht unbegrenzt verbraucht
  • Es wird nur eine in sich geschlossene Binärdatei benötigt (optional zusätzlich eine Steuer-Binärdatei)
  • Keine Umwandlung oder Kompilierung von Konfigurationsdateien nötig; ein Dienst ist einfach ein Verzeichnis mit Skripten
  • Unterstützung für Dienst-Neustarts und Logging-Ketten
  • Funktioniert auch dann korrekt, wenn die Systemuhr nicht exakt ist
  • Kann unter FreeBSD über /etc/ttys ausgeführt werden
  • Mit musl libc lassen sich ultrakleine statische Binärdateien erstellen

Dienstverwaltung

  • Jedes Dienstverzeichnis (standardmäßig unter /etc/nitro) kann die folgenden Dateien enthalten

    • setup: (optionales) Skript, das vor dem Start des Dienstes ausgeführt wird; der Dienst startet nur bei erfolgreichem Ende (0)
    • run: Skript für den eigentlichen Dienstbetrieb; solange es nicht endet, gilt der Dienst als aktiv; falls nicht implementiert, wird der Dienst als One-Shot-Dienst behandelt
    • finish: (optionales) Skript, das nach dem Ende von run ausgeführt wird; Exit-Status und Signalwert werden als Argumente übergeben
    • log: symbolischer Link auf ein anderes Dienstverzeichnis; die Ausgabe von run wird an die Eingabe dieses Dienstes weitergeleitet (für Logging-Ketten nutzbar)
    • down: wenn diese Datei existiert, startet nitro diesen Dienst standardmäßig nicht
    • Endet der Verzeichnisname auf @, wird er ignoriert und kann als parametrisierter Dienst verwendet werden
    • Dienstnamen müssen kürzer als 64 Zeichen sein und dürfen kein /, , oder Zeilenumbrüche enthalten
  • Das chpst-Utility von runit ist beim Schreiben von run-Skripten nützlich

Besondere Dienste

  • LOG: Standarddienst zum Protokollieren aller Dienste ohne log-Link
  • SYS: SYS/setup wird vor dem Start aller Dienste ausgeführt und kann für geordnete Startabläufe verwendet werden
    • SYS/finish: wird vor dem Eintritt in die globale Beendigungsphase ausgeführt
    • SYS/final: wird ausgeführt, nachdem alle Prozesse beendet wurden
    • SYS/fatal: wird bei fatalen Fehlern statt eines Beendens ausgeführt, falls vorhanden
    • SYS/reincarnate: wird statt eines Shutdowns ausgeführt und kann z. B. für eine Re-Implementierung von initramfs genutzt werden

Parametrisierte Dienste

  • Dienstverzeichnisse, die auf @ enden, werden von nitro ignoriert, können aber per symbolischem Link oder über den Befehl nitroctl direkt angesprochen werden
  • Der Parameter nach @ wird als erstes Argument an jedes Skript übergeben
    • Beispiel: Wenn symbolische Links agetty@/run und agetty@tty1 existieren, wird agetty@/run tty1 ausgeführt
    • Mit nitroctl up agetty@tty2 kann agetty@/run tty2 ausgeführt werden, unabhängig davon, ob das Verzeichnis existiert

Betriebsmodi

  • Der gesamte Lebenszyklus besteht aus drei Phasen: Booten, Dienstausführung (Supervision) und Beenden
    • Booten: Wenn der besondere Dienst SYS existiert, wird ab setup ausgeführt; danach werden alle nicht auf down gesetzten Dienste gestartet
    • Wenn ein Dienst endet, wird er neu gestartet; war der letzte Neustart jedoch sehr kurz zuvor, wird 2 Sekunden gewartet
    • Mit nitroctl Reboot oder Shutdown kann ein Beendigungssignal ausgelöst werden
      • Dann folgt SYS/finish → SIGTERM an alle Dienste (maximal 7 Sekunden warten) → SIGKILL → SYS/final → Beendigungssequenz
    • Für Container oder unprivilegierte Supervisoren werden nur die Prozesse beendet

Steuerung mit nitroctl

  • Das CLI-Tool nitroctl ermöglicht die Fernsteuerung von nitro

Beispiele für Befehle:

  • list: Ausgabe von Dienstliste, Status, PID, Uptime und letztem Exit-Status
  • up/down/start/stop/restart: Dienste starten, anhalten, neu starten usw.
  • Signale senden: p(SIGSTOP), c(SIGCONT), h(SIGHUP), a(SIGALRM), i(SIGINT), q(SIGQUIT), 1(SIGUSR1), 2(SIGUSR2), t(SIGTERM), k(SIGKILL)
  • pidof: Ausgabe der PID des angegebenen Dienstes
  • rescan: Dienstverzeichnisse neu einlesen und hinzugefügte bzw. entfernte Dienste übernehmen
  • Shutdown/Reboot: gesamtes System herunterfahren bzw. neu starten

Steuerung über Signale

  • Der nitro-Prozess kann auch durch direkt gesendete Signale gesteuert werden
    • SIGHUP: Dienste neu einlesen (rescan)
    • SIGINT: Neustart
    • SIGTERM: Beenden (wenn nitro nicht pid 1 ist)

Nitro als Init unter Linux

  • Nitro ist eine in sich geschlossene Binärdatei und kann unter Linux direkt als pid 1 booten
  • /dev und /run werden bei Bedarf gemountet; weitere Abläufe werden in SYS/setup behandelt
  • Ctrl-Alt-Del-Ereignisse lösen einen geordneten Neustart aus

Verwendung von Nitro als Init in Docker-Containern

  • Nitro kann statisch gebaut und einfach in Container eingebunden werden
  • /run muss im Container vorhanden sein, damit der Standardpfad für den Socket verwendet werden kann
  • Wenn der Kontroll-Socket per Bind-Mount eingebunden wird, ist eine externe Fernsteuerung mit nitroctl möglich

Nitro unter FreeBSD

  • Durch Hinzufügen der folgenden Zeile in /etc/ttys kann nitro von FreeBSD init überwacht werden
    /etc/nitro "/usr/local/sbin/nitro" "" on
    

Autor

Danksagung

  • Entwickelt auf Grundlage einer detaillierten Analyse bestehender Prozess-Supervisionssysteme wie daemontools, freedt, runit, perp und s6

Lizenz

  • 0BSD-Lizenz (Details siehe Datei LICENSE)

Noch keine Kommentare.

Noch keine Kommentare.