25.7Eigene Init-Scripts bzw. Init-Konfigurationsdateien

Für Netzwerkdienste, die in fertigen Paketen zur Verfügung stehen, müssen Sie sich nicht um Init-Scripts oder -Konfigurationsdateien kümmern: Die erforderlichen Dateien werden bei allen Distributionen gleich mitgeliefert. Bei CentOS, Fedora, RHEL und SUSE müssen Sie den Dienst nur noch mit systemctl start und systemctl enable starten und dauerhaft aktivieren – bei Debian, Raspbian und Ubuntu entfällt selbst dieser Schritt.

Was aber müssen Sie tun, um einen eigenen Dienst im Init-System Ihrer Distribution zu verankern? Wenn Sie nach einer distributionsübergreifenden Lösung suchen, ist eine herkömmliche Init-V-Datei noch immer die beste Wahl. Dank der Init-V-Kompatibilität von Upstart und Systemd werden korrekt eingerichtete Init-V-Scripts von allen Distributionen gestartet.

Wenn Sie hingegen ohnedies nur mit Distributionen zu tun haben, die Systemd verwenden, ist es besser und einfacher, eine neue Systemd-Konfigurationsdatei zu erstellen und diese durch systemctl zu aktivieren. Dieser Abschnitt gibt für beide Varianten ein Beispiel.

Eigene Init-V-Scripts

Wenn Sie ein eigenes Init-V-Script verfassen, verwenden Sie am besten ein vorhandenes Script als Vorlage und modifizieren dieses. Vorweg einige Grundregeln: Da es sich um ein Script handelt, muss die Datei mit #!/bin/sh oder #!/bin/bash beginnen und ausführbar sein (chmod a+x). Einige Kommentarzeilen, die mit BEGIN INIT INFO eingeleitet werden und mit END INIT INFO enden, geben Auskunft darüber, welche Aufgabe das Script erfüllt, von welchen anderen Diensten es abhängig ist und in welchen Runleveln es standardmäßig aktiviert werden soll.

Nach eventuell noch erforderlichen Initialisierungsarbeiten folgt dann die Auswertung des Parameters $1. Sie sollten zumindest die Fälle start, stop und restart berücksichtigen, möglichst auch reload und status.

Die folgenden Zeilen zeigen den Aufbau des eigenen Init-V-Scripts /etc/init.d/masquerading, um den Rechner als Internet-Gateway einzurichten (siehe Abschnitt 28.3, »Masquerading (NAT)«):

#!/bin/sh ### BEGIN INIT INFO # Provides: masquerading # Required-Start: $network $local_fs $remote_fs # Required-Stop: $network $local_fs $remote_fs # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: start masquerading ### END INIT INFO DESC="masquerading" # Bezeichnung des Scripts ADSL=eth1 # Schnittstelle, über die der Internetzugang erfolgt . /lib/lsb/init-functions # Grundfunktionen lesen IPT=$(which iptables) # iptables-Kommando suchen if [ -z $IPT ]; then [ -x /sbin/iptables ] && IPT=/sbin/iptables [ -x /usr/sbin/iptables ] && IPT=/usr/sbin/iptables fi [ -z $IPT ] && (echo "iptables cannot be found!"; exit 0) # Funktionen für start, stop und restart case "$1" in start) log_begin_msg "Starting masquerading ..." ERROR=0 $IPT -t nat -A POSTROUTING -o $ADSL -j MASQUERADE echo 1 > /proc/sys/net/ipv4/ip_forward log_end_msg $ERROR ;; stop) log_begin_msg "Stopping masquerading ..." ERROR=0 echo 0 > /proc/sys/net/ipv4/ip_forward $IPT -t nat -D POSTROUTING -o $ADSL -j MASQUERADE log_end_msg $ERROR ;; restart) $0 stop $0 start ;; *) log_success_msg "Usage: masquerading {start|stop|restart}" exit 1 ;; esac exit 0

Mit service starten Sie das Script erstmalig:

root# service masquerading start

Damit das Script in Zukunft beim Rechnerstart ausgeführt wird, führen Sie die folgenden Kommandos aus:

root# insserv masquerading (Debian, openSUSE, Ubuntu) root# chkconfig --on masquerading (CentOS, Fedora, RHEL)

Eigene Systemd-Konfigurationsdatei

Um einen Systemd-Dienst einzurichten, müssen Sie eine *.service-Datei im Verzeichnis /etc/systemd/system erstellen. Abermals ist es zweckmäßig, wenn Sie sich dabei an einer Service-Datei eines anderen, vergleichbaren Diensts orientieren. Die vorgegebenen Service-Dateien befinden sich je nach Distribution in den Verzeichnissen /lib/systemd/system oder /usr/lib/systemd/system.

