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 9.1.2020 unter Ubuntu 18.04 erfolgreich getestet.

Zum Verständnis dieses Artikels sind folgende Seiten hilfreich:

  1. Ein Terminal öffnen

  2. Einen Editor öffnen

  3. mit Root-Rechten arbeiten

  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 auszugeben.

 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, ergänzt man die Datei wsgiserver.service in der Sektion "[Service]" 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ührungsrecht benötigt.

Möchte man für die Python-Datei 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 den Webserver von anderen Clients im Netzerreichen 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 läuft der Server für alle 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"

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

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

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