- 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
nitroctlund 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
tmpfsoder 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/ttysausgeführt werden - Mit musl libc lassen sich ultrakleine statische Binärdateien erstellen
Dienstverwaltung
-
Jedes Dienstverzeichnis (standardmäßig unter
/etc/nitro) kann die folgenden Dateien enthaltensetup: (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 behandeltfinish: (optionales) Skript, das nach dem Ende vonrunausgeführt wird; Exit-Status und Signalwert werden als Argumente übergebenlog: symbolischer Link auf ein anderes Dienstverzeichnis; die Ausgabe vonrunwird 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 vonrun-Skripten nützlich
Besondere Dienste
LOG: Standarddienst zum Protokollieren aller Dienste ohnelog-LinkSYS:SYS/setupwird vor dem Start aller Dienste ausgeführt und kann für geordnete Startabläufe verwendet werdenSYS/finish: wird vor dem Eintritt in die globale Beendigungsphase ausgeführtSYS/final: wird ausgeführt, nachdem alle Prozesse beendet wurdenSYS/fatal: wird bei fatalen Fehlern statt eines Beendens ausgeführt, falls vorhandenSYS/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 Befehlnitroctldirekt angesprochen werden - Der Parameter nach
@wird als erstes Argument an jedes Skript übergeben- Beispiel: Wenn symbolische Links
agetty@/runundagetty@tty1existieren, wirdagetty@/run tty1ausgeführt - Mit
nitroctl up agetty@tty2kannagetty@/run tty2ausgeführt werden, unabhängig davon, ob das Verzeichnis existiert
- Beispiel: Wenn symbolische Links
Betriebsmodi
- Der gesamte Lebenszyklus besteht aus drei Phasen: Booten, Dienstausführung (Supervision) und Beenden
- Booten: Wenn der besondere Dienst
SYSexistiert, wird absetupausgeführt; danach werden alle nicht aufdowngesetzten Dienste gestartet - Wenn ein Dienst endet, wird er neu gestartet; war der letzte Neustart jedoch sehr kurz zuvor, wird 2 Sekunden gewartet
- Mit
nitroctl RebootoderShutdownkann ein Beendigungssignal ausgelöst werden- Dann folgt
SYS/finish→ SIGTERM an alle Dienste (maximal 7 Sekunden warten) → SIGKILL →SYS/final→ Beendigungssequenz
- Dann folgt
- Für Container oder unprivilegierte Supervisoren werden nur die Prozesse beendet
- Booten: Wenn der besondere Dienst
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
/devund/runwerden bei Bedarf gemountet; weitere Abläufe werden inSYS/setupbehandelt- 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
/runmuss 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/ttyskann nitro von FreeBSD init überwacht werden/etc/nitro "/usr/local/sbin/nitro" "" on
Autor
- Leah Neukirchen leah@vuxu.org
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.