Bernsteins Daemontools installieren und einrichten

In diesem Beitrag soll es um die Einrichtung der sog. Daemontools gehen. Mit den Daemontools kann man Programme als Daemon laufen lassen, und den Prozess einfacher steuern.

Das Einrichten der Daemontools ist insofern sinnvoll, da man sich von der „Alternative“, den virtuellen Screens, ablösen kann. Der Vorteil liegt auf der Hand: Der Supervisor-Prozess wird beim Booten des Servers gestartet, und mit ihm auch die angelegten Services. Es entfällt das lästige händische Neustarten von verschiedenen Diensten in virtuellen Screens.

Da mein Vserver bei Netcup ein paar Krankheiten zum Opfer viel, nach welchen ich sämtliche Dienste von Hand neustarten musste, wollte ich die Daemontools einrichten.

Die Installation der Daemontools

Alles was man zur Installation wissen muss beschreibt der Author des Programms auf seiner Webseite recht kompakt. Ich möchte das ein wenig ausführlicher behandeln, um den Einstieg zu vereinfachen.

Zunächst legen wir einen neuen Ordner an, ändern dessen Rechte und wechseln dort hinein:

sudo mkdir /package
sudo chmod 1755 /package
cd /package

Dorthin werden wir später die Daemontools installieren. Die Quelltexte laden und entpacken wir im nächsten Schritt:

sudo wget http://cr.yp.to/daemontools/daemontools-0.76.tar.gz
sudo tar xfv daemontools-0.76.tar.gz 

Danach wechseln wir in die neuen Verzeichnisse und stoßen den Kompilierungsprozess an:

cd admin/daemontools-0.76
sudo ./package/compile

In manchen Fällen beendet sich der Compiler mit der folgenden (oder ähnlichen) Fehlermeldung:

/usr/bin/ld: errno: TLS definition in /lib/arm-linux-gnueabihf/libc.so.6 section .tbss mismatches non-TLS reference in envdir.o
/lib/arm-linux-gnueabihf/libc.so.6: could not read symbols: Bad value
collect2: ld returned 1 exit status
make: *** [envdir] Fehler 1

Dieses Problem lässt sich sehr leicht fixen. Man muss nur eine Zeile in der Datei src/conf-cc anpassen. Öffnet diese dazu mit einem Editor:

vim src/conf-cc

Dort hängt ihr an das Ende der ersten Zeile folgendes an:

--include /usr/include/errno.h

Nun sollte das Kompilieren des Quelltextes keine Probleme mehr ergeben:

sudo ./package/compile

Zuletzt muss noch die Installation angestoßen werden.

sudo ./package/install

Sollte die Installationsroutine melden, dass sie das Start-Up des svscanboot-Programms in die /etc/rc.local eingetragen hat, dann müsst ihr folgende Änderungen in dieser Datei noch übernehmen:

# By default this script does nothing.
#exit 0
bash -cf '/command/svscanboot &'
exit 0

Jetzt müsst ihr der rc.local Datei noch das x-Flag setzen:

sudo chmod +x /etc/rc.local

Neue Services einrichten

Bevor neue Services eingerichtet bzw. konfiguriert werden können, muss einmalig ein passender Ordner dazu angelegt werden. Ich habe mich für /etc/service entschieden:

sudo mkdir /etc/service
sudo chmod 1755 /etc/service

Ich werde im Folgenden die Erstellung eines neuen Services allgemein halten. Im Endeffekt müssen nur die Parameter zum Ausführen des entsprechenden Programms geändert werden.

Man erstellt zunächst einige neue Ordner und Dateien

sudo mkdir -p /etc/service/SERVICENAME/log/main
sudo touch /etc/service/SERVICENAME/run
sudo touch /etc/service/SERVICENAME/log/run

Den beiden Dateien müssen dann noch die korrekten Rechte verpasst werden:

sudo chmod 700 /etc/service/SERVICENAME/run
sudo chmod 700 /etc/service/SERVICENAME/log/run

Die run-Dateien bestimmen jeweils was ausgeführt wird. Die einfachere von beiden ist die run-Datei im „log“ Verzeichnis. Deren Inhalt ist bei fast allen anzulegenden Services gleich. Die folgenden Zeilen müssen in die /etc/service/SERVICENAME/log/run Datei:

#!/bin/bash
exec multilog t ./main

