Benutzer-Werkzeuge

Webseiten-Werkzeuge


Seitenleiste

Was fehlt?

Es liegt in der Natur der Sache: Ein Wiki ist niemals fertig. Wir geben uns große Mühe, mit der Entwicklung Schritt zu halten; lassen Supportanfragen direkt in neue Artikel einfließen … aber auch wir sind nicht perfekt. Wenn du hier nicht fündig wirst: Nicht schmollen - Bescheid sagen! Unter hallo@uberspace.de steht dir unser Team gerne bereit. Hand drauf!

system:runwhen

runwhen

runwhen von Paul Jarc ist eine praktische Cron-Alternative, die gegenüber klassischen Cronjobs viele Vorteile bietet:

  • Keine Kollisionen. Man kann diesen Punkt gar nicht oft genug betonen. Jeder, der schon einmal einen Cronjob verfasst hat, der z.B. alle fünf Minuten laufen sollte und der dann aber für einen Durchlauf länger als fünf Minuten braucht, hat gesehen, wie ärgerlich es ist, wenn mehrere Instanzen eines Cronjobs gleichzeitig laufen (nehmen wir zum Beispiel einen Job, der Newsletter verschickt, mit dem Versand aber einige Stunden beschäftigt ist und währenddessen alle fünf Minuten weitere Instanzen startet, die ebenfalls anfangen, den gleichen Newsletter an die gleichen Empfänger zu verschicken …).
  • Sekundengenaue Ausführung. Mit Cron können Jobs maximal minutengenau ausgeführt werden; runwhen arbeitet sekundengenau. Es ist also kein Problem, einen Job mehrmals in der Minute laufen zu lassen, beispielsweise, weil er die Verfügbarkeit eines Dienstes prüfen soll und Probleme nicht erst nach einer Minute bemerken soll.
  • Integriertes Logging. runwhen-Jobs laufen unter den daemontools und können sich dessen Fähigkeit, sämtliche Ausgaben direkt in einen Logging-Prozess zu schicken, zunutze machen.
  • Auskunft, wann die nächste Ausführung stattfindet. Unmittelbar beim Start wird ins Logfile geschrieben, wann die nächste Ausführung des Scripts zu erwarten ist. Damit siehst du sofort, ob das von dir gewählte Zeitschema korrekt angegeben wurde.
  • „Mach's sofort“-Feature. Du hast jederzeit die Möglichkeit, einen Job jetzt sofort anzustoßen, ungeachtet der eigentlich geplanten Zeit. Dabei läuft der Job unter exakt der gleichen Umgebung wie sonst auch, was jeden freuen dürfte, der schon mal darüber gestolpert ist, dass unter Cron das Set an Umgebungsvariablen nicht völlig identisch zu dem der Login-Shell ist.
  • Temporäres Pausieren. Wie alle Jobs, die unter den Daemontools laufen, kannst du mit einem einzigen svc-Aufruf weitere Ausführungen temporär unterbinden und später jederzeit wieder aktivieren.

Aus Sicht eines Systemadministrators - also aus unserer Sicht - können wir noch ergänzen, dass es im Gegensatz zu Cron ohne ein setuid-Programm wie crontab auskommt und dass es keinen zentralen Daemon benötigt. Zurecht fragt der Autor nach dem Sinn von Konfigurationsdateien wie /etc/cron.allow, wenn doch ein zeitgesteuerter Job eigentlich nicht mehr ist als …

(sleep 1234 && do-some-command) &

… in entsprechend regelmäßigen Wiederholungen, was nun wirklich jeder ohne irgendeinen Daemon ausführen kann.

Das Prinzip

runwhen-Scripts laufen unter den daemontools und machen sich deren Eigenschaft zunutze, dass ein Job, der sich beendet, automatisch neu gestartet wird. Jener Job sieht insofern so aus:

  1. Berechne die Anzahl der Sekunden, bis der nächste Zeitpunkt nach dem gewählten Zeitschema eintritt
  2. Warte die Anzahl dieser Sekunden
  3. Führe das gewünsche Programm aus
  4. Beende dich, auf dass du von den daemontools neu gestartet wirst

Einfach - aber effektiv! Die Hauptarbeit erledigt das Programm rw-match, das für die Berechnung der Wartedauer da ist. rw-sleep übernimmt das Warten und die anschließende Ausführung. Zusätzliche Programme ermöglichen noch eine feinere Beeinflussung der Wartezeit, um beispielsweise bestimmte Minimalwerte nicht zu unter- oder bestimmte Maximalwerte nicht zu überschreiten. Paul Jarc stellt ein komplexes Beispiel bereit. In der Regel reicht es aber, sich auf eine einfache Berechnung der Wartezeit zu beschränken.

