Viele regelmäßig Aufgaben erledigen Admins mit Script, die per Cron gestartet werden. Solange sich das Zeitmuster im Format von Cron eingeben läßt, ist das alles kein Problem.
- 0 9 * * * = Jeden Tag um 9 Uhr
- 30 14 * * 1-5 = Wochentags um 14:30 Uhr
Aber was, wenn ein Script z.B. am letzten Freitag im Monat gestartet werden soll? Das läßt sich in diesem Muster nicht darstellen. Es gibt aber ein paar einfache Tricks, die in Kombination zum Ziel dieser Aufgabe führen.
Trick 1: Kommandos mit && Verknüpfen
Mehrere Kommandos lassen sich mit && verknüpfen. Die Shell führt dabei das zweite Kommando nur aus, wenn das erste Kommando erfolgreich war (Exitcode 0):
/usr/local/daten_einsammeln.sh && /usr/local/daten_verarbeiten.sh
Somit kann man die Ausführung des zweiten Scripts (Verarbeiten der Daten) vom Erfolg des ersten Scripts (Sammeln der Daten) abhängig machen.
Trick 2: Abfragen ohne if mit [[ und ]]
Man kann mit [[ und ]] Bedingungen erstellen, ohne ‚if‘ einzusetzen. Ist die Bedingung erfüllt, wird Exitcode 0 zurückgemeldet. In Kombination mit Trick 1 läßt sich so eine bedingte Ausführung realisieren, ohne mit if-then-fi arbeiten zu müssen:
[[ bedingung ]] && kommando
Trick 3: Letzten Tag finden
Sucht man den letzten Freitag im Monat, so kann man das ganz einfach in eine Bedingung packen:
- date -d ‚1 week‘ ‚+%m‘ ergibt den Monat des heutigen Datums.
- date -d ‚1 week‘ ‚+%m‘ ergibt den Monat des Datums in genau einer Woche.
Jetzt einfache mathematische Logik: Wenn der Monat in genau einer Woche anders ist als heute, dann ist der heutige Wochentag der letzte in diesem Monat vorkommende.
Anders gesagt: Wenn wir in 7 Tagen in einem anderen Monat sind UND heute Freitag ist, dann ist heute der letzte Freitag im Monat.
Kombination der Tricks
Wir starten einen Cronjob jeden Freitag und nutzen den Trick 2, um das Kommando nur auszuführen, wenn eine Bedingung erfüllt ist. Die Bedingung ist aus Trick 3, wir prüfen nämlich, ob nächsten Freitag schon ein neuer Monat ist. Das sieht so aus:
[[ $(/bin/date -d '1 week' '+%m') -ne $(/bin/date '+%m') ]] && kommando
Somit haben wir einen Cronjob, der jeden Freitag gestartet wird, aber das gewünschte Kommando jeweils nur am letzten Freitag des Monats ausführt.
Hier eine Beispieldatei (/etc/cron.d/abrechnung), die Cron so akzeptieren wird:
MAILTO="cronjobs@butschek.de" PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" # +--------------------------------------------- Minute (0-59) # | +-------------------------------------- Stunde (0-24) # | | +------------------------------- Kalendertag (1-31) # | | | +------------------------ Monat (1-12) # | | | | +----------------- Wochentag (1-7 = Mo-So) # | | | | | +---------- Benutzer (z.B. root) # | | | | | | +--- Kommando (Pfad + Filename) # | | | | | | | # Abrechnung am Letzten Freitag im Monat starten 30 10 * * 5 root [[ $(/bin/date -d '1 week' '+%m') -ne $(/bin/date '+%m') ]] && /usr/local/abrechnung # | | | | | | | # | | | | | | +--- Kommando (Pfad + Filename) # | | | | | +---------- Benutzer (z.B. root) # | | | | +----------------- Wochentag (1-7 = Mo-So # | | | +------------------------ Monat (1-12) # | | +------------------------------- Kalendertag (1-31) # | +-------------------------------------- Stunde (0-24) # +--------------------------------------------- Minute (0-59)