it-swarm.com.de

So planen Sie den ersten Sonntag im Monat

Ich benutze Bash auf RedHat. Ich muss einen Cron-Job einplanen, der jeden ersten Sonntag im Monat um 9:00 Uhr ausgeführt wird. Wie kann ich das machen?

49
ring bearer

Sie können so etwas in die crontab -Datei einfügen:

00 09 * * 7 [ $(date +\%d) -le 07 ] && /run/your/script

Das date +%d gibt Ihnen die Nummer des aktuellen Tages an, und Sie können dann überprüfen, ob der Tag kleiner oder gleich 7 ist. Führen Sie in diesem Fall Ihren Befehl aus.

Wenn Sie dieses Skript nur sonntags ausführen, sollte dies bedeuten, dass es nur am ersten Sonntag des Monats ausgeführt wird.

Denken Sie daran, dass in der Datei crontab die Formatierungsoptionen für den Befehl date maskiert werden sollten.

130
Lukasz Stelmach

Sie müssen zwei Ansätze kombinieren:

a) Verwenden Sie cron, um jeden Sonntag um 9:00 Uhr einen Job auszuführen.

 00 09 * * 7     /usr/local/bin/once_a_week

b) Zu Beginn von once_a_week, berechne das Datum und extrahiere den Tag des Monats über Shell, Python, C/C++, ... und teste, dass zwischen 1 und 7 liegt. Wenn ja, führen Sie das eigentliche Skript aus. wenn nicht, leise beenden.

12

Es ist erwähnenswert, dass der offensichtlichste Ansatz für dieses Problem nicht funktioniert.

Sie könnten denken, Sie könnten einfach einen crontab-Eintrag schreiben, der den Wochentag als 0 (für Sonntag) und den Monatstag als 1-7 angibt, wie folgt ...

# This does NOT work.
0 9 1-7 * 0 /path/to/your/script

... aber aufgrund von eine Exzentrizität in der Art, wie Cron mit Crontab-Zeilen mit Angabe von Wochentag und Monatstag umgeht funktioniert dies nicht und wird tatsächlich fortgesetzt am 1., 2., 3., 4., 5., 6. und 7. des Monats (unabhängig davon, welcher Wochentag sie sind) und am jeden Sonntag des Monats.

Aus diesem Grund wird die Empfehlung angezeigt, mit einem [ ... ] - Häkchen bei date eine Regel wie diese einzurichten. Geben Sie entweder den Wochentag in der Crontab an und verwenden Sie [ und date , um zu überprüfen, ob der Tag des Monats <= 7 ist, bevor das Skript ausgeführt wird (siehe akzeptierte Antwort) , oder geben Sie den Bereich für den Tag des Monats in der Registerkarte crontab an und überprüfen Sie den Wochentag vor der Ausführung mit [ und date wie folgt:

# This DOES work.
0 9 1-7 * * [ $(date +\%u) = 7 ] && /path/to/your/script

Einige Best Practices, die Sie beachten sollten, wenn Sie sicherstellen möchten, dass Ihre Crontab-Linie funktioniert unabhängig davon unter welchem ​​Betriebssystem Sie sie verwenden:

  • Verwenden Sie zum Vergleich = Und nicht ==. Es ist portabler, da nicht alle Shells eine Implementierung von [ Verwenden, die den Operator == Unterstützt.
  • Verwenden Sie den Bezeichner %u Für date, um den Wochentag als Zahl abzurufen, nicht den Operator %a, Da %a Je nach Ergebnis unterschiedliche Ergebnisse liefert Das Gebietsschema date wird ausgeführt.
  • Verwenden Sie einfach date, nicht /bin/date Oder /usr/bin/date, Da das Dienstprogramm date auf verschiedenen Systemen unterschiedliche Positionen hat.
6
Mark Amery

Führe eine Cron-Aufgabe am 1. Montag, 3. Dienstag, letzten Sonntag usw. aus.

http://xr09.github.io/cron-last-sunday/

Setzen Sie einfach die run-if-today Skript im Pfad und benutze es mit cron.

30 6 * * 6 root run-if-today 1 Sat && /root/myfirstsaturdaybackup.sh

Das run-if-today script gibt nur 0 zurück (Bash-Wert für True), wenn es das richtige Datum ist.

BEARBEITEN:

Jetzt mit einfacherer Oberfläche, nur ein Parameter für die Wochennummer.

# run every first saturday
30 6 * * 6 root run-if-today 1 && /root/myfirstsaturdaybackup.sh

# run every last sunday
30 6 * * 7 root run-if-today L && /root/lastsunday.sh
5
MGP

Dies funktioniert auch mit Namen der Wochentage:

0 0 1-7 * * [ "$(date '+\%a')" == "Sun" ] && /usr/local/bin/urscript.sh

Aber,

[ "$(date '+\%a')" == "Sun" ] && echo SUNDAY

wird [~ # ~] fehlschlagen [~ # ~] im Kommando wegen spezieller Behandlung von "%" in crontab (auch gültig für https://stackoverflow.com/a/3242169/2919695 )

4
maniac_on_moon

Wenn Sie nicht möchten, dass cron Ihren Job jeden Tag oder jeden Sonntag ausführt, können Sie einen Wrapper schreiben, der Ihren Code ausführt, den nächsten ersten Sonntag festlegt und die Ausführung an diesem Datum einplant.

Planen Sie dann diesen Wrapper für den nächsten ersten Sonntag des Monats. Danach erledigt es alles selbst.

Der Code würde ungefähr so ​​lauten (Betonung auf etwas ... keine Fehlerprüfung durchgeführt):

#! /bin/bash
#We run your code first
/path/to/your/code
#now we find the next day we want to run
nskip=28 #the number of days we want to check into the future
curr_month=`date +"%m"`
new_month=`date --date='$nskip days' +"%m"`
if [[ curr_month = new_month ]] 
then
((nskip+=7))
fi
date=`date --date='$nskip days' +"09:00AM %D` #you may need to change the format if you use another scheduler
#schedule the job using "at"
at -m $date < /path/to/wrapper/code

Die Logik ist einfach, den nächsten ersten Sonntag zu finden. Da wir am ersten Sonntag des aktuellen Monats beginnen, werden wir durch Hinzufügen von 28 entweder am letzten Sonntag des aktuellen Monats oder am ersten Sonntag des nächsten Monats platziert. Wenn es der aktuelle Monat ist, werden wir auf den nächsten Sonntag (der in der ersten Woche des nächsten Monats liegt) erhöht.

Und ich habe "at" verwendet. Ich weiß nicht, ob das betrügt. Die Hauptidee ist jedoch, den nächsten ersten Sonntag zu finden. Sie können danach den gewünschten Scheduler ersetzen, da Sie das Datum und die Uhrzeit kennen, zu der der Job ausgeführt werden soll (ein anderer Scheduler benötigt jedoch möglicherweise eine andere Syntax für das Datum).

0
user390948

verwenden Sie möglicherweise cron.hourly, um ein anderes Skript aufzurufen. Dieses Skript prüft dann, ob es der erste Sonntag im Monat und 9 Uhr morgens ist. Führen Sie in diesem Fall Ihr Programm aus. Klingt für mich optimal genug :-).

0
gtrak