Devo creare un lavoro CRON che verrà eseguito l'ultimo giorno di ogni mese. Lo creerò usando cPanel.
Qualsiasi aiuto è apprezzato. Grazie
Devo creare un lavoro CRON che verrà eseguito l'ultimo giorno di ogni mese. Lo creerò usando cPanel.
Qualsiasi aiuto è apprezzato. Grazie
Risposte:
Forse il modo più semplice è fare semplicemente tre lavori separati:
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
Tuttavia, funzionerà il 28 febbraio, anche negli anni bisestili, quindi, se questo è un problema, dovrai trovare un altro modo.
Tuttavia, di solito è sostanzialmente più facile e corretto eseguire il lavoro il prima possibile il primo giorno di ogni mese, con qualcosa del tipo:
0 0 1 * * myjob.sh
e modificare lo script per elaborare i dati del mese precedente .
Ciò elimina qualsiasi problema che potresti incontrare nel capire quale giorno è l'ultimo del mese e garantisce anche che tutti i dati per quel mese siano disponibili, supponendo che tu stia elaborando i dati. L'esecuzione da cinque minuti a mezzanotte dell'ultimo giorno del mese potrebbe farti perdere tutto ciò che accade tra allora e la mezzanotte.
Questo è il solito modo per farlo comunque, per la maggior parte dei lavori di fine mese.
Se ancora davvero desidera eseguire l'ultimo giorno del mese, una possibilità è quella di rilevare semplicemente se domani è il primo (sia come parte dello script, oppure nel crontab stesso).
Quindi, qualcosa come:
55 23 28-31 * * [[ "$(date --date=tomorrow +\%d)" == "01" ]] && myjob.sh
dovrebbe essere un buon inizio, ammesso che tu abbia un date
programma relativamente intelligente .
Se il tuo date
programma non è abbastanza avanzato da darti date relative, puoi semplicemente mettere insieme un programma molto semplice per darti il giorno del mese di domani (non hai bisogno di tutta la potenza di date
), come ad esempio:
#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;
}
e poi usa (supponendo che tu l'abbia chiamato tomdom
"giorno del mese di domani"):
55 23 28-31 * * [[ "$(tomdom)" == "1" ]] && myjob.sh
Anche se potresti prendere in considerazione l'aggiunta del controllo degli errori poiché entrambi time()
e mktime()
possono tornare -1
se qualcosa va storto. Il codice precedente, per motivi di semplicità, non ne tiene conto.
C'è un metodo leggermente più breve che può essere utilizzato simile a uno di quelli sopra. Questo è:
[ $(date -d +1day +%d) -eq 1 ] && echo "last day of month"
Inoltre, la voce crontab potrebbe essere aggiornata per controllare solo dal 28 al 31 poiché è inutile eseguirla negli altri giorni del mese. Che ti darebbe:
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
e la data POSIX non supporta "-d +1day"
: - \ Una soluzione più complicata (e brutta) sarebbe:[ `date +\%d` -eq `cal | xargs echo | awk '{print $NF}'` ] && myscript.sh
Imposta un cron job da eseguire il primo giorno del mese. Quindi cambia l'orologio del sistema in modo che sia un giorno avanti.
Che ne dici di questo, dopo Wikipedia?
55 23 L * * /full/path/to/command
Adattando la soluzione di paxdiablo, corro il 28 e 29 febbraio. I dati del 29 sovrascrivono il 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
?
È possibile impostare un cron job da eseguire ogni giorno del mese e farlo eseguire uno script di shell come il seguente. Questo script determina se il numero del giorno di domani è inferiore a quello di oggi (cioè se domani è un nuovo mese) e poi fa quello che vuoi.
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
Alcune implementazioni di cron supportano il flag "L" per rappresentare l'ultimo giorno del mese.
Se sei fortunato ad utilizzare una di queste implementazioni, è semplice come:
0 55 23 L * ?
Sarà eseguito alle 23:55 dell'ultimo giorno di ogni mese.
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"
Per l'implementazione di cron di AWS Cloudwatch (Scheduling Lambdas, ecc.) Funziona:
55 23 L * ? *
In esecuzione alle 23:55 dell'ultimo giorno di ogni mese.
00 23 * * * [[ $(date +'%d') -eq $(cal | awk '!/^$/{ print $NF }' | tail -1) ]] && job
Controlla una domanda correlata sul forum unix.com.
Puoi semplicemente connettere tutte le risposte in una riga cron e usarle solo date
comando.
Basta controllare la differenza tra il giorno del mese che è oggi e sarà domani:
0 23 * * * root [ $(expr $(date +\%d -d '1 days') - $(date +\%d) ) -le 0 ] && echo true
Se questa differenza è inferiore a 0 significa che cambiamo il mese e c'è l'ultimo giorno del mese.
55 23 28-31 * * echo "[ $(date -d +1day +%d) -eq 1 ] && my.sh" | /bin/bash
Che dire di questo?
modifica l' .bashprofile
aggiunta dell'utente :
export LAST_DAY_OF_MONTH=$(cal | awk '!/^$/{ print $NF }' | tail -1)
Quindi aggiungi questa voce a crontab:
mm hh * * 1-7 [[ $(date +'%d') -eq $LAST_DAY_OF_MONTH ]] && /absolutepath/myscript.sh
L'ultimo giorno del mese può essere 28-31 a seconda del mese in cui si trova (febbraio, marzo ecc.). Tuttavia, in entrambi i casi, il giorno successivo è sempre il primo del mese successivo. Quindi possiamo usarlo per assicurarci di eseguire un lavoro sempre l'ultimo giorno di un mese utilizzando il codice seguente:
0 8 28-31 * * [ "$(date +%d -d tomorrow)" = "01" ] && /your/script.sh