Jeden ersten Montag im Monat einen Cron-Job ausführen?


32

Ich möchte jeden ersten Montag im Monat um 8.30 Uhr einen Job von cron ausführen. Die Cron Wikipedia Seite sagt

Während der Job normalerweise ausgeführt wird, wenn die Zeit- / Datumsangaben alle mit der aktuellen Uhrzeit und dem aktuellen Datum übereinstimmen, gibt es eine Ausnahme: Wenn sowohl "Tag des Monats" als auch "Wochentag" eingeschränkt sind (nicht "*"), dann auch nicht Das Feld "Tag des Monats" (3) oder das Feld "Wochentag" (5) muss mit dem aktuellen Tag übereinstimmen.

(meine Betonung)

Bedeutet das, dass ich den ersten Montag des Monats nicht machen kann, ich kann nur den ersten (oder was auch immer) Tag des Monats machen? Ich kann mir keinen Ausweg vorstellen.


slhck - das klingt nach einer guten lösung - würde es dir etwas ausmachen, sie zu einer antwort mit dem vollständigen code zu erweitern? dann werde ich es als richtig markieren :)
Max Williams

Antworten:


39

Sie können die Bedingung in den aktuellen Befehl crontab einfügen:

[ "$(date '+%a')" = "Mon" ] && echo "It's Monday"

Wenn diese Bedingung an einem der ersten sieben Tage eines Monats erfüllt ist, haben Sie den ersten Montag. Beachten Sie, dass in der Crontab die Prozent-Syntax jedoch maskiert werden muss:

0   12  1-7 *   *   [ "$(date '+\%a')" = "Mon" ] && echo "It's Monday"

Ersetzen Sie den echoBefehl durch den tatsächlichen Befehl, den Sie ausführen möchten. Ich habe auch einen ähnlichen Ansatz gefunden .


eigentlich, slhck, habe ich zu früh gesprochen - das funktioniert nicht auf meiner crontab: es scheint aus irgendeinem grund ein problem mit dem datentest zu geben. Dies funktioniert in der Kommandozeile [ "$(date '+%a')" = "Mon" ] && echo "It's Monday"genauso wie [ $(date '+%a') = "Mon" ] && echo "It's Monday" in der Crontab. Bei diesem Test scheint es jedoch zu scheitern. Ich kann auch keine nützlichen Rückmeldungen von cron bekommen: Ich versuche [ "$(date '+%a')" = "Tue" ] >> /home/deploy/cron.log 2>&1, hiermit Fehlerausgaben in einem Protokoll festzuhalten, aber das funktioniert auch nicht: /
Max Williams,

Hm. Können Sie überprüfen, ob die dateAusgabe korrekt ist? Lassen Sie beispielsweise einen cronBefehl ausführen, der dies in eine Datei ausgibt: date '+%a' > ~/datetest 2>&1- Überprüfen Sie dann, ob die richtige Zeichenfolge zum Vergleich gefunden wurde.
Slhck

1
Ich fand das Problem - das Prozent +%aerforderlich entkommen , wenn es in der crontab war, dh die Linie notwendig , um dies zu sein: [ "$(date '+\%a')" = "Mon" ] && echo "It's Monday". Wenn Sie Ihre Antwort damit aktualisieren könnten, wäre es für zukünftige Leser hilfreich :) Nochmals vielen Dank - Max
Max Williams

Oh, jetzt verstehe ich warum. Ich bin froh, dass es jetzt funktioniert, danke, dass du es ausprobiert hast!
Slhck

14

Ich habe einen Computer mit einem Gebietsschema für Spanisch, daher funktioniert dieser Ansatz bei mir nicht, weil mein Tag auf Mittag wechselt

Andere Sprachen würden ebenfalls scheitern. Daher habe ich die akzeptierte Antwort leicht abgewandelt, um die Sprachbarriere zu überwinden:

 0 9 1-7 * *   [ "$(date '+\%u')" = "1" ] && echo "¡Es lunes!"

+1 ¡Muy Bien, Señor!
JakeGould

1
Gracias ¡Pura vida! ; D
Cumanacr

Dies sollte die akzeptierte Antwort sein. Ich habe ein niederländisches Gebietsschema, das auch unterschiedliche Namen für Wochentage verwendet. Die Verwendung von Zahlen fühlt sich auch sauberer an, als Zeichenfolgen zu vergleichen, um den Wochentag zu bestimmen.
0ne_Up

7

Ich finde es einfacher, wenn es nicht nötig ist, mit Tageszahlen umzugehen.

Führen Sie den ersten Montag im Monat aus:

0 2 * * 1 [ `date '+\%m'` == `date '+\%m' -d "1 week ago"` ] || /path/to/command

