Necesito crear un trabajo CRON que se ejecutará el último día de cada mes. Lo crearé usando cPanel.
Se agradece cualquier ayuda. Gracias
Necesito crear un trabajo CRON que se ejecutará el último día de cada mes. Lo crearé usando cPanel.
Se agradece cualquier ayuda. Gracias
Respuestas:
Posiblemente, la forma más fácil es simplemente hacer tres trabajos separados:
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
Sin embargo, eso se ejecutará el 28 de febrero, incluso en años bisiestos, por lo que, si eso es un problema, deberá encontrar otra forma.
Sin embargo, generalmente es mucho más fácil y correcto ejecutar el trabajo lo antes posible el primer día de cada mes, con algo como:
0 0 1 * * myjob.sh
y modificar el script para procesar los datos del mes anterior .
Esto elimina cualquier molestia que pueda encontrar al determinar qué día es el último del mes y también garantiza que todos los datos de ese mes estén disponibles, suponiendo que esté procesando datos. Correr cinco minutos antes de la medianoche del último día del mes puede hacer que se pierda todo lo que suceda entre esa hora y la medianoche.
Esta es la forma habitual de hacerlo de todos modos, para la mayoría de los trabajos de fin de mes.
Si todavía realmente desea que se ejecute en el último día del mes, una opción es simplemente detectar si mañana es el primero (ya sea como parte de su script, o en el crontab en sí).
Entonces, algo como:
55 23 28-31 * * [[ "$(date --date=tomorrow +\%d)" == "01" ]] && myjob.sh
debería ser un buen comienzo, asumiendo que tiene un date
programa relativamente inteligente .
Si su date
programa no está lo suficientemente avanzado como para darle fechas relativas, puede armar un programa muy simple para darle el día del mes de mañana (no necesita toda la potencia de date
), como por ejemplo:
#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;
}
y luego use (suponiendo que lo haya llamado tomdom
para "el día de mañana del mes"):
55 23 28-31 * * [[ "$(tomdom)" == "1" ]] && myjob.sh
Aunque es posible que desee considerar la adición de comprobación de errores, ya que ambos time()
y mktime()
puede regresar -1
si algo va mal. El código anterior, por razones de simplicidad, no lo tiene en cuenta.
Hay un método un poco más corto que se puede usar de manera similar a uno de los anteriores. Es decir:
[ $(date -d +1day +%d) -eq 1 ] && echo "last day of month"
Además, la entrada crontab podría actualizarse para verificar solo del 28 al 31, ya que no tiene sentido ejecutarla los otros días del mes. Lo que te daría:
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
y la fecha POSIX no es compatible "-d +1day"
: - \ Una solución más complicada (y fea) sería:[ `date +\%d` -eq `cal | xargs echo | awk '{print $NF}'` ] && myscript.sh
Configure un trabajo cron para que se ejecute el primer día del mes. Luego, cambie el reloj del sistema para que esté un día adelantado.
¿Qué pasa con este, después de Wikipedia?
55 23 L * * /full/path/to/command
Adaptando la solución de paxdiablo, corro los días 28 y 29 de febrero. Los datos del 29 sobrescriben al 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
?
Puede configurar un trabajo cron para que se ejecute todos los días del mes y hacer que ejecute un script de shell como el siguiente. Este script determina si el número del día de mañana es menor que el de hoy (es decir, si mañana es un mes nuevo), y luego hace lo que quieras.
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
Algunas implementaciones de cron admiten el indicador "L" para representar el último día del mes.
Si tiene suerte de utilizar una de esas implementaciones, es tan simple como:
0 55 23 L * ?
Eso se ejecutará a las 11:55 pm del último día de cada mes.
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"
Para la implementación de cron de AWS Cloudwatch (programación de Lambdas, etc.), esto funciona:
55 23 L * ? *
Se ejecuta a las 11:55 p. M. Del último día de cada mes.
00 23 * * * [[ $(date +'%d') -eq $(cal | awk '!/^$/{ print $NF }' | tail -1) ]] && job
Consulte una pregunta relacionada en el foro de unix.com.
Puede conectar todas las respuestas en una línea cron y usar solo date
comando.
Simplemente verifique la diferencia entre el día del mes que es hoy y mañana:
0 23 * * * root [ $(expr $(date +\%d -d '1 days') - $(date +\%d) ) -le 0 ] && echo true
Si esta diferencia está por debajo de 0 significa que cambiamos el mes y hay último día del mes.
55 23 28-31 * * echo "[ $(date -d +1day +%d) -eq 1 ] && my.sh" | /bin/bash
¿Qué pasa con esto?
editar la .bashprofile
adición del usuario :
export LAST_DAY_OF_MONTH=$(cal | awk '!/^$/{ print $NF }' | tail -1)
Luego agregue esta entrada a crontab:
mm hh * * 1-7 [[ $(date +'%d') -eq $LAST_DAY_OF_MONTH ]] && /absolutepath/myscript.sh
El último día del mes puede ser 28-31 dependiendo de qué mes sea (febrero, marzo, etc.). Sin embargo, en cualquiera de estos casos, el día siguiente es siempre el primero del mes siguiente. Entonces podemos usar eso para asegurarnos de que ejecutamos algún trabajo siempre el último día de un mes usando el siguiente código:
0 8 28-31 * * [ "$(date +%d -d tomorrow)" = "01" ] && /your/script.sh