Howto/systemd Service Unit Beispiel

Achtung!

Die Verwendung dieses Howto geschieht auf eigene Gefahr. Bei Problemen mit der Anleitung melde dies bitte in der dazugehörigen Diskussion und wende dich zusätzlich an den Verfasser des Howtos.

Hinweis:

Diese Howto-Anleitung wurde zuletzt von noisefloor am 23.3.2018 unter Ubuntu 16.04 erfolgreich getestet.

Zum Verständnis dieses Artikels sind folgende Seiten hilfreich:

  1. Ein Terminal öffnen

  2. Einen Editor öffnen

  3. Root-Rechte

  4. Rechte für Dateien und Ordner ändern

Inhaltsverzeichnis
  1. .service Datei anlegen
  2. Service Unit aktivieren
  3. Modifikation
    1. Benutzer ändern
    2. Server im gesamten Netzwerk erreichbar m...
    3. zusätzliche Befehl vor und nach dem Star...
  4. Links

Im folgenden wird anhand eines Beispiels gezeigt, wie man eine eigene Service Unit für systemd anlegt und aktiviert.

Das Programm, welches ausgeführt werden soll, ist ein simpler, in Python geschriebener Webserver, welcher nichts anderes macht, als auf localhost und Port 8000 zu lauschen und beim Aufruf der Adresse http://127.0.0.1:8000 "Hello World" und die aktuelle Uhrzeit zurück liefert.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
#!/usr/bin/env python3

from wsgiref.simple_server import make_server
from datetime import datetime

def hello_world_app(environ, start_response):
    status = '200 OK'
    headers = [('Content-type', 'text/plain; charset=utf-8')]
    start_response(status, headers)
    text = 'Hello World @ {}'.format(datetime.now())
    return [text.encode('utf-8')]

httpd = make_server('', 8000, hello_world_app)
httpd.serve_forever()

Der Code wird z.B. im Homeverzeichnis unter /home/BENUTZER/code/simple_wsgi_server.py gespeichert. Anschließend muss die Datei noch ausführbar gemacht werden[4].

.service Datei anlegen

Als erstes muss eine .service Datei unter /etc/systemd/system angelegt werden, z.B. mit dem Dateinamen wsgiserver.service. Diese Datei editiert man dann mit einem Editor mit Root-Rechten[2][3] und fügt folgenden Inhalt ein:

[Unit]
Description=Simple WSGI Server

[Service]
Type=simple
ExecStart=/home/BENUTZER/code/simple_wsgi_server.py

[Install]
WantedBy=multi-user.target

Service Unit aktivieren

Jetzt muss die Service Unit noch aktiviert werden[1][3]:

sudo systemctl enable wsgiserver.service 

Anschließend kann die Unit gestartet werden:

sudo systemctl start wsgiserver.service 

Wer jetzt auf dem Rechner im Webbrowser die Adresse http://127.0.0.1:8000 aufruft, der sollte mit einem "Hello World" plus Datum und Uhrzeit begrüßt werden.

Modifikation

Benutzer ändern

Da in der .service Datei kein Nutzer angegeben ist, wird das Python-Skript von Root ausgeführt. Um den Nutzer zu ändern, fügt ergänzt man die Datei wsgiserver.service in der Sektion "[Service]" einfach um die Zeile

User=www-data

Dann läuft das Skript mit den Rechten des Nutzers www-data. Natürlich kann man hier auch jeden anderen Benutzer angeben, der auf dem System existiert.

Wichtig ist dabei, dass dieser Nutzer auch die nötigen Rechte hat, die Datei auszuführen. Für das obige Beispiel des einfachen Servers würde das Ausführungsrechte benötigt.

Möchte man für die Python-Datei bei nur das Leserecht für alle Nutzer einräumen, dann wäre folgende Änderung an der .service Datei notwendig:

...
[Service]
...
ExecStart=/usr/bin/python3 /home/BENUTZER/code/simple_wsgi_server.py
...

Da der Pfad zum Python3 Interpreter mit angegeben wird, muss die Datei simple_wsgi_server.py nicht (mehr) ausführbar sein.

Server im gesamten Netzwerk erreichbar machen

Der Server aus dem obigen Beispiel läuft nur auf localhost und ist somit für andere Rechner im selben Netzwerk nicht erreichbar. Wer das möchte, muss die letzte Zeile im Python-Skript wie folgt ändern:

1
httpd = make_server('0.0.0.0', 8000, hello_world_app)

Damit lauft der Server auf allen IP-Addresse.

Und da der Server jetzt über das Netzwerk erreichbar ist, sollt er natürlich nur gestartet werden, wenn das Netzwerk auch verfügbar ist. Um das zu erreichen, fügt man in der .service-Datei in der Sektion "[Unit]" noch folgende Zeile ein:

After=network.target

systemd prüft so vor Starten des Servers, ob das Netzwerk vorhanden / bereit ist.

zusätzliche Befehl vor und nach dem Start ausführen

Das Python Serverskript benötigt keine zusätzlichen Befehle, die vor oder nach dem Start ausgeführt werden müssten. Andere / komplexere Skripte / Programme, benötigen dies aber vielleicht doch, z.B. zum Löschen von alten Daten etc.

Um zusätzliche Befehle auszuführen, hinterlegt man in der Sektion "[Service]" die Schlüssel ExecStartPre und / oder ExecStartPost

Würde man die Sektion um z.B. um die Zeile

ExecStartPost=/bin/echo "Server gestartet"

so würde der Eintrag "Server gestartet" zusätzlich in die zentrale Logdatei geschrieben, nachdem der Server erfolgreich gestartet wurde.

Hinweis: bei realen Applikation ist diese Art von Logging normalerweise überflüssig, da systemd sowieso in die zentrale Logdatei loggt, wenn ein Service gestartet wurde. Für diese Beispiel sieht der Logeintrag z.B so aus

Jan 16 17:32:31 noisefloor-xubuntu systemd[1]: Started Simple WSGI Server