dh wenn der Monat vor 1 Woche nicht mit dem aktuellen Monat übereinstimmt, sind wir am 1. Tag 1 (= Montag) des Monats.

Ähnliches gilt für den dritten Freitag

0 2 * * 6 [ `date '+\%m'` == `date '+\%m' -d "3 weeks ago"` ] || /path/to/command

dh wenn der Monat vor 3 Wochen vom aktuellen Monat abweicht, sind wir am 3. Tag 6 (= Freitag) des Monats


Tag 6 der Woche ist Samstag, nicht Freitag.
Robert

4

Ich habe einen Auftrag für den 4. Montag eines jeden Monats um 16:00 Uhr wie folgt eingeplant:

0 16 22-28 * Mon [ "$(date '+\%a')" == "Mon" ] && touch /home/me/FourthMonOfMonth.txt

1

Soweit ich weiß, ist es NICHT möglich, nur crontab zu verwenden. Sie können jedoch eine Wrapper-Funktion verwenden, um den richtigen Tag aus einem Contab-Eintrag für die ersten sieben Tage im Monat auszuwählen. siehe dies vom Eintrag.

Das Wrapper-Skript wäre

#! /usr/bin/ksh
day=$(date +%d)
if ((day <= 7)) ; then
   exec somecommand
fi
exit 1

und Sie müssten es mit dem Eintrag crontab ausführen (vorausgesetzt, es heißt wrapper.sh und ist global verfügbar)

0 0 * * 1 wrapper.sh

danke elemaki. Ich habe über eine ähnliche Lösung nachgedacht, bei der ein zusätzlicher Code in der ausgeführten Task verwendet wird, um zu testen, ob es der erste Montag des Monats im Skript ist, und ihn dann jeden Montag in crontab aufzurufen. Es ist ein Ruby-Skript, so dass es einfach ist, den Wochentag zu testen. Aber ich hatte gehofft, es gäbe nur einen Crontab-Weg.
Max Williams

1

Unter Solaris 10 musste ich die Bedingung wie folgt formatieren:

[ `date +\%a` = "Sat" ] && echo "It's Saturday"

1

Sie können versuchen, Cronjob für die ersten sieben Tage des Monats auszuführen und es nur am Montag ausführen zu lassen.

30 8 * * 1 [`date +\%d` -le 07] && <job>

Oben sollte für Sie arbeiten.


+1 mehr Erfolgsration als in der ersten Woche und Prüfung für Montag. :-)
xmedeko

1

Ich empfehle zu verwenden

"$(/bin/date '+%\w')" = "1"

anstatt

"$(date '+\%a')" = "Mon"

um Probleme mit dem Gebietsschema zu vermeiden.


0

Ich habe eine allgemeine Lösung für diese Art von Problemen gefunden. Sie funktioniert für den ersten, zweiten, dritten ... letzten Wochentag des Monats.

Du kannst es so benutzen:

30 06 * * Mon run-if-today 1 "Mon" && echo "First Monday"
30 06 * * Thu run-if-today 3 "Thu" && echo "Third Thursday"
30 06 * * Sun run-if-today L "Sun" && echo "Last Sunday"

Das Skript prüft, ob der Wochentag und der gewünschte Wochentag übereinstimmen. Wenn beide übereinstimmen, wird 0 zurückgegeben, andernfalls 1.

Überprüfen Sie den Code hier. https://github.com/xr09/cron-last-sunday


0

Ich glaube, das löst das Problem eleganter:

30 8 1-7 * 1 /run/your/job.sh

1
Doh! : "Wenn beide Felder eingeschränkt sind (dh nicht *), wird der Befehl ausgeführt, wenn eines der Felder mit der aktuellen Zeit übereinstimmt."
Symcbean

Ebenfalls am 28. Februar wird es nicht alle 4 Jahre durchgeführt.
igraczech

"entweder" bedeutet eine von ihnen, nicht "beide". Dies wird jeden Tag für die ersten 7 Tage des Monats ausgeführt.
minus

Diese Reihe führte jeden ersten bis siebten Monat sowie jeden Montag einen Befehl aus
Tomasz Jakub Rup

0

Da ich meine cron-Anweisungen mit php und js interpretiere, kann ich bash nicht verwenden. Schließlich fand ich , dass es ist in der Tat möglich , mit nur cron:

0 30 8 * 1/1 MON#1

Hoffe das hilft jemand anderem. Trotzdem wünsche ich Ihnen allen einen schönen Tag. :-)


Dies ist kein Cron, es ist möglicherweise Quarz
Sivann

-1
0 9 1-7 * 1 * 

Dies funktioniert jeden Montag im Monat.


Eine Antwort wurde akzeptiert, ist Ihre Antwort besser, anders oder nützlich für eine neuere Version usw.
mic84
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.