Diese Datei weist multilog an, im Verzeichnis „log/main“ die Logs des Services zu verwalten. Die Option „t“ schreibt vor jede Logzeile einen Timestamp.

Als nächstes müssen wir das auszuführende Programm in der zweiten run-Datei ( /etc/service/SERVICENAME/run ) festlegen. Der Inhalt dieser run-Datei ist etwas umfangreicher, kann jedoch in fast allen Fällen wiederverwendet werden:

#!/bin/bash
HOME="/home/otheruser"
USER="otheruser"
cd $HOME
exec 2>&1
exec setuidgid otheruser Programm

In diesem Fall gehe ich davon aus, dass man das Programm später nicht als Root sondern als low-rights-User ausführen möchte. Dazu passt man die zwei Umgebungsvariablen entsprechend an. Die fünfte Zeile leitet alle Stderr-Ausgaben auf die Stdout-Ausgabe um, damit auch die Errors später im log/main-Verzeichnis auftauchen.

In der letzten Zeile wird das Programm mit den Rechten (setuidgid) des low-rights-Users ausgeführt. Man sollte dabei darauf achten, dass sich das Programm selbst nicht in den Hintergrund verabschiedet. In einem solchen Fall denkt nämlich der Supervisor, dass das Programm beendet wurde, und startet es neu.

Hat man die beiden run-Dateien erfolgreich bearbeitet fehlt ein letzter Schritt, um das Programm als Service laufen zu lassen. Man muss einen finalen Symlink durchführen:

sudo ln -s /etc/service/SERVICENAME /service/SERVICENAME

Danach sollte der Supervisor den Service starten. Ob das Programm mitspielt und erfolgreich gestartet ist, zeigt ein Aufruf von svstat:

sudo svstat /service/SERVICENAME

Führt den letzten Befehl einige Male aus, und wenn die Lebensdauer des Prozesses 10 Sekunden übersteigt, sollte alles in Ordnung sein. Dies lässt sich ggf. mit einem Blick in die /etc/service/SERVICENAME/log/main/current Logdatei bestätigen.

Services steuern

Zum Steuern der Services nutzen wir im Allgemeinen das Programm „svc“. Dieses bietet die folgenden Optionen:

  • -u: Up. If the service is not running, start it. If the service stops, restart it.
  • -d: Down. If the service is running, send it a TERM signal and then a CONT signal. After it stops, do not restart it.
  • -o: Once. If the service is not running, start it. Do not restart it if it stops.
  • -p: Pause. Send the service a STOP signal.
  • -c: Continue. Send the service a CONT signal.
  • -h: Hangup. Send the service a HUP signal.
  • -a: Alarm. Send the service an ALRM signal.
  • -i: Interrupt. Send the service an INT signal.
  • -t: Terminate. Send the service a TERM signal.
  • -k: Kill. Send the service a KILL signal.
  • -x: Exit. supervise will exit as soon as the service is down. If you use this option on a stable system, you’re doing something wrong; supervise is designed to run forever.

Wenn ihr demnach einen Service stoppen wollt, dann führt ihr folgende Zeile aus:

sudo svc -d /service/SERVICENAME

Möchtet ihr den Service wieder starten, dann entsprechend folgendes:

sudo svc -u /service/SERVICENAME

Die Optionen können auch kombiniert werden. Der folgende Befehl startet einen Service neu:

sudo svc -du /service/SERVICENAME

Einen Service löschen

Wenn man einen Daemon nicht mehr benötigt, muss man die Löschung der Dateien folgendermaßen durchführen:

cd /service/SERVICENAME
sudo rm /service/SERVICENAME
sudo svc -dx . log
sudo rm -rf /etc/service/SERVICENAME

Wir wechseln über den Symlink in das Verzeichnis /etc/service/SERVICENAME. Danach löschen wir den Symlink, über den wir dort hin gekommen sind. Danach beenden wir den Service, sowie den dazugehörigen Supervisor-Prozess. Zuletzt löschen wir die angelegten Konfigurationsdateien, welche wir nun nicht mehr benötigen.

Fazit

Die Daemontools von Bernstein können sehr hilfreich sein, um Programme einfacher zu kontrollieren bzw. als Service laufen zu lassen. Die Einrichtung der Tools ist relativ einfach, genauso wie das konfigurieren von neuen Services.

~Sebastian