linux - minutos - ¿Cómo se le ordena a cron que ejecute un trabajo cada dos semanas?
ejecutar crontab manualmente (10)
Me gustaría ejecutar un trabajo a través de cron que se ejecutará cada segundo martes a una hora determinada del día. Para cada martes es fácil:
0 6 * * Tue
¿Pero cómo hacerlo en "cada segundo martes" (o si lo prefiere, cada dos semanas)? No me gustaría implementar ninguna lógica en el script en sí mismo, pero mantengo la definición solo en cron.
Responder
Modifique su lógica cron de martes para ejecutar cada dos semanas desde la época .
Sabiendo que hay 604800 segundos en una semana (ignorando los cambios de horario de verano y los segundos de salto, gracias) y usando la fecha de GNU:
0 6 * * Tue expr `date +/%s` / 604800 /% 2 >/dev/null || /scripts/fortnightly.sh
Aparte
La aritmética del calendario es frustrante.
La respuesta de @xahtep es excelente, pero como dice @Doppelganger en los comentarios , fallará en ciertos límites de años. Ninguno de los especificadores de la " date
del año" de la utilidad de date
puede ayudar aquí. Algunos martes a principios de enero, inevitablemente, se repetirá la paridad de la semana del último martes del año anterior: 2016-01-05 (% V), 2018-01-02 (% U) y 2019-01-01 (% W) .
Descubrí algunas limitaciones adicionales de los enfoques anteriores que pueden fallar en algunos casos extremos. Por ejemplo, considere:
@xahtep y @Doppelganger discutieron problemas usando
%W
en ciertos límites de años anteriores.La respuesta de @ pilcrow se acerca hasta cierto punto, sin embargo, también fallará en ciertos límites. Las respuestas en este u otros temas relacionados usan la cantidad de segundos en un día (frente a la semana), que también fallan en ciertos límites por las mismas razones.
Esto se debe a que estos enfoques se basan en la hora UTC (fecha +% s). Considere un caso en el que estamos ejecutando un trabajo a la 1 a.m. y a las 10 p.m. cada 2do martes.
Supongamos que GMT-2:
- 1:00 hora local = 11:00 UTC de ayer
- 22:00 hora local = 8:00 UTC de hoy
Si solo estamos comprobando una sola vez cada día, esto no será un problema, pero si lo estamos verificando varias veces, o si estamos cerca de la hora UTC y se producen ahorros de luz diurna, el script no consideraría estos como el mismo día.
Para evitar esto, tenemos que calcular una compensación de UTC basada en nuestra zona horaria local no UTC. No pude encontrar una manera simple de hacer esto en BASH, así que desarrollé una solución que usa un trazador de líneas rápido en Perl para calcular el desplazamiento de UTC en segundos.
Este script aprovecha la fecha +% z, que emite la zona horaria local.
Guión Bash:
TZ_OFFSET=$( date +%z | perl -ne ''$_ =~ /([+-])(/d{2})(/d{2})/; print eval($1."60**2") * ($2 + $3/60);'' )
DAY_PARITY=$(( ( `date +%s` + ${TZ_OFFSET} ) / 86400 % 2 ))
luego, para determinar si el día es par o impar:
if [ ${DAY_PARITY} -eq 1 ]; then
...
else
...
fi
¿Por qué no algo así como
0 0 1-7,15-21,29-31 * 5
¿Es eso apropiado?
¿Qué pasa cada 3ª semana?
Aquí está mi sugerencia:
0 6 * * Tue expr `date +/%W` /% 3 == 0 > /dev/null || /scripts/fortnightly.sh
... o ...
0 6 * * Tue expr `date +/%W` /% 3 == 1 > /dev/null || /scripts/fortnightly.sh
... o por supuesto ...
0 6 * * Tue expr `date +/%W` /% 3 == 2 > /dev/null || /scripts/fortnightly.sh
... dependiendo de la rotación de la semana.
Cron proporciona una sintaxis de "todos los demás" "/ 2". Simplemente siga el campo de unidad de tiempo apropiado con "/ 2" y ejecutará el cronjob ''cada dos veces''. En tu caso...
0 6 * * Tue/2
Lo anterior debe ejecutarse cada dos martes.
La sintaxis "/ 2" no coincide con el día de la semana. Entonces, mi agregado al inteligente de arriba es simplemente usar 1,15 en MonthDay archivado.
0 6 1,15 * * /scripts/fornightly.sh> / dev / null 2> & 1
Qué tal esto, lo mantiene en el crontab
incluso si no está exactamente definido en los primeros cinco campos:
0 6 * * Tue expr `date +/%W` /% 2 > /dev/null || /scripts/fortnightly.sh
Si quieres todos los martes de la segunda semana solamente:
00 06 * * 2 # 2
Tal vez un poco tonto, pero también se podrían crear dos cronjobs, uno por cada primer martes y uno por cada tercio.
Primer cronjob:
0 0 8 ? 1/1 TUE#1 *
Segundo cronjob:
0 0 8 ? 1/1 TUE#3 *
No estoy seguro acerca de la sintaxis aquí, utilicé http://www.cronmaker.com/ para hacer esto.
La respuesta de Pilcrow es genial. Sin embargo, resulta en el script quincenal.sh que se ejecuta cada semana par (desde la época). Si necesita que el script se ejecute en semanas impares , puede modificar un poco su respuesta:
0 6 * * Tue expr /( `date +/%s` / 604800 + 1 /) /% 2 > /dev/null || /scripts/fortnightly.sh
Cambiar el 1 a un 0 lo moverá de nuevo a semanas pares.