Muszę utworzyć zadanie CRON, które będzie uruchamiane ostatniego dnia każdego miesiąca. Stworzę go za pomocą cPanel.
Każda pomoc jest mile widziana. Dzięki
Muszę utworzyć zadanie CRON, które będzie uruchamiane ostatniego dnia każdego miesiąca. Stworzę go za pomocą cPanel.
Każda pomoc jest mile widziana. Dzięki
Odpowiedzi:
Prawdopodobnie najłatwiej jest po prostu wykonać trzy oddzielne zadania:
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
Będzie to jednak działać 28 lutego, nawet w latach przestępnych, więc jeśli to jest problem, musisz znaleźć inny sposób.
Jednak zazwyczaj znacznie łatwiejsze i poprawne jest uruchamianie zadania tak szybko, jak to możliwe pierwszego dnia każdego miesiąca, z czymś takim:
0 0 1 * * myjob.sh
i zmodyfikuj skrypt, aby przetwarzał dane z poprzedniego miesiąca.
Eliminuje to wszelkie problemy, które możesz napotkać przy ustalaniu, który dzień jest ostatnim dniem miesiąca, a także zapewnia, że wszystkie dane z tego miesiąca są dostępne, zakładając, że przetwarzasz dane. Bieganie od pięciu minut do północy ostatniego dnia miesiąca może spowodować, że przegapisz wszystko, co wydarzy się między tą chwilą a północą.
W każdym razie jest to typowy sposób wykonywania większości prac na koniec miesiąca.
Jeśli nadal naprawdę chcesz go uruchomić ostatniego dnia miesiąca, jedną z opcji jest po prostu wykrycie, czy jutro jest pierwsze (w ramach skryptu lub w samej tabeli crontab).
A więc coś takiego:
55 23 28-31 * * [[ "$(date --date=tomorrow +\%d)" == "01" ]] && myjob.sh
powinien być dobrym początkiem, zakładając, że masz stosunkowo inteligentny date
program.
Jeśli Twój date
program nie jest wystarczająco zaawansowany, aby podać daty względne, możesz po prostu ułożyć bardzo prosty program, aby podać jutrzejszy dzień miesiąca (nie potrzebujesz pełnej mocy date
), na przykład:
#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;
}
a następnie użyj (zakładając, że nazwałeś to tomdom
„jutrzejszym dniem miesiąca”):
55 23 28-31 * * [[ "$(tomdom)" == "1" ]] && myjob.sh
Chociaż możesz rozważyć dodanie funkcji sprawdzania błędów, ponieważ oba time()
i mktime()
mogą zwrócić, -1
jeśli coś pójdzie nie tak. Powyższy kod ze względu na prostotę nie bierze tego pod uwagę.
Istnieje nieco krótsza metoda, której można użyć podobnie do jednej z powyższych. To jest:
[ $(date -d +1day +%d) -eq 1 ] && echo "last day of month"
Ponadto wpis crontab może zostać zaktualizowany, aby sprawdzać tylko od 28 do 31, ponieważ nie ma sensu uruchamiać go w inne dni miesiąca. Co dałoby ci:
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
a data POSIX nie obsługuje "-d +1day"
: - \ Bardziej skomplikowanym (i brzydkim) rozwiązaniem byłoby:[ `date +\%d` -eq `cal | xargs echo | awk '{print $NF}'` ] && myscript.sh
Skonfiguruj zadanie cron, aby było uruchamiane pierwszego dnia miesiąca. Następnie zmień zegar systemowy na jeden dzień do przodu.
Adaptując rozwiązanie paxdiablo, biegam 28 i 29 lutego. Dane z 29 stycznia zastępują 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
?
Możesz skonfigurować zadanie crona do uruchamiania każdego dnia miesiąca i uruchomić skrypt powłoki, taki jak poniżej. Ten skrypt sprawdza, czy numer jutrzejszego dnia jest mniejszy niż dzisiejszy (tj. Czy jutro jest nowy miesiąc), a następnie robi, co chcesz.
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
Niektóre implementacje crona obsługują flagę „L”, która reprezentuje ostatni dzień miesiąca.
Jeśli masz szczęście, że korzystasz z jednej z tych implementacji, jest to tak proste, jak:
0 55 23 L * ?
Będzie to działać ostatniego dnia każdego miesiąca o 23:55.
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"
W przypadku implementacji cron AWS Cloudwatch (planowanie lambdas itp.) Działa to:
55 23 L * ? *
Wyświetlanie o godzinie 23:55 ostatniego dnia każdego miesiąca.
00 23 * * * [[ $(date +'%d') -eq $(cal | awk '!/^$/{ print $NF }' | tail -1) ]] && job
Sprawdź powiązane pytanie na forum unix.com.
Możesz po prostu połączyć wszystkie odpowiedzi w jednej linii crona i użyć tylko date
polecenia.
Wystarczy sprawdzić różnicę między dniem miesiąca, który jest dzisiaj i jutro:
0 23 * * * root [ $(expr $(date +\%d -d '1 days') - $(date +\%d) ) -le 0 ] && echo true
Jeśli ta różnica jest poniżej 0, oznacza to, że zmieniamy miesiąc i jest ostatni dzień miesiąca.
55 23 28-31 * * echo "[ $(date -d +1day +%d) -eq 1 ] && my.sh" | /bin/bash
A co z tym?
edytuj .bashprofile
dodawanie użytkownika :
export LAST_DAY_OF_MONTH=$(cal | awk '!/^$/{ print $NF }' | tail -1)
Następnie dodaj ten wpis do crontab:
mm hh * * 1-7 [[ $(date +'%d') -eq $LAST_DAY_OF_MONTH ]] && /absolutepath/myscript.sh
Ostatni dzień miesiąca może przypadać na 28-31, w zależności od tego, jaki jest miesiąc (luty, marzec itp.). Jednak w każdym z tych przypadków następny dzień jest zawsze pierwszym dniem następnego miesiąca. Możemy więc użyć tego, aby upewnić się, że wykonujemy zadanie zawsze ostatniego dnia miesiąca, używając poniższego kodu:
0 8 28-31 * * [ "$(date +%d -d tomorrow)" = "01" ] && /your/script.sh