DAEMON(7) | daemon | DAEMON(7) |
BEZEICHNUNG
daemon - Schreiben und Paketieren von System-Daemons
BESCHREIBUNG
Ein Daemon ist ein Diensteprozess, der im Hintergrund läuft und das System beaufsichtigt oder Funktionalitäten für andere Prozesse bereitstellt. Traditionell werden Daemons so implementiert, dass sie einem ursprünglich aus SysV-Unix stammenden Schema folgen. Moderne Daemons sollten einem einfacheren, aber dennoch leistungsfähigeren Schema folgen (hier »neuartige« Daemons genannt), wie es von systemd(1) implementiert wird. Diese Handbuchseite deckt beide Schemata ab und enthält insbesondere Empfehlungen für Daemons, die im Systemd-Init-System aufgenommen werden sollen.
SysV-Daemons
Wenn ein traditioneller SysV-Daemon startet, sollte er die folgenden Schritte als Teil seiner Initialisierung ausführen. Beachten Sie, dass diese Schritte von neuartigen Daemons (siehe unten) nicht benötigt werden. Sie sollten daher nur implementiert werden, wenn die Kompatibilität zu SysV essenziell ist.
Die BSD-Funktion daemon() sollte nicht verwandt werden, da sie nur eine Teilmenge dieser Schritte implementiert.
Ein Daemon, der Kompatibilität mit SysV-Systemen bereitstellen muss, sollte das oben dargestellte Schema implementieren. Es wird allerdings empfohlen, dieses Verhalten über eine Befehlszeilenoption optional und konfigurierbar zu gestalten, um die Fehlersuche zu erleichtern und um die Integration in Systeme, die Systemd verwenden, zu erleichtern.
Neuartige Daemons
Moderne Dienste für Linux sollten als neuartige Daemons implementiert werden. Dies erleichtert die Beaufsichtigung und Steuerung zur Laufzeit und vereinfacht ihre Implementierung.
Zur Entwicklung eines neuartigen Daemons muss keiner der für SysV-Daemons empfohlenen Initialisierungsschritte implementiert werden. Bei neuartigen Init-Systemen wie Systemd sind diese alle redundant. Da einige dieser Schritte sogar die Prozessüberwachung, Dateideskriptorweitergabe und andere Funktionalitäten des Diensteverwalters stören, wird empfohlen, sie nicht auszuführen, wenn sie als neuartiger Dienst ausgeführt laufen.
Beachten Sie, dass neuartige Init-Systeme die Ausführung eines Daemon-Prozesses in einem sauberen Prozesskontext garantieren: Es wird garantiert, dass der Umgebungsblock bereinigt ist, dass Signal-Handler und -Masken zurückgesetzt sind und dass kein übrig gebliebener Dateideskriptor weitergegeben wird. Daemons werden in ihrer eigenen Sitzung ausgeführt, wobei die Standardeingabe mit /dev/null und die Standardausgabe/Standardfehlerausgabe mit dem Protokollierungsdienst systemd-journald.service(8) verbunden ist, außer dies ist anders konfiguriert. Die Umask ist zurückgesetzt.
Es wird empfohlen, dass neuartige Daemons folgendes implementieren:
Diese Empfehlungen sind ähnlich zu, aber nicht identisch mit den Apple-MacOS-X-Daemon-Anforderungen[2].
AKTIVIERUNG
Neuartige Init-Systeme stellen eine Reihe von zusätzlichen Mechanismen bereit, um Dienste zu aktivieren. Details dazu weiter unten. Es ist typisch, dass Dienste konfiguriert wurden, über mehr als einen Mechanismus gleichzeitig aktiviert zu werden. Beispielsweise könnte in einem Systemd-System bluetoothd.service aktiviert werden, wenn eine Bluetooth-Hardware eingesteckt wird oder wenn eine Anwendung mittels D-Bus auf seine Programmierschnittstelle zugreift. Oder ein Drucker-Server-Daemon könnte aktiviert werden, wenn Daten auf einem IPP-Port ankommen oder wenn ein Drucker eingesteckt wird oder wenn eine Datei im Drucker-Spool-Verzeichnis in die Warteschlange kommt. Selbst für Dienste, die dazu gedacht sind, beim Systemstart bedingungslos zu starten, ist es eine gute Idee, einige der unten dargestellten verschiedenen Aktivierungsschemata zu implementieren, um die Parallelisierung zu maximieren. Falls ein Daemon einen D-Bus-Dienst implementiert oder an einem Socket auf Anfragen wartet, erlaubt die Implementierung des kompletten Bus- und Socket-Aktivierungsschematas das Starten des Daemons mit seinen Clients parallel durchzuführen (womit der Systemstart beschleunigt wird), da bereits alle Kommunikationskanäle etabliert sind und keine Anfrage verloren geht, da Client-Anfragen vom Bus-System in Warteschlangen gestellt werden (im Falle von D-Bus) oder durch den Kernel (im Falle von Sockets), bis die Aktivierung abgeschlossen ist.
Aktivierung beim Systemstart
Daemons der alten Art werden typischerweise exklusiv beim Systemstart (oder manuell durch den Systemadministrator) mittels SysV-Init-Skripten aktiviert, wie dies in der LSB Linux Standard Base Kern-Spezifikation[1] dargestellt ist. Diese Methode wird universell auf Linux-Init-Systemen unterstützt, sowohl bei denen der alten Art als auch bei neuartigen. Unter anderen Problemen haben die SysV-Init-Skripte den Nachteil, Shell-Skripte im Systemstartprozess zu involvieren. Neuartige Init-Systeme verwenden im Allgemeinen aktualisierte Versionen der Aktivierung, sowohl während des Systemstarts als auch während der Laufzeit und verwenden minimalere Dienstebeschreibungsdateien.
Falls der Entwickler oder Administrator in Systemd sicherstellen möchte, dass ein Dienst oder eine andere Unit automatisch beim Systemstart aktiviert ist, wird empfohlen, einen Symlink auf die Unit-Datei im Verzeichnis .wants/ von entweder multi-user.target oder graphical.target, die normalerweise als Systemstartziele beim Systemstart verwandt werden, zu legen. Siehe systemd.unit(5) für Details über die Verzeichnisse .wants/ und systemd.special(7) für Details über die zwei Systemstartziele.
Socket-basierte Aktivierung
Um die Parallelisierung und Robustheit zu maximieren und die Konfiguration und Entwicklung zu vereinfachen, wird für alle neuartigen Daemons empfohlen, die über Warten an Sockets kommunizieren, eine Socket-basierte Aktivierung zu verwenden. In einem Socket-basierten Aktivierungsschema wird die Erstellung und das Binden des Sockets, an dem gewartet werden soll, als primären Kommunikationskanal von Daemons mit lokalen (und manchmal fernen) Clients aus dem Daemon-Code in den Diensteverwalter verschoben. Basierend auf einer Daemon-basierten Konfiguration installiert der Diensteverwalter die Sockets und gibt sie an die erstellten Prozesse, sobald der respektive Daemon gestartet wird. Optional kann die Aktivierung des Dienstes verzögert werden, bis der erste eingehende Verkehr auf dem Socket eintrifft, um eine bedarfsgesteuerte Aktivierung von Daemons zu realisieren. Allerdings ist der Hauptvorteil dieses Schemas, dass alle Anbieter und Konsumenten des Sockets parallel gestartet werden können, sobald alle Sockets etabliert sind. Zusätzlich können Daemons neugestartet werden und dabei nur eine minimale Anzahl an Client-Transaktionen verlieren oder sogar überhaupt keine Client-Anfrage (Letzteres stimmt insbesondere für zustandslose Protokolle wie DNS oder Syslog), da das Socket während des Neustarts angebunden und zugreifbar verbleibt und alle Anfragen in einer Warteschlange verbleiben, während der Daemon sie nicht verarbeiten kann.
Neuartige Daemons, die Socket-Aktivierung unterstützen, müssen in der Lage sein, Sockets vom Diensteverwalter zu erhalten, statt sie selbst zu erstellen und sich daran zu binden. Für Details über die Programmierschnittstellen für dieses von Systemd bereitgestellte Schema, siehe sd_listen_fds(3) und sd-daemon(3). Für Details über die Portierung bestehender Daemons zu Socket-basierter Aktivierung, siehe unten. Mit minimalem Einsatz ist es möglich, Socket-basierte Aktivierung zusätzlich zu traditioneller interner Socket-Erstellung in der gleichen Codebasis zu erstellen, um sowohl neuartige als auch Init-Systeme der alten Art im gleichen Daemon-Programm zu unterstützen.
Systemd implementiert Socket-basierte Aktivierung mittels .socket-Units, die in systemd.socket(5) beschrieben sind. Wenn Socket-Units für Socket-basierte Aktivierung konfiguriert werden, ist es wesentlich, dass alle Sockets, bei denen auf Anfragen gewartet wird, durch eine spezielle Ziel-Unit sockets.target hereingezogen werden. Es wird empfohlen, eine Anweisung WantedBy=sockets.target in den Abschnitt »[Install]« zu setzen, um eine solche Abhängigkeit automatisch bei der Installation einer Socket-Unit hinzuzufügen. Die notwendigen Ordnungs-Abhängigkeiten werden für alle Socket-Units implizit erstellt, falls DefaultDependencies=no nicht gesetzt ist. Für weitere Informationen über sockets.target, siehe systemd.special(7). Es ist nicht notwendig oder empfohlen, zusätzliche Abhängigkeiten auf Socket-Units abzulegen (zum Beispiel von multi-user.target oder ähnlichem), wenn eine in sockets.target installiert ist.
Bus-basierte Aktivierung
Wenn das D-Bus-IPC-System für die Kommunikation mit Clients verwandt wird, sollten neuartige Daemons Bus-Aktivierung verwenden, so dass sie automatisch aktiviert werden, wenn eine Client-Anwendung auf ihre IPC-Schnittstelle zugreift. Dies wird in D-Bus-Dienste-Dateien (die nicht mit Systemds Dienste-Unit-Dateien durcheinandergebracht werden dürfen) konfiguriert. Um sicherzustellen, dass D-Bus Systemd verwendet, um den Daemon zu starten und zu verwalten, verwenden Sie die Anweisung SystemdService= in diesen Dienste-Dateien, um den passenden Systemd-Dienst für einen D-Bus-Dienst zu konfigurieren. Stellen Sie beispielsweise für einen D-Bus-Dienst, dessen D-Bus-Aktivierungsdatei org.freedesktop.RealtimeKit.service heißt, sicher, dass SystemdService=rtkit-daemon.service in dieser Datei gesetzt ist, um ihn an den Systemd-Dienst rtkit-daemon.service zu binden. Dies wird benötigt, um sicherzustellen, dass der Daemon ohne Ressourcenwettläufe gestartet wird, wenn er über mehrere Mechanismen simultan aktiviert wird.
Geräte-basierte Aktivierung
Oft sollen Daemons, die einen besonderen Hardwaretyp verwalten, nur aktiviert werden, wenn die Hardware der entsprechenden Art eingesteckt oder andernfalls verfügbar gemacht wird. In einem neuartigen Init-System ist es möglich, die Aktivierung an Hardware-Einsteck-/Aussteck-Ereignisse zu binden. In Systemd können Kernel-Geräte, die in dem Gerätebaum sysfs/udev auftauchen, als Units offengelegt werden, falls sie mit der Zeichenkette »systemd« markiert sind. Wie andere Arten von Units können sie dann andere Units bei der Aktivierung (z.B. beim Einstecken) hereinziehen, und daher Geräte-basierte Aktivierung implementieren. Systemd-Abhängigkeiten können in der Udev-Datenbank mittels der Eigenschaft SYSTEMD_WANTS= kodiert werden. Siehe systemd.device(5) für Details. Oft ist es schöner, einen Dienst von Geräten nur indirekt über dedizierte Ziele hereinzuziehen. Beispiel: Statt bluetoothd.service von alle den verschiedenen Bluetooth-Dongles und anderen verfügbaren Hardwaren hereinzuziehen, ziehen Sie von ihnen bluetooth.target herein und dann bluetoothd.service von diesem Ziel. Dies stellt eine nettere Abstraktion bereit und ermöglicht Administratoren die Option, bluetoothd.service über einen Symlink bluetooth.target.wants/ uniform mit einem Befehl der Art enable von systemctl(1) zu steuern, statt den Udev-Regelsatz zu bearbeiten.
Pfadbasierte Aktivierung
Oft können Laufzeit-Daemons, die Spool-Dateien oder -Verzeichnisse (wie bei einem Drucksystem) verarbeiten, verzögert werden, bis diese Dateisystemobjekte den Zustand ändern oder nicht mehr leer sind. Neuartige Init-Systeme stellen einen Weg bereit, die Diensteaktivierung an Dateisystemänderungen zu binden. Systemd implementiert dieses Schema mittels in .path-Units konfigurierter pfadbasierter Aktivierung, wie in systemd.path(5) skizziert.
Timer-basierte Aktivierung
Einige Daemons, die Aufräumaufgaben erledigen, die regelmäßig ausgeführt werden sollen, ziehen aus Timer-basierter Aktivierung einen Nutzen. In Systemd ist dies mittels .timer-Units implementiert, wie in systemd.timer(5) beschrieben.
Andere Formen der Aktivierung
Es wurden andere Formen der Aktivierung vorgeschlagen und in einigen Systemen implementiert. Allerdings gibt es oft einfachere und bessere Alternativen oder sie können als Kombination der obigen Schemata zusammengestellt werden. Beispiel: Manchmal erscheint es nützlich, Daemons oder .socket-Units zu starten, wenn eine bestimmte IP-Adresse an einer Netzwerkschnittstelle konfiguriert ist, da Netzwerk-Sockets an diese Adresse gebunden werden sollen. Eine Alternative zur Implementierung hiervon ist die Verwendung der Socket-Option IP_FREEBIND/IPV6_FREEBIND von Linux, die mittels FreeBind=yes in Systemd-Socket-Dateien erreichbar ist (siehe systemd.socket(5) für Details). Diese Option erlaubt Sockets, wenn sie aktiviert ist, an nichtlokale, nichtkonfigurierte IP-Adressen gebunden zu werden und erlaubt damit Anbindungen an bestimmte IP-Adressen, bevor diese tatsächlich verfügbar werden; dies macht eine solche explizite Abhängigkeit auf die konfigurierte Adresse redundant. Ein anderer oft vorgeschlagener Auslöser für Dienste-Aktivierung ist niedrige Systemlast. Auch hier könnte allerdings ein überzeugender Ansatz sein, die Funktionalitäten des Betriebssystems korrekt zu benutzen, insbesondere des CPU- oder E/A-Schedulers von Linux. Anstatt Aufträge vom Anwenderbereich, basierend auf der Überwachung des Betriebssystem-Schedulers, einzuplanen, ist es empfehlenswert, die Einplanung von Prozessen dem Betriebssystem-Scheduler selbst zu überlassen. Systemd stellt einen feingranularen Zugriff auf die CPU- und E/A-Scheduler bereit. Falls ein vom Diensteverwalter ausgeführter Prozess den Umfang der für andere Prozesse verfügbaren CPU- oder E/A-Bandbreite nicht negativ beeinflussen soll, sollte er mit CPUSchedulingPolicy=idle und/oder IOSchedulingClass=idle konfiguriert werden. Optional kann dies mit Timer-basierter Aktivierung kombiniert werden, um Hintergrund-Aufträge während der Laufzeit und mit minimalen Auswirkungen auf das System einzuplanen und ihn aus der Systemstartphase selbst zu entfernen.
INTEGRATION MIT SYSTEMD
Schreiben von Systemd-Unit-Dateien
Beim Schreiben von Systemd-Unit-Dateien wird empfohlen, die folgenden Vorschläge zu berücksichtigen:
Systemd-Dienstedateien installieren
Zum Bauinstallationszeitpunkt (d.h. make install während des Paketbaus) wird empfohlen, dass Pakete ihre Systemd-Unit-Dateien im Verzeichnis, das von pkg-config systemd --variable=systemdsystemunitdir (für Systemdienste) oder pkg-config systemd --variable=systemduserunitdir (für Benutzerdienste) zurückgeliefert wird, zu installieren. Damit wird der Dienst im System für explizite Anfragen verfügbar gemacht, aber nicht beim Systemstart automatisch aktiviert. Optional sollten während der Paketinstallation (z.B. rpm -i durch den Administrator) Symlinks in den Systemd-Konfigurationsverzeichnissen mit dem Befehl enable des Werkzeuges systemctl(1) erstellt werden, um sie beim Systemstart automatisch zu aktivieren.
Für Pakete, die autoconf(1) verwenden, wird empfohlen, einen Configure-Skript-Auszug wie den nachfolgenden zu verwenden, um den Unit-Installationspfad während der Quellkonfiguration zu ermitteln:
PKG_PROG_PKG_CONFIG() AC_ARG_WITH([systemdsystemunitdir], [AS_HELP_STRING([--with-systemdsystemunitdir=DIR], [Directory for systemd service files])],, [with_systemdsystemunitdir=auto]) AS_IF([test "x$with_systemdsystemunitdir" = "xyes" -o "x$with_systemdsystemunitdir" = "xauto"], [ def_systemdsystemunitdir=$($PKG_CONFIG --variable=systemdsystemunitdir systemd) AS_IF([test "x$def_systemdsystemunitdir" = "x"], [AS_IF([test "x$with_systemdsystemunitdir" = "xyes"], [AC_MSG_ERROR([systemd support requested but pkg-config unable to query systemd package])]) with_systemdsystemunitdir=no], [with_systemdsystemunitdir="$def_systemdsystemunitdir"])]) AS_IF([test "x$with_systemdsystemunitdir" != "xno"], [AC_SUBST([systemdsystemunitdir], [$with_systemdsystemunitdir])]) AM_CONDITIONAL([HAVE_SYSTEMD], [test "x$with_systemdsystemunitdir" != "xno"])
Dieser Schnipsel ermöglicht die automatische Installation der Unit-Dateien auf Systemd-Maschinen und erlaubt optional ihre Installation selbst auf Maschinen, denen Systemd fehlt. (Die Anpassung des Schnipsels auf das Benutzer-Unit-Verzeichnis bleibt als Aufgabe für den Leser.)
Damit make distcheck weiterhin funktioniert, wird auf automake(1) basierenden Projekten zusätzlich empfohlen, folgendes zur Datei Makefile.am auf oberster Ebene hinzuzufügen:
AM_DISTCHECK_CONFIGURE_FLAGS = \ --with-systemdsystemunitdir=$$dc_install_base/$(systemdsystemunitdir)
Schließlich sollten Unit-Dateien im System mit einem Automake-Ausschnitt der folgenden Art installiert werden:
if HAVE_SYSTEMD systemdsystemunit_DATA = \ foobar.socket \ foobar.service endif
In der .spec-Datei von rpm(8) verwenden Sie Schnipsel der folgenden Art, um Dienste während der Installation/Deinstallation zu aktivieren/zu deaktivieren. Dies verwendet RPM-Makros, die zusammen mit Systemd ausgeliefert werden. Ziehen Sie die Paketierungsrichtlinien Ihrer Distribution für Details und die Äquivalente anderer Paketverwalter hinzu.
Am Anfang der Datei:
BuildRequires: systemd %{?systemd_requires}
Und als Skriptteile, weiter unten:
%post %systemd_post foobar.service foobar.socket %preun %systemd_preun foobar.service foobar.socket %postun %systemd_postun
Falls der Dienst während der Aktualisierung neu gestartet werden soll, ersetzen Sie den Skriptteil »%postun« mit nachfolgendem:
%postun %systemd_postun_with_restart foobar.service
Beachten Sie, dass »%systemd_post« und »%systemd_preun« die Namen sämtlicher zu installierender/entfernender Units als durch Leerzeichen getrennte Argumente erwarten. »%systemd_postun« erwartet keine Argumente. »%systemd_postun_with_restart« erwartet die neu zu startenden Units als Argumente.
Um Aktualisierungen von einer Paketversion, die nur SysV-Init-Skripte auslieferte, zu einer Paketversion, die sowohl SysV-Init-Skripte als auch eine native Systemd-Dienstedatei ausliefert, zu unterstützen, verwenden Sie Fragmente der folgenden Art:
%triggerun -- foobar < 0.47.11-1 if /sbin/chkconfig --level 5 foobar ; then /bin/systemctl --no-reload enable foobar.service foobar.socket >/dev/null 2>&1 || : fi
Wobei 0.47.11-1 die erste Paketversion ist, die die native Unit-Datei enthält. Dieses Fragment bewirkt, dass bei der erstmaligen Installation der Unit-Datei diese nur aktiviert wird, falls das SysV-Init-Skript aktiviert ist und stellt damit sicher, dass der Aktivierungsstatus sich nicht ändert. Beachten Sie, dass der Befehl chkconfig, der zum Überprüfen des Aktivitätsstandes eines SysV-Init-Skriptes verwandt werden kann, Fedora-spezifisch ist. Hier werden andere Betriebssysteme andere Befehle verwenden müssen.
EXISTIERENDE DAEMONS PORTIEREN
Da neuartige Init-Systeme wie Systemd zu traditionellen SysV-Init-Systemen kompatibel sind, ist es strenggenommen nicht notwendig, Daemons auf die neue Art zu portieren. Erfolgt dies, ermöglicht es aber, zusätzliche Funktionalitäten zum Daemon hinzuzufügen, sowie die Integration in das neuartige Init-System zu vereinfachen.
Um einen bestehenden, SysV-kompatiblen Daemon zu portieren, werden die folgenden Schritte empfohlen:
ABLAGE VON DAEMON-DATEN
Es wird empfohlen, den allgemeinen Richtlinien, beschrieben in file-hierarchy(7), für die Ablage von Paketdateien zu folgen.
SIEHE AUCH
systemd(1), sd-daemon(3), sd_listen_fds(3), sd_notify(3), daemon(3), systemd.service(5), file-hierarchy(7)
ANMERKUNGEN
- 1.
- LSB-Empfehlungen für SysV-Init-Skripte
- 2.
- Apple-MacOS-X-Daemon-Anforderungen
ÜBERSETZUNG
Die deutsche Übersetzung dieser Handbuchseite wurde von Helge Kreutzmann <debian@helgefjell.de> erstellt.
Diese Übersetzung ist Freie Dokumentation; lesen Sie die GNU General Public License Version 3 oder neuer bezüglich der Copyright-Bedingungen. Es wird KEINE HAFTUNG übernommen.
Wenn Sie Fehler in der Übersetzung dieser Handbuchseite finden, schicken Sie bitte eine E-Mail an die Mailingliste der Übersetzer.
systemd 255 |