DAEMON(7) daemon DAEMON(7) BEZEICHNUNG daemon - Schreiben und Paketieren von System-Daemons BESCHREIBUNG Ein Daemon ist ein Diensteprozess, der im Hintergrund lauft und das System beaufsichtigt oder Funktionalitaten fur andere Prozesse bereitstellt. Traditionell werden Daemons so implementiert, dass sie einem ursprunglich aus SysV-Unix stammenden Schema folgen. Moderne Daemons sollten einem einfacheren, aber dennoch leistungsfahigeren Schema folgen (hier >>neuartige<< Daemons genannt), wie es von systemd(1) implementiert wird. Diese Handbuchseite deckt beide Schemata ab und enthalt insbesondere Empfehlungen fur 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 ausfuhren. Beachten Sie, dass diese Schritte von neuartigen Daemons (siehe unten) nicht benotigt werden. Sie sollten daher nur implementiert werden, wenn die Kompatibilitat zu SysV essenziell ist. 1. Alle offenen Dateideskriptoren ausser der Standardeingabe, -ausgabe und -fehlerausgabe (d.h. den drei ersten Dateideskriptoren 0, 1, 2) werden geschlossen. Dies stellt sicher, dass kein versehentlich geoffneter Dateideskriptor im Daemon-Prozess verbleibt. Unter Linux wird dies am besten dadurch implementiert, dass durch /proc/self/fd iteriert wird, mit der Ruckfalloption, von Dateideskriptor 3 bis zu dem von getrlimit() fur RLIMIT_NOFILE zuruckgelieferten Wert durchzuiterieren. 2. Alle Signal-Handler werden auf ihre Vorgaben zuruckgesetzt. Dies erfolgt am besten durch Iteration durch alle verfugbaren Signale bis zur Grenze von _NSIG und dem Zurucksetzen dieser auf SIG_DFL. 3. Zurucksetzen der Signal-Maske mittels sigprocmask(). 4. Bereinigen des Umgebungsblocks, Entfernen oder Zurucksetzen der Umgebungsvariablen, die einen negativen Einfluss auf die Laufzeit des Daemons haben konnten. 5. Aufrufen von fork(), um einen Hintergrundprozess zu erzeugen. 6. Aufruf von setsid() im Kind, um von jedem Terminal zu trennen und eine unabhangige Sitzung zu erzeugen. 7. Erneuter Aufruf von fork() im Kind, um sicherzustellen, dass der Daemon niemals wieder ein Terminal erlangen kann. (Dies ist relevant, falls das Programm und alle seine Abhangigkeiten nicht sorgfaltig genug sind, um bei jedem >>open()<<-Aufruf, der moglicherweise einen TTY-Gerateknoten erlangen konnte, stets >>O_NOCTTY<< festzulegen.) 8. Aufruf von exit() im ersten Kind, so dass nur das zweite Kind (der eigentliche Daemon) verbleibt. Dies stellt sicher, dass der Daemon-Prozess PID 1 als neuen Elternprozess bekommt, wie das bei allen Daemons der Fall sein sollte. 9. Verbinden von /dev/null im Daemon-Prozess mit der Standardeingabe, -ausgabe und -fehlerausgabe. 10. Zurucksetzen der Umask auf 0 im Daemon-Prozess, so dass die an open(), mkdir() und ahnliche weitergegebenen Dateimodi direkt die Zugriffsmodi auf die erstellten Dateien und Verzeichnisse steuern. 11. Andern des aktuellen Verzeichnisses im Daemon-Prozess auf das Wurzelverzeichnis (/), um zu vermeiden, dass der Daemon unfreiwillig die Einhangepunkte vor dem Aushangen blockiert. 12. Schreiben der Daemon-PID (wie von getpid() zuruckgeliefert) im Daemon-Prozess in eine PID-Datei, beispielsweise /run/foobar.pid (fur einen hypothetischen Daemon >>foobar<<), um sicherzustellen, dass der Daemon nicht mehr als einmal gestartet wird. Dies muss so implementiert werden, dass kein Ressourcenwettlauf moglich ist, so dass die PID-Datei nur aktualisiert wird, wenn gleichzeitig sichergestellt ist, dass die vorher in der PID-Datei gespeicherte PID nicht mehr existiert oder zu einem fremden Prozess gehort. 13. Abgeben der Privilegien im Daemon-Prozess, falls moglich und zutreffend. 14. Benachrichtigen des ursprunglich gestarteten Prozesses aus dem Daemon-Prozess, dass die Initialisierung abgeschlossen ist. Dies kann uber eine unbenannte Pipe oder einen ahnlichen Kommunikationskanal, der vor dem ersten fork() erstellt wurde und daher in sowohl dem ursprunglichen als auch dem Daemon-Prozess verfugbar ist, erfolgen. 15. Aufrufen von exit() im ursprunglichen Prozess. Der Prozess, der den Daemon gestartet hat, muss in der Lage sein, sich darauf zu verlassen, dass dieser exit() passiert, nachdem die Initialisierung abgeschlossen und die externen Kommunikationskanale etabliert und zugreifbar sind. Die BSD-Funktion daemon() sollte nicht verwandt werden, da sie nur eine Teilmenge dieser Schritte implementiert. Ein Daemon, der Kompatibilitat mit SysV-Systemen bereitstellen muss, sollte das oben dargestellte Schema implementieren. Es wird allerdings empfohlen, dieses Verhalten uber 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 fur 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 fur SysV-Daemons empfohlenen Initialisierungsschritte implementiert werden. Bei neuartigen Init-Systemen wie Systemd sind diese alle redundant. Da einige dieser Schritte sogar die Prozessuberwachung, Dateideskriptorweitergabe und andere Funktionalitaten des Diensteverwalters storen, wird empfohlen, sie nicht auszufuhren, wenn sie als neuartiger Dienst ausgefuhrt laufen. Beachten Sie, dass neuartige Init-Systeme die Ausfuhrung eines Daemon-Prozesses in einem sauberen Prozesskontext garantieren: Es wird garantiert, dass der Umgebungsblock bereinigt ist, dass Signal-Handler und -Masken zuruckgesetzt sind und dass kein ubrig gebliebener Dateideskriptor weitergegeben wird. Daemons werden in ihrer eigenen Sitzung ausgefuhrt, wobei die Standardeingabe mit /dev/null und die Standardausgabe/Standardfehlerausgabe mit dem Protokollierungsdienst systemd-journald.service(8) verbunden ist, ausser dies ist anders konfiguriert. Die Umask ist zuruckgesetzt. Es wird empfohlen, dass neuartige Daemons folgendes implementieren: 1. Falls zutreffend sollte der Daemon uber den Abschluss des Startens oder Statusaktualisierungen den Diensteverwalter mittels der Schnittstelle sd_notify(3), insbesondere READY=1 und STATUS=, informieren. 2. Falls SIGTERM empfangen wird, soll der Daemon sich herunterfahren und sauber beenden. Es sollte mittels sd_notify(3) eine Stopp-Benachrichtigung gesandt werden. 3. Falls SIGHUP empfangen wird, sollen die Konfigurationsdateien, falls zutreffend, neu geladen werden. Dies sollte mit Benachrichtigungen mittels sd_notify(3) kombiniert werden: RELOADING=1 und READY=1. 4. Es soll ein korrekter Exit-Code vom Haupt-Daemon-Prozess bereitgestellt werden, da dieser vom Diensteverwalter benutzt wird, um Dienstefehler und Probleme zu erkennen. Es wird empfohlen, dem in LSB-Empfehlungen fur SysV-Init-Skripte[1] definierten Exit-Code-System zu folgen. 5. Falls moglich und zutreffend sollte die Steuerschnittstelle mittels des D-Bus-IPC-Systems zuganglich gemacht und ein Bus-Name als letzten Schritt in der Initialisierung erlangt werden. 6. Stellen Sie eine .service-Unit-Datei zur Integration mit Systemd bereit, die Informationen zum Starten, Beenden und anderseitigen Verwalten des Daemons enthalt. Siehe systemd.service(5) fur Details. 7. Verlassen Sie sich soweit moglich auf die Funktionalitaten des Diensteverwalters, den Zugriff des Daemons auf Dateien, Dienste und andere Ressourcen zu begrenzen, d.h. im Falle von Systemd, verlassen Sie sich auf Systemds Ressourenbegrenzungssteuerung statt Ihre eigene zu implementieren, verlassen Sie sich auf den Privilegienabgabe-Code von Systemd, statt ihn in Ihrem Daemon zu implementieren und so weiter. Siehe systemd.exec(5) fur die verfugbaren Steuerungen. 8. Falls D-Bus verwandt wird, ermoglichen Sie die Bus-Aktivierung Ihres Daemons, indem Sie eine D-Bus-Dienste-Aktivierungsdatei bereitstellen. Dies hat eine Reihe von Vorteilen: Ihr Daemon kann erst bei Bedarf gestartet werden; er kann parallel zu anderen Daemons, die ihn benotigen, gestartet werden -- wodurch die Parallelisierung und die Systemstartgeschwindigkeit maximiert wird; Ihr Daemon kann im Fehlerfall neu gestartet werden, ohne eine Bus-Anfrage zu verlieren, da die Bus-Warteschlagen aktivierbare Dienste erbitten. Siehe unten fur Details. 9. Falls Ihr Daemon Dienste fur andere lokale Prozesse oder Clients in der Ferne uber ein Socket anbietet, sollte es gemass des nachfolgend dargestellten Schemas Socket-aktivierbar sein. Ahnlich der D-Bus-Aktivierung ermoglicht dies bedarfsgesteuertes Starten von Diensten sowie verbesserte Parallelisierung beim Starten der Dienste. Fur zustandslose Protokolle (wie Syslog, DNS) kann ein Daemon, der Socket-basierte Aktivierung implementiert, auch ohne Verlust einer einzelnen Anfrage neu gestartet werden. Siehe unten fur Details. 10. Falls der Dienst Sockets oder andere Dateien selbst offnet und diese Dateideskriptoren einen Neustart uberleben sollen, sollte der Daeomen sie im Diensteverwalter mittels sd_notify(3) mit FDSTORE=1 speichern. 11. Statt den Aufruf syslog() zum direkten Protokollieren in den Systemprotokolldienst zu verwenden, kann ein neuartiger Daemon einfach auf die Standardfehlerausgabe mittels fprintf() protokollieren, was dann an Syslog weitergeleitet wird. Falls Protokollierungsstufen notwendig sind, konnen diese durch Voranstellen von Zeichenketten wie >><4><< (fur Protokollierungsstufe 4 >>WARNING<< im Syslog-Prioritatsschema) vor individuellen Protokollierzeilen kodiert werden. Dies folgt einem ahnlichen Stil wie das printk()-Stufensystem des Linux-Kernels. Fur Details siehe sd-daemon(3) und systemd.exec(5). 12. Da neuartige Daemons ohne ein steuerndes TTY (aber sie selbst als ihren eigenen Sitzungsleiter) aufgerufen werden, sollte sichergestellt werden, dass bei open(2)-Aufrufen, die moglicherweise einen TTY-Gerateknoten referenzieren, stets O_NOCTTY festgelegt wird, so dass nicht versehentlich ein steuerndes TTY erlangt wird. Diese Empfehlungen sind ahnlich zu, aber nicht identisch mit den Apple-MacOS-X-Daemon-Anforderungen[2]. AKTIVIERUNG Neuartige Init-Systeme stellen eine Reihe von zusatzlichen Mechanismen bereit, um Dienste zu aktivieren. Details dazu weiter unten. Es ist typisch, dass Dienste konfiguriert wurden, uber mehr als einen Mechanismus gleichzeitig aktiviert zu werden. Beispielsweise konnte 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 konnte 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 fur 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 durchzufuhren (womit der Systemstart beschleunigt wird), da bereits alle Kommunikationskanale 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 unterstutzt, 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 wahrend des Systemstarts als auch wahrend der Laufzeit und verwenden minimalere Dienstebeschreibungsdateien. Falls der Entwickler oder Administrator in Systemd sicherstellen mochte, 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) fur Details uber die Verzeichnisse .wants/ und systemd.special(7) fur Details uber die zwei Systemstartziele. Socket-basierte Aktivierung Um die Parallelisierung und Robustheit zu maximieren und die Konfiguration und Entwicklung zu vereinfachen, wird fur alle neuartigen Daemons empfohlen, die uber 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 primaren 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 verzogert 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 konnen, sobald alle Sockets etabliert sind. Zusatzlich konnen Daemons neugestartet werden und dabei nur eine minimale Anzahl an Client-Transaktionen verlieren oder sogar uberhaupt keine Client-Anfrage (Letzteres stimmt insbesondere fur zustandslose Protokolle wie DNS oder Syslog), da das Socket wahrend des Neustarts angebunden und zugreifbar verbleibt und alle Anfragen in einer Warteschlange verbleiben, wahrend der Daemon sie nicht verarbeiten kann. Neuartige Daemons, die Socket-Aktivierung unterstutzen, mussen in der Lage sein, Sockets vom Diensteverwalter zu erhalten, statt sie selbst zu erstellen und sich daran zu binden. Fur Details uber die Programmierschnittstellen fur dieses von Systemd bereitgestellte Schema, siehe sd_listen_fds(3) und sd-daemon(3). Fur Details uber die Portierung bestehender Daemons zu Socket-basierter Aktivierung, siehe unten. Mit minimalem Einsatz ist es moglich, Socket-basierte Aktivierung zusatzlich 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 unterstutzen. Systemd implementiert Socket-basierte Aktivierung mittels .socket-Units, die in systemd.socket(5) beschrieben sind. Wenn Socket-Units fur 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 Abhangigkeit automatisch bei der Installation einer Socket-Unit hinzuzufugen. Die notwendigen Ordnungs-Abhangigkeiten werden fur alle Socket-Units implizit erstellt, falls DefaultDependencies=no nicht gesetzt ist. Fur weitere Informationen uber sockets.target, siehe systemd.special(7). Es ist nicht notwendig oder empfohlen, zusatzliche Abhangigkeiten auf Socket-Units abzulegen (zum Beispiel von multi-user.target oder ahnlichem), wenn eine in sockets.target installiert ist. Bus-basierte Aktivierung Wenn das D-Bus-IPC-System fur 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 durfen) 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 fur einen D-Bus-Dienst zu konfigurieren. Stellen Sie beispielsweise fur einen D-Bus-Dienst, dessen D-Bus-Aktivierungsdatei org.freedesktop.RealtimeKit.service heisst, sicher, dass SystemdService=rtkit-daemon.service in dieser Datei gesetzt ist, um ihn an den Systemd-Dienst rtkit-daemon.service zu binden. Dies wird benotigt, um sicherzustellen, dass der Daemon ohne Ressourcenwettlaufe gestartet wird, wenn er uber mehrere Mechanismen simultan aktiviert wird. Gerate-basierte Aktivierung Oft sollen Daemons, die einen besonderen Hardwaretyp verwalten, nur aktiviert werden, wenn die Hardware der entsprechenden Art eingesteckt oder andernfalls verfugbar gemacht wird. In einem neuartigen Init-System ist es moglich, die Aktivierung an Hardware-Einsteck-/Aussteck-Ereignisse zu binden. In Systemd konnen Kernel-Gerate, die in dem Geratebaum sysfs/udev auftauchen, als Units offengelegt werden, falls sie mit der Zeichenkette >>systemd<< markiert sind. Wie andere Arten von Units konnen sie dann andere Units bei der Aktivierung (z.B. beim Einstecken) hereinziehen, und daher Gerate-basierte Aktivierung implementieren. Systemd-Abhangigkeiten konnen in der Udev-Datenbank mittels der Eigenschaft SYSTEMD_WANTS= kodiert werden. Siehe systemd.device(5) fur Details. Oft ist es schoner, einen Dienst von Geraten nur indirekt uber dedizierte Ziele hereinzuziehen. Beispiel: Statt bluetoothd.service von alle den verschiedenen Bluetooth-Dongles und anderen verfugbaren Hardwaren hereinzuziehen, ziehen Sie von ihnen bluetooth.target herein und dann bluetoothd.service von diesem Ziel. Dies stellt eine nettere Abstraktion bereit und ermoglicht Administratoren die Option, bluetoothd.service uber 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 konnen Laufzeit-Daemons, die Spool-Dateien oder -Verzeichnisse (wie bei einem Drucksystem) verarbeiten, verzogert werden, bis diese Dateisystemobjekte den Zustand andern oder nicht mehr leer sind. Neuartige Init-Systeme stellen einen Weg bereit, die Diensteaktivierung an Dateisystemanderungen 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 Aufraumaufgaben erledigen, die regelmassig ausgefuhrt 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 konnen als Kombination der obigen Schemata zusammengestellt werden. Beispiel: Manchmal erscheint es nutzlich, 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) fur 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 tatsachlich verfugbar werden; dies macht eine solche explizite Abhangigkeit auf die konfigurierte Adresse redundant. Ein anderer oft vorgeschlagener Ausloser fur Dienste-Aktivierung ist niedrige Systemlast. Auch hier konnte allerdings ein uberzeugender Ansatz sein, die Funktionalitaten des Betriebssystems korrekt zu benutzen, insbesondere des CPU- oder E/A-Schedulers von Linux. Anstatt Auftrage vom Anwenderbereich, basierend auf der Uberwachung des Betriebssystem-Schedulers, einzuplanen, ist es empfehlenswert, die Einplanung von Prozessen dem Betriebssystem-Scheduler selbst zu uberlassen. Systemd stellt einen feingranularen Zugriff auf die CPU- und E/A-Scheduler bereit. Falls ein vom Diensteverwalter ausgefuhrter Prozess den Umfang der fur andere Prozesse verfugbaren 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-Auftrage wahrend 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 Vorschlage zu berucksichtigen: 1. Falls moglich, nutzen Sie die Einstellung Type=forking in Dienstedateien nicht. Falls Sie es aber machen, stellen Sie sicher, den PID-Dateipfad mit PIDFile= zu setzen. Siehe systemd.service(5) fur Details. 2. Falls Ihr Daemon einen D-Bus-Namen auf dem Bus registriert, stellen Sie sicher, falls moglich Type=dbus in der Dienstedatei zu verwenden. 3. Setzen Sie eine gut lesbare Beschreibung in Description=. 4. Deaktivieren Sie DefaultDependencies= nicht, ausser Sie wissen genau, was Sie tun und Ihre Unit ist in der fruhen Systemstartphase oder im spaten Herunterfahren beteiligt. 5. Normalerweise werden wenige, falls uberhaupt, Abhangigkeiten explizit definiert werden mussen. Falls Sie allerdings explizite Abhangigkeiten definieren, beziehen Sie sich nur auf Units, die in systemd.special(7) aufgefuhrt sind oder auf Namen, die von Ihrem eigenen Paket bekanntgegeben sind, um Ihre Unit-Datei Betriebssystem-unabhangig zu halten. 6. Nehmen Sie einen Abschnitt >>[Install]<< auf, der die Installationsinformation fur die Unit-Datei enthalt. Siehe systemd.unit(5) fur Details. Um Ihren Dienst beim Systemstart zu aktivieren, fugen Sie eine Anweisung WantedBy=multi-user.target oder WantedBy=graphical.target hinzu. Um Ihr Socket beim Systemstart zu aktivieren, fugen Sie WantedBy=sockets.target hinzu. Normalerweise wollen Sie auch sicherstellen, dass bei der Installation Ihres Dienstes auch Ihr Socket installiert wird, daher fugen Sie Also=foo.socket in Ihrer Dienstedatei foo.service fur ein hypothetisches Programm foo hinzu. Systemd-Dienstedateien installieren Zum Bauinstallationszeitpunkt (d.h. make install wahrend des Paketbaus) wird empfohlen, dass Pakete ihre Systemd-Unit-Dateien im Verzeichnis, das von pkg-config systemd --variable=systemdsystemunitdir (fur Systemdienste) oder pkg-config systemd --variable=systemduserunitdir (fur Benutzerdienste) zuruckgeliefert wird, zu installieren. Damit wird der Dienst im System fur explizite Anfragen verfugbar gemacht, aber nicht beim Systemstart automatisch aktiviert. Optional sollten wahrend 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. Fur Pakete, die autoconf(1) verwenden, wird empfohlen, einen Configure-Skript-Auszug wie den nachfolgenden zu verwenden, um den Unit-Installationspfad wahrend 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 ermoglicht 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 fur den Leser.) Damit make distcheck weiterhin funktioniert, wird auf automake(1) basierenden Projekten zusatzlich empfohlen, folgendes zur Datei Makefile.am auf oberster Ebene hinzuzufugen: AM_DISTCHECK_CONFIGURE_FLAGS = \ --with-systemdsystemunitdir=$$dc_install_base/$(systemdsystemunitdir) Schliesslich 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 wahrend der Installation/Deinstallation zu aktivieren/zu deaktivieren. Dies verwendet RPM-Makros, die zusammen mit Systemd ausgeliefert werden. Ziehen Sie die Paketierungsrichtlinien Ihrer Distribution fur Details und die Aquivalente 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 wahrend 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 samtlicher 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 unterstutzen, 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 enthalt. 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 andert. Beachten Sie, dass der Befehl chkconfig, der zum Uberprufen des Aktivitatsstandes eines SysV-Init-Skriptes verwandt werden kann, Fedora-spezifisch ist. Hier werden andere Betriebssysteme andere Befehle verwenden mussen. 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, ermoglicht es aber, zusatzliche Funktionalitaten zum Daemon hinzuzufugen, sowie die Integration in das neuartige Init-System zu vereinfachen. Um einen bestehenden, SysV-kompatiblen Daemon zu portieren, werden die folgenden Schritte empfohlen: 1. Falls noch nicht implementiert, fugen Sie einen zusatzlichen Befehlszeilenschalter zu dem Daemon hinzu, um die Daemonisierung zu deaktivieren. Dies ist nicht nur fur den Einsatz in neuartigen Init-Systemen, sondern auch zur Erleichterung der Fehlersuche nutzlich. 2. Falls der Daemon zu anderer, auf dem lokalen System laufenden Software Schnittstellen mittels lokaler AF_UNIX-Sockets anbietet, sollte eine Socket-basierte Aktivierung (siehe oben) uberlegt werden. Normalerweise reicht ein minimaler Patch, um dies zu implementieren: Erweitern Sie die Socket-Erstellung im Daemon-Code, so dass zuerst sd_listen_fds(3) auf bereits ubergebene Sockets gepruft wird. Falls Sockets ubergeben wurden (d.h. wenn sd_listen_fds() einen positiven Wert liefert), uberspringen Sie den Socket-Erstellungsschritt und verwenden Sie die ubergebenen Sockets. Zweitens sollten die System-Socket-Knoten fur lokale, in der Socket-basierten Aktivierung verwandten AF_UNIX-Sockets nicht entfernt werden, wenn der Daemon heruntergefahren wird, falls Sockets ubergeben wurden. Falls der Daemon normalerweise alle verbliebenen offenen Dateideskriptoren als Teil seiner Initialisierung schliesst, mussen drittens die vom Diensteverwalter ubergebenen Sockets verschont werden. Da neuartige Init-Systeme garantieren, dass keine verbliebenen Dateideskriptoren an ausgefuhrte Prozesse ubergeben werden, konnte es eine gute Idee sein, einfach das Schliessen aller verbliebenen offenen Dateideskriptoren zu uberspringen, falls Sockets ubergeben wurden. 3. Schreiben und installieren Sie eine Systemd-Unit-Datei fur den Dienst (und die Sockets, falls Socket-basierte Aktivierung verwandt wird, sowie eine Pfad-Unit-Datei, falls der Daemon ein Spool-Verzeichnis verarbeitet), siehe oben fur Details. 4. Falls der Daemon Schnittstellen mittels D-Bus offenlegt, schreiben Sie eine D-Bus-Aktivierungsdatei fur den Dienst, siehe oben fur Details. ABLAGE VON DAEMON-DATEN Es wird empfohlen, den allgemeinen Richtlinien, beschrieben in file-hierarchy(7), fur 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 fur SysV-Init-Skripte http://refspecs.linuxbase.org/LSB_3.1.1/LSB-Core-generic/LSB-Core-generic/iniscrptact.html 2. Apple-MacOS-X-Daemon-Anforderungen https://developer.apple.com/library/mac/documentation/MacOSX/Conceptual/BPSystemStartup/Chapters/CreatingLaunchdJobs.html UBERSETZUNG Die deutsche Ubersetzung dieser Handbuchseite wurde von Helge Kreutzmann erstellt. Diese Ubersetzung ist Freie Dokumentation; lesen Sie die GNU General Public License Version 3 oder neuer bezuglich der Copyright-Bedingungen. Es wird KEINE HAFTUNG ubernommen. Wenn Sie Fehler in der Ubersetzung dieser Handbuchseite finden, schicken Sie bitte eine E-Mail an die Mailingliste der Ubersetzer . systemd 255 DAEMON(7)