Eine minimale Service-Datei sieht wie folgt aus:

[Unit] Description=Foo [Service] ExecStart=/usr/sbin/foo-daemon [Install] WantedBy=multi-user.target

Das bedeutet, dass der Dienst »Foo« in Form des Hintergrundprozesses foo-daemon gestartet werden soll. Ein explizites Stop-Kommando fehlt; deswegen wird Systemd zum Beenden zuerst das Signal SIGTERM und, wenn das nicht hilft, auch SIGKILL an den Prozess senden.

An ExecStart muss ein Kommandoname mit vollständigem Pfad übergeben werden. In der gleichen Weise können Sie mit ExecStop ein zweites Kommando angeben, das ausgeführt wird, wenn der Hintergrundprozess beendet werden soll.

Normalerweise ist es nicht zulässig, mit ExecStart oder ExecStop mehrere Kommandos anzugeben. Wenn Sie das möchten, müssen Sie im [Service]-Block Type=oneshot angeben. Nun sind beliebig viele ExecStart- bzw. ExecStop-Anweisungen erlaubt, die der Reihe nach ausgeführt werden.

Wenn Sie bei einer derartigen Konfiguration explizit zwischen zwei Zuständen hin- und herschalten möchten (start/stop), dann müssen Sie wie im folgenden Beispiel auch das Schlüsselwort RemainAfterExit verwenden. Die Option bewirkt, dass Systemd sich den gerade aktivierten Zustand merkt. Ohne diese Option glaubt Systemd nach systemctl start name, dass die Aktion mit dem Ende des letzten StartExec-Kommando beendet ist, und setzt den Status sofort wieder auf stop. Ein explizites Ausführen von systemctl stop bleibt dann wirkungslos.

Für das obige Beispiel galt implizit Type=simple. Systemd nimmt in diesem Fall an, dass das mit ExecStart angegebene Kommando der zu startende Dienst ist. Sobald dieses Programm endet, betrachtet Systemd den Dienst als regulär beendet.

Der dritte wichtige Typ für Services ist Type=fork: Diese Variante wählen Sie dann, wenn das mit ExecStart angegebene Kommando ein anderes Hintergrundprogramm startet (also einen Dämon). In diesem Fall sollten Sie mit PIDFile eine Datei angeben, in der die Prozessnummer gespeichert wird. Das gibt Systemd die Möglichkeit, den Hintergrundprozess zu überwachen bzw. bei Bedarf zu stoppen.

Weitere Informationen zum Verfassen eigener Systemd-Service-Dateien geben man systemd.service und man systemd.exec sowie die folgenden Seiten:

https://fedoraproject.org/wiki/Packaging:Systemd
https://wiki.archlinux.org/index.php/Systemd
http://0pointer.de/blog/projects/systemd-for-admins-3.html

Das folgende Beispiel greift nochmals die Masquerading-Funktionen auf, die schon als Beispiel für das Init-V-Script dienten. Zur einfacheren Administration gibt es in diesem Fall gleich zwei Konfigurationsdateien:

Die Datei zur Festlegung der ADSL-Schnittstelle kann z.B. so aussehen:

# Datei /etc/sysconfig/masquerading # Masquerading-Schnittstelle des Internet-Gateways ADSL=enp4s0

Die Service-Datei verwendet das Schlüsselwort EnvironmentFile, um diese Konfigurationsdatei einzulesen. Alle dort definierten Variablen können nun in der Service-Datei in der Form $varname angesprochen werden.

[Unit] Description=Masquerading After=syslog.target network.target [Service] Type=oneshot RemainAfterExit=true EnvironmentFile=/etc/sysconfig/masquerading ExecStart=/sbin/iptables -t nat -A POSTROUTING -o $ADSL -j MASQUERADE ExecStart=/bin/sh -c "echo 1 > /proc/sys/net/ipv4/ip_forward" ExecStop=/sbin/iptables -t nat -D POSTROUTING -o $ADSL -j MASQUERADE ExecStop=/bin/sh -c "echo 0 > /proc/sys/net/ipv4/ip_forward" [Install] WantedBy=multi-user.target

Aus Effizienzgründen hält Systemd den Inhalt der wichtigsten Konfigurationsdateien in einem Zwischenspeicher (Cache). Nach Konfigurationsänderungen müssen Sie Systemd deswegen auffordern, die Konfigurationsdateien neu einzulesen:

root# systemctl daemon-reload

Um das Masquerading unmittelbar und in Zukunft jedes Mal zu starten, wenn das Multi-User-Target erreicht wird, sind die folgenden Kommandos erforderlich:

root# systemctl start masquerading root# systemctl enable masquerading