automation - tareas - El trabajo de Cron se ejecutará el último día del mes
programador de tareas linux (13)
¿Qué hay de este, después de Wikipedia?
55 23 L * * /full/path/to/command
Necesito crear un trabajo cron que se ejecutará el último día del mes. Lo crearé desde cpanel.
Cualquier ayuda es apreciada. Gracias
¿Qué hay de esto?
editar la adición de .bashprofile
del usuario:
export LAST_DAY_OF_MONTH=$(cal | awk ''!/^$/{ print $NF }'' | tail -1)
A continuación, agregue esta entrada a crontab:
mm hh * * 1-7 [[ $(date +''%d'') -eq $LAST_DAY_OF_MONTH ]] && /absolutepath/myscript.sh
Adaptando la solución de paxdiablo, corro los días 28 y 29 de febrero. La información del 29 sobrescribe la 28ma.
# 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
Configure una tarea cron para que se ejecute el primer día del mes. Luego cambie el reloj del sistema para que esté un día por delante.
Hay un método ligeramente 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 del crontab podría actualizarse para verificar solo el 28vo al 31vo puesto que no tiene sentido ejecutarlo los otros días del mes. Lo cual te daría:
0 23 28-31 * * [ $(date -d +1day +%d) -eq 1 ] && myscript.sh
Para la implementación cron de AWS Cloudwatch (programación de Lambdas, etc.) esto funciona:
55 23 L * ? *
Corriendo a las 11:55 p.m. el último día de cada mes.
Para un método más seguro en un crontab basado en la solución @Indie (el uso de la ruta absoluta a la date
+ $()
no funciona en todos los sistemas crontab):
0 23 28-31 * * [ `/bin/date -d +1day +/%d` -eq 1 ] && myscript.sh
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 los años bisiestos, por lo que, si eso es un problema, tendrá que 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 modifique la secuencia de comandos para procesar los datos del mes anterior .
Esto elimina cualquier problema que pueda surgir al determinar qué día es el último del mes y también garantiza que todos los datos para ese mes estén disponibles, suponiendo que está procesando datos. Correr a los cinco minutos hasta la medianoche del último día del mes puede hacer que te pierdas de todo lo que sucede entre entonces 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 desea ejecutarlo el último día del mes, una opción es simplemente detectar si mañana es el primero (ya sea como parte de su secuencia de comandos o en el propio crontab).
Entonces, algo como:
55 23 28-31 * * [[ "$(date --date=tomorrow +/%d)" == "01" ]] && myjob.sh
debería ser un buen comienzo, suponiendo que tiene un programa de date
relativamente inteligente.
Si su programa de date
no es 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 la 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 agregar comprobación de errores, ya que tanto time()
como mktime()
pueden devolver -1
si algo sale mal. El código anterior, por razones de simplicidad, no tiene eso en cuenta.
Puede configurar una tarea cron para que se ejecute todos los días del mes y hacer que ejecute un script de shell como el siguiente. Esta secuencia de comandos 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 usted desea.
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
Puede simplemente conectar todas las respuestas en una línea cron y usar solo el comando de date
.
Simplemente marque la diferencia entre el día del mes que es hoy y será mañana:
0 23 * * * root [ $(expr $(date +/%d -d ''1 days'') - $(date +/%d) ) -le 0 ] && echo true
Si la diferencia es inferior a 0, significa que cambiamos el mes y el último día del mes.
Algunas implementaciones de cron admiten la bandera "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 p.m. el ú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"
00 23 * * * [[ $(date +''%d'') -eq $(cal | awk ''!/^$/{ print $NF }'' | tail -1) ]] && job
Mira una pregunta relacionada en el foro de Unix.com.