So funktioniert's

Wir stellen dir das Script runwhen-conf bereit, das dir einen fertigen Job anlegt, in dem du nur noch dein Zeitschema einstellen musst und ihn dann in dein ~/service-Verzeichnis verlinken musst. Wenn du noch kein eigenes ~/service-Verzeichnis besitzt, so musst du dir zunächst eins anlegen. Du kannst es nicht nur für runwhen, sondern auch noch für viele andere Sachen benutzen. In aller Kürze reicht dafür ein Befehl:

[sandra@xenon ~]$ test -d ~/service || uberspace-setup-svscan

Erledigt? Prima, dann können wir weitermachen. Im konkreten Fall wollen wir das Programm ~/bin/reminder.pl einmal täglich ausführen lassen (bitte beachte, dass das Programm ausführbar sein muss, also ein chmod +x erfahren haben muss). Der Service soll den Namen reminder bekommen. Und so sieht das aus:

[sandra@xenon ~]$ runwhen-conf ~/etc/run-reminder ~/bin/reminder.pl --parameter1 --parameter2
Creating the service directories... done
Creating the run script... done
Creating the log/run script... done
Setting restrictive permissions on directories and scripts... done

The service is now nearly set up, but two steps are missing:

* Set the time when you want to run the job through setting the variable
  RUNWHEN within /home/sandra/etc/run-reminder/run

* Put a symlink pointing to the service directory into a directory that is
  monitored by svscan, for example:
  ln -s /home/sandra/etc/run-reminder /service

Entsprechend der Anweisungen bearbeiten wir nun das Script /home/sandra/etc/run-reminder/run mit einem beliebigen Texteditor. Im Kopf wird bereits die Variable RUNWHEN definiert, nur eben mit leerem Wert. Darunter befindet sich direkt eine kleine Dokumentation, welche Möglichkeiten hier bestehen.

Jede zeitliche Bedingung beginnt mit einem Komma („,“), dann der Angabe der Einheit (z.B. „H“ für Stunde) und dann der Bedingung (z.B. „=14“ für „um 14 Uhr“ oder „/2“ für „alle 2 Stunden“). Für eine tägliche Ausführung um 14 Uhr müsstest du also setzen:

RUNWHEN=",H=14"

Kombinationen sind ebenfalls möglich - soll der Job um 14:30 Uhr laufen, kannst du Stunde und Minute definieren:

RUNWHEN=",H=14,M=30"

Du möchtest, dass der Job nur am 3., 6., 9. … eines Monats, jeweils um 14:30 Uhr läuft? Auch das ist kein Problem:

RUNWHEN=",d/3,H=14,M=30"

Oder vielleicht um Mitternacht des drittletzten Tags eines Monats?

RUNWHEN=",d-3"

Das Prinzip dürfte klar sein. Was dann noch fehlt, ist, den Service zu starten, in dem er per Symlink nach ~/service verlinkt wird:

ln -s ~/etc/run-reminder ~/service/reminder

Innerhalb von 5 Sekunden nimmt der Job seine Tätigkeit auf. Ein Blick ins Logfile verrät den Zeitpunkt der nächsten Ausführung (hier bei RUNWHEN=„,H=9,M=30“:

[sandra@xenon ~]$ tail -f ~/service/reminder/log/main/current | tai64nlocal
2011-03-04 00:18:14.130403500 next run time: 2011-03-04 09:30:00.000000000

Möchtest du den Job jetzt sofort starten, kannst du ihm mittels svc ein ALRM-Signal senden - rw-sleep nimmt das zum Anlass, die restliche Wartezeit unter den Tisch fallen zu lassen und den Job sofort zu starten:

[sandra@xenon ~]$ svc -a ~/service/reminder

Pausieren und Entfernen

Du kannst alle normalen svc-Kommandos auf deine runwhen-Jobs anwenden. Ein …

[sandra@xenon ~]$ svc -d ~/service/reminder

… beispielsweise schaltet den Job aus; er wird dann nicht mehr ausgeführt. Das ist beispielsweise bei häufig laufenden Jobs praktisch, wenn du zwischendurch Änderungen vornehmen möchtest und währenddessen nicht willst, dass der Job weiterhin läuft. Willst du ihn dann wieder starten, sendest du ihm ein up-Signal:

[sandra@xenon ~]$ svc -u ~/service/reminder

Möchtest du einen runwhen-Job stoppen und komplett entfernen, kannst du genauso vorgehen wie bei jedem anderen unter den daemontools laufenden Service - schau dort einfach in der Doku im Abschnitt Einen Daemon entfernen.

system/runwhen.txt · Zuletzt geändert: 2016/08/03 23:34 von uber