Ich muss einen CRON-Job erstellen, der am letzten Tag eines jeden Monats ausgeführt wird. Ich werde es mit cPanel erstellen.
Jede Hilfe wird geschätzt. Vielen Dank
Ich muss einen CRON-Job erstellen, der am letzten Tag eines jeden Monats ausgeführt wird. Ich werde es mit cPanel erstellen.
Jede Hilfe wird geschätzt. Vielen Dank
Antworten:
Möglicherweise ist der einfachste Weg, einfach drei separate Jobs zu erledigen:
55 23 30 4,6,9,11 * myjob.sh
55 23 31 1,3,5,7,8,10,12 * myjob.sh
55 23 28 2 * myjob.sh
Das wird jedoch am 28. Februar laufen, auch in Schaltjahren. Wenn dies ein Problem ist, müssen Sie einen anderen Weg finden.
In der Regel ist es jedoch wesentlich einfacher und korrekter, den Job so schnell wie möglich am ersten Tag eines jeden Monats auszuführen. Dabei gilt Folgendes:
0 0 1 * * myjob.sh
und ändern Sie das Skript, um das vorherige zu verarbeiten Monat Daten.
Dies beseitigt alle Probleme, die auftreten können, wenn Sie herausfinden, welcher Tag der letzte des Monats ist, und stellt außerdem sicher, dass alle Daten für diesen Monat verfügbar sind, vorausgesetzt, Sie verarbeiten Daten. Wenn Sie am letzten Tag des Monats zwischen fünf Minuten und Mitternacht laufen, verpassen Sie möglicherweise alles, was zwischen diesem Zeitpunkt und Mitternacht passiert.
Dies ist ohnehin die übliche Vorgehensweise für die meisten Jobs am Monatsende.
Wenn du noch wirklich es am letzten Tag des Monats ausgeführt werden sollen, ist eine Option, einfach zu erkennen , ob morgen die ersten (entweder als Teil des Skripts oder in dem crontab selbst) ist.
Also so etwas wie:
55 23 28-31 * * [[ "$(date --date=tomorrow +\%d)" == "01" ]] && myjob.sh
sollte ein guter Anfang sein, vorausgesetzt, Sie haben ein relativ intelligentes date
Programm.
Wenn Ihr date
Programm nicht weit genug fortgeschritten ist, um Ihnen relative Daten zu geben, können Sie einfach ein sehr einfaches Programm zusammenstellen, um Ihnen den morgigen Tag des Monats zu geben (Sie benötigen nicht die volle Leistung von date
), wie zum Beispiel:
#include <stdio.h>
#include <time.h>
int main (void) {
// Get today, somewhere around midday (no DST issues).
time_t noonish = time (0);
struct tm *localtm = localtime (&noonish);
localtm->tm_hour = 12;
// Add one day (86,400 seconds).
noonish = mktime (localtm) + 86400;
localtm = localtime (&noonish);
// Output just day of month.
printf ("%d\n", localtm->tm_mday);
return 0;
}
und dann verwenden (vorausgesetzt, Sie haben es tomdom
für "morgigen Tag des Monats" genannt):
55 23 28-31 * * [[ "$(tomdom)" == "1" ]] && myjob.sh
Obwohl Sie da beide prüfen , sollten die Fehlerprüfung Hinzufügen time()
und mktime()
zurückgeben kann , -1
wenn etwas schief geht. Der obige Code berücksichtigt dies aus Gründen der Einfachheit nicht.
Es gibt eine etwas kürzere Methode, die ähnlich wie die oben beschriebene verwendet werden kann. Das ist:
[ $(date -d +1day +%d) -eq 1 ] && echo "last day of month"
Außerdem könnte der Crontab-Eintrag so aktualisiert werden, dass er nur am 28. bis 31. überprüft wird, da es sinnlos ist, ihn an den anderen Tagen des Monats auszuführen. Welches würde Ihnen geben:
0 23 28-31 * * [ $(date -d +1day +%d) -eq 1 ] && myscript.sh
/bin/sh: -c: line 1: unexpected EOF while looking for matching ')'
.
[ $(date -d +1day +\%d) -eq 1 ] && run_job
posix
und das POSIX-Datum unterstützt nicht "-d +1day"
: - \ Eine kompliziertere (und hässlichere) Lösung wäre:[ `date +\%d` -eq `cal | xargs echo | awk '{print $NF}'` ] && myscript.sh
Richten Sie einen Cron-Job ein, der am ersten Tag des Monats ausgeführt wird. Ändern Sie dann die Uhr des Systems so, dass sie einen Tag voraus ist.
Was ist mit diesem nach Wikipedia?
55 23 L * * /full/path/to/command
Ich passe die Lösung von paxdiablo an und laufe am 28. und 29. Februar. Die Daten vom 29. überschreiben den 28 ..
# min hr date month dow
55 23 31 1,3,5,7,8,10,12 * /path/monthly_copy_data.sh
55 23 30 4,6,9,11 * /path/monthly_copy_data.sh
55 23 28,29 2 * /path/monthly_copy_data.sh
,29
.
55 23 28 2
?
Sie können einen Cron-Job einrichten, der an jedem Tag des Monats ausgeführt wird, und ein Shell-Skript wie das folgende ausführen lassen. Dieses Skript ermittelt, ob die Nummer des morgigen Tages kleiner als die des heutigen Tages ist (dh ob morgen ein neuer Monat ist), und macht dann, was Sie wollen.
TODAY=`date +%d`
TOMORROW=`date +%d -d "1 day"`
# See if tomorrow's day is less than today's
if [ $TOMORROW -lt $TODAY ]; then
echo "This is the last day of the month"
# Do stuff...
fi
Einige Cron-Implementierungen unterstützen das "L" -Flag, um den letzten Tag des Monats darzustellen.
Wenn Sie das Glück haben, eine dieser Implementierungen zu verwenden, ist dies so einfach wie:
0 55 23 L * ?
Das läuft jeden letzten Tag im Monat um 23.55 Uhr.
http://www.quartz-scheduler.org/documentation/quartz-1.x/tutorials/crontrigger
#########################################################
# Memory Aid
# environment HOME=$HOME SHELL=$SHELL LOGNAME=$LOGNAME PATH=$PATH
#########################################################
#
# string meaning
# ------ -------
# @reboot Run once, at startup.
# @yearly Run once a year, "0 0 1 1 *".
# @annually (same as @yearly)
# @monthly Run once a month, "0 0 1 * *".
# @weekly Run once a week, "0 0 * * 0".
# @daily Run once a day, "0 0 * * *".
# @midnight (same as @daily)
# @hourly Run once an hour, "0 * * * *".
#mm hh Mday Mon Dow CMD # minute, hour, month-day month DayofW CMD
#........................................Minute of the hour
#| .................................Hour in the day (0..23)
#| | .........................Day of month, 1..31 (mon,tue,wed)
#| | | .................Month (1.12) Jan, Feb.. Dec
#| | | | ........day of the week 0-6 7==0
#| | | | | |command to be executed
#V V V V V V
* * 28-31 * * [ `date -d +'1 day' +\%d` -eq 1 ] && echo "Tomorrow is the first today now is `date`" >> ~/message
1 0 1 * * rm -f ~/message
* * 28-31 * * [ `date -d +'1 day' +\%d` -eq 1 ] && echo "HOME=$HOME LOGNAME=$LOGNAME SHELL = $SHELL PATH=$PATH"
Für die AWS Cloudwatch-Cron-Implementierung (Scheduling Lambdas usw.) funktioniert dies:
55 23 L * ? *
Laufen am letzten Tag eines jeden Monats um 23.55 Uhr.
00 23 * * * [[ $(date +'%d') -eq $(cal | awk '!/^$/{ print $NF }' | tail -1) ]] && job
Schauen Sie sich eine verwandte Frage im unix.com-Forum an.
Sie können einfach alle Antworten in einer Cron-Zeile verbinden und nur den date
Befehl verwenden.
Überprüfen Sie einfach den Unterschied zwischen dem Tag des Monats, der heute ist und morgen sein wird:
0 23 * * * root [ $(expr $(date +\%d -d '1 days') - $(date +\%d) ) -le 0 ] && echo true
Wenn diese Differenz unter 0 liegt, bedeutet dies, dass wir den Monat ändern und es den letzten Tag des Monats gibt.
55 23 28-31 * * echo "[ $(date -d +1day +%d) -eq 1 ] && my.sh" | /bin/bash
Was ist damit?
Benutzer .bashprofile
hinzufügen:
export LAST_DAY_OF_MONTH=$(cal | awk '!/^$/{ print $NF }' | tail -1)
Fügen Sie dann diesen Eintrag zu crontab hinzu:
mm hh * * 1-7 [[ $(date +'%d') -eq $LAST_DAY_OF_MONTH ]] && /absolutepath/myscript.sh
Der letzte Tag des Monats kann zwischen 28 und 31 liegen, je nachdem, um welchen Monat es sich handelt (Februar, März usw.). In beiden Fällen ist der nächste Tag jedoch immer der 1. des nächsten Monats. Damit können wir sicherstellen, dass wir immer am letzten Tag eines Monats einen Job ausführen, indem wir den folgenden Code verwenden:
0 8 28-31 * * [ "$(date +%d -d tomorrow)" = "01" ] && /your/script.sh