Expresiones CRON.
0. Índice de contenidos.
1. Introducción
A veces nos las hemos visto y nos las hemos deseado para configurar «bien» una tarea programada, os lanzo una pregunta :
¿A cuántos de vosotros os ha salido bien a la primera el configurar la planificación de una tarea?
Si sois de los privilegiados que lo conseguís no me queda otra que daros la enhorabuena ;-), en cambio si pertenecáis al resto
de los mortales, es decir, si habeis tenido que realizar un millón y medio de pruebas cambiando la fecha y hora del sistema/servidor, espero
ayudaros con este tutorial para no tener que dedicar tanto tiempo.
¿Quá es una expresión CRON?
Una expresión CRON es una cadena de texto compuesta por 6 o 7 campos separados por un espacio en blanco que se utiliza para representar
instantes o periodos de tiempo.
Su principal uso recae en la planificación de ejecuciones de procesos / rutinas programadas, por lo que puede tener diferentes usos
dentro del ámbito de la empresa , como por ejemplo : ejecución de procesos batch, envio de newsletters a primera hora de la mañana, etc.
Si alguno es un usuario de Unix seguro que todo esto le suena, ya que cron es una herramienta que siempre ha estado incluida y que por
lo tanto ha tenido una amplia comunidad que lo ha utilizado y probado.En mi caso todavía no conozco a nadie que lo haya utilizado y que
no le haya gustado ;-).
Se que este tipo de expresiones se utilizan en numeros sitios, pero en mi caso particular casi siempre he tenido que utilizarlas con
el framework de Quartz
¿Quá es Quartz?
Quartz es un framework Java para la planificación de tareas, que destaca sobre todo
por su potencia y sencillez,esta potencia le viene dada por sus amplias posibilidades de configuración.
Para introduciros un poco más en Quartz os dire que se basa en tres conceptos :
- Job : Tarea que se desea ejecutar
- Trigger : Disparador que le indica la forma en la que se ejecutará el job
- Scheduler : Responsable de ejecutar las tareas mediante su configuración en los trigger.
Conviene diferencias los tipos de trigger que hay :
- SimpleTrigger : Disparador que se utiliza para ejecutar tareas en una fecha determinada, una hora, un nº de repeticiones o bien
un intervalor entre repeticiones. - CronTrigger : Disparador más utilizado ya que permite realizar expresiones para referirnos a instantes o periodos de tiempo más complejos
De los dos disparadores anteriores nosotros utilizaremos para nuestras expresiones CRON los del tipo CronTrigger.
Si quereis saber más sobre este framework os aconsejo visitar el siguiente tutorial que ha sido realizado por mi compañero
Carlos García Perez : Planificación de tareas en Java mediante Quartz
El objetivo de este tutorial es enseñaros a definir bien vuestras expresiones CRON con independencia del lugar donde se use, por lo que los siguientes puntos
serán totalmente teóricos.
2. Formato.
Para comenzar a explicar su formato primero recordar que una expresión CRON no es otra cosa que una cadena de texto compuesta por 6 o 7 campos
separados por espacios en blanco.
Los campos tienen un orden concreto a la hora de indicar a que nos estamos refiriendo.
«Segundos» «Minutos» «Horas» «Día del mes» «Mes» «Día de la semana» «Año»
Los campos pueden contener alguno de los valores permitidos que se indicarán en la siguiente tabla.
Los campos pueden contener valores permitidos sobre los que se aplican diferentes combinaciones de carecteres especiales con el objetivo
de dotarles de nuevas características
Campo | ¿Es obligatorio? | Valores Permitidos | Caracteres especiales |
Segundos | SI | 0-59 | , – * / |
Minutos | SI | 0-59 | , – * / |
Horas | SI | 0-23 | , – * / |
Día del mes | SI | 1-31 | , – * ? / L W |
Mes | SI | 1-12 o JAN-DEC | , – * / |
Día de la semana | SI | 1-7 o SUN-SAT | , – * ? / L # |
Año | NO | Vacio | 1970-2099 | , – * / |
Importante : Recordar que las semanas comienzan en Domingo (valor 1)
3. Caracteres especiales.
En este punto se explicarán los caracteres especiales que de utilizarán con los diferentes campos sobre los que
se permite su aplicación.
- * : Selecciona todos los valores de un campo (por ejemplo cada hora, cada minuto)
- ? : Selecciona sin un valor específico cuando se puede utilizar (es similar a decir cualquiera)
- – : Selecciona rango de valores (por ejemplo 4-6 que es de 4 a 6)
- , : Selecciona valores específicos (por ejemplo MON,WED,FRI es decir los lunes, miárcoles y viernes )
- / : Selecciona incrementos a partir del primer valor (por ejemplo 0/15 que es cada 15 minutos comenzando desde el minuto 0 -> 15, 30 ,45)
- L (Día del mes) : Selecciona el último día del mes
- L (Día de la semana) : Selecciona el último día de la semana (7 / sabado / SAT)
- XL (Día de la semana) : Seleccona el último día de ese tipo del mes (por ejemplo 6L -> el último viernes del mes)
- W : Selecciona el día de la semana (de lunes a viernes) más cercano al día (weekday)
- LW : Selecciona el último weekday del mes
- # : Selecciona la posición de un día del mes (por ejemplo 6#3 -> el tercer viernes del mes)
4. Ejemplos.
En este punto se detallarán algunos ejemplos de expresiones CRON
Expresión CRON | Descripción |
15 * * * * ? | Se ejecuta cada 15 segundos |
15 0 0 * * ? | Se ejecuta a las 00:00:15 |
0 15 * * * ? | Se ejecuta cada 15 minutos |
0 0 15 * * ? | Se ejecuta cada día a las 15:00:00 |
0 15 15 ? * * | Se ejecuta cada día a las 15:15:00 |
0 15 15 * * ? | Se ejecuta cada día a las 15:15:00 |
0 15 15 * * ? * | Se ejecuta cada día a las 15:15:00 |
0 15 15 * * ? 2010 | Se ejecuta cada día a las 15:15:00 durante el 2010 |
0 0/15 15 * * ? | Se ejecuta cada 15 minutos a partir de las 15:00:00 |
0 10/15 15 * * ? | Se ejecuta cada 15 minutos a partir de las 15:10:00 |
0 0/15 15,17 * * ? | Se ejecuta cada 15 minutos a partir de las 15:00:00 hasta las 17:45:00 |
0 0-15 15 * * ? | Se ejecuta cada 15 minutos empezando a las 15:00:00 y terminando a las 15:15:00 |
0 15,25 15 * * ? | Se ejecuta a las 15:15:00 y a las 15:25:00 |
0 15 15 2 * ? | Se ejecuta a las 15:15:00 del día 2 de cada mes |
0 15 15 2 4 ? | Se ejecuta a las 15:15:00 del día 2 del mes de abril |
0 15 15 ? 4 FRI | Se ejecuta a las 15:15:00 de cada viernes del mes de abril |
0 15 15 ? * MON-FRI | Se ejecuta a las 15:15:00 de lunes a viernes |
0 15 15 L * ? | Se ejecuta a las 15:15:00 del último día de cada mes |
0 15 15 ? * 6L | Se ejecuta a las 15:15:00 del último viernes del mes |
0 15 15 ? * 6L 2010 | Se ejecuta a las 15:15:00 del último viernes del mes durante el 2010 |
0 15 15 ? * 6L 2008-2010 | Se ejecuta a las 15:15:00 del último viernes del mes entre el 2008 y el 2010 |
0 15 15 ? * 6#2 | Se ejecuta a las 15:15:00 el segundo viernes de cada mes |
0 15 15 1/5 * ? | Se ejecuta a las 15:15:00 cada 5 dias a partir del primer dia del mes |
5. Conclusiones.
Espero haberos podido ayudar a tener un poco más claro lo que son estas expresiones, para que sirven y sobre todo como implementarlas de forma correcta.
Para cualquier duda ya sabes que me podéis enviar un correo
Un saludo.
Víctor
Hola.
Buen tutorial, pero te saco un error. El 4º ejemplo es erróneo.
0 15 * * * ? Se ejecuta cada 15 minutos
Eso no se ejecuta cada 15 minutos sino cada minuto 15:00 de cada hora.
Lo correcto (para Se ejecuta cada 15 minutos) :
0 0/15 * * * ? (Se ejecuta los minutos 0,15,30 y 45 de cada hora.)
Corrígeme si me equivoco pero creo que es así.
Muchas gracias por compartir Víctor, pero ¿Y si lo que deseo es ejecutar algo EXCEPTO el último día de mes?
He probado esto, en dos sistemas Red Hat Enterprise Linux Server release 6.3 (Santiago) y en uno funciona y en otro no:
50 23 * * * [[ $(date +\\\’%d\\\’) -ne $(cal | awk \\\’!/^$/{ print $NF }\\\’ | tail -1) ]] && /ruta_absoluta/blabla.sh
Incluso en el sistema que falla, si ejecuto a mano:
[[ $(date +\\\’%d\\\’) -ne $(cal | awk \\\’!/^$/{ print $NF }\\\’ | tail -1) ]] && /ruta_absoluta/blabla.sh
funciona perfectamente pero si lo planifico con crontab me dice que
From: root@waspro1.localdomain (Cron Daemon)
To: was@waspro1.localdomain
Subject: Cron [[ $(date +\\\’
Content-Type: text/plain; charset=UTF-8
Auto-Submitted: auto-generated
X-Cron-Env:
X-Cron-Env:
X-Cron-Env:
X-Cron-Env:
X-Cron-Env:
Message-Id:
Date: Fri, 25 Apr 2014 12:50:01 +0200 (CEST)
/bin/sh: -c: line 0: unexpected EOF while looking for matching `\\\’\\\’
/bin/sh: -c: line 1: unexpected token `▒\\\’ in conditional command
/bin/sh: -c: line 1: syntax error: unexpected end of file
De locos, vamos. Algo debo estar haciendo mal pero llevo toda la mañana y no soy capaz de descubrirlo.
Podrías hacer algo como 50 23 * * * 1-29 si te sirve, claro que no es totalmente eficiente ya que algunos meses tienen 31 días. pero a mi me funciona cuando no puedo ejecutar la tarea en los cierres de nomina de mi empresa.
Muchas gracias por la explicación tan clara 10/10 puntos para este articulo.
Hola Victor espero y me puedas ayudar.
Lo que intento hacer es que en de 6 dìas se borre mi tabla que la tengo en SQL y me cree otra con los mismos campo, pero como hago para que eso se ejecute automaticamente,
eclipse
sql
te agradeceria mucho si me puedes ayudar
Nota : estaba usando un Truncate pero no me deja ya que tengo una llave foranea.
0 15 15 ? * MON-FRI Se ejecuta a las 15:15:00 de lunes a viernes
¿Por qué MON-FRI está en el último lugar?
Quisiera saber si podrías ayudarme con algunas dudas ya que no logrado solucionar….
lo primero es lo que aparece en el siguiente foro http://stackoverflow.com/questions/34547113/quartz-how-can-i-use-injection
lo segundo es poder saber como hago para ver el estado de un job,cron,proceso o como quieras llamarlo, ya que yo ejecuto la programación y este llama a 2 procesos almacenados en la base de datos… se ejecuta el primer proceso y al terminar ejecuta el segundo todo bajo el mismo job…. pero si el proceso esta croneado para que se ejecute cada 5 minutos por ejemplo pero no ha terminado la ejecutante de estos dos proceso, no quiero se vuelva a ejecutar, porque necesito que termine antes de empezar nuevamente…. no se si entiendes….
Agradecería mucho que me pudieses ayudar…. Desde ya muchas gracias
Erik Parra
Si quiero que se ejecute a la 1 y a las 8:30, seria algo así?
0 0,30 1,8 * * ?
http://www.cronmaker.com/ te paso un generador automatico, espero que te funcione
Solo hay una pequeña falla también en el primero de los ejemplos.
Para que se ejecute cada 15 segundos, la manera correcta debe:
0/15 * * * * ?
Saludos.
Hola Victor, muy buena entrada.
Tengo una duda y si quiero que se ejecute cada minuto «0 0/1 * * * ?» pero que solo se ejecute siempre y cuando no este ya en ejecución?
Muchas gracias, un saludo
Una consulta, que pasa si programo para que se ejecute todos los 31 de todos los meses. Como haría para los meses que tienen 30 días y/o en el caso de febrero que solo tiene 28 o 29 días. Este se ejecuta el último día del meses o solo lo obvia?
Tengo un pequeño problema, quiero que algo se ejecute cada X minutos, a partir de una hora específica. por ejemplo: cada 20min a partir de las 12:50.
Entendería que la forma de expresar sería así:0 50/20 * ? * * *
El problema está en que se calendariza de ésta manera:
1. Tuesday, August 8, 2017 12:50 PM
2. Tuesday, August 8, 2017 1:50 PM
No se como hacer para que en lugar e que se ejecue a la 1:50, se ejecute a la 1:10 como debería…
Está todo mal
Hola!
muchas gracias por el aporte, quisera preguntar que pasa si el usuario quiere guardar una tarea programada para todos los dias 30 del mes, pero llega febrero que solo tiene 28 dias y no se ejecuta, quisiera saber si puedo hacer esa excepcion (que si es febrero se ejecute el 28 y no el 30) dentro de la exprecion cron, o tengo que añadirle esa logica a mi codigo en java.
Si puedo hacerlo dentro de la exprecion CRON como se podria hacer?
Hola, estoy varias intentando esta expresión, podrían ayudarme o decirme si es que se puede o no?
Quiero plasmar «Todos los domingos entre los días del 11 al 31 de cada mes a las 7am.»