Generador y Lector de Expresiones Cron
*/15minute*hour*day of month*month*day of weekPróximas ejecuciones
tu hora localNada de lo que escribes aquí se almacena, registra ni comparte.
Escribe una expresión cron y ve las próximas horas en que se ejecutará de verdad. Cada campo se valida, y las programaciones que nunca pueden dispararse se señalan.
Cómo usarlo
- Escribe una expresión, o parte de un preajuste.
- Los cinco campos están etiquetados debajo para que veas cuál es cuál.
- Comprueba las próximas ejecuciones antes de desplegarla.
Los cinco campos
Una expresión cron estándar tiene cinco campos separados por espacios: minuto 0-59, hora 0-23, día del mes 1-31, mes 1-12 y día de la semana 0-7, donde tanto 0 como 7 significan domingo. Los meses y los días de la semana pueden escribirse con sus nombres en inglés de tres letras.
Cada campo admite las mismas cuatro construcciones. Un asterisco coincide con todos los valores. Una lista separada por comas coincide con cualquiera de ellos. Un rango con guion coincide con todo lo que hay entre sus extremos. Un paso con barra toma uno de cada n valores de un rango, así que */15 en el campo de minuto es cada cuarto de hora y 0-30/10 son los minutos 0, 10, 20 y 30.
Los atajos @hourly, @daily, @weekly, @monthly y @yearly se expanden a las expresiones evidentes y merece la pena usarlos cuando encajan, porque no hay forma de malinterpretarlos.
La regla del día del mes y el día de la semana
Es el comportamiento de cron que pilla a casi todo el mundo, y está en la especificación, no es casual. Cuando los campos de día del mes y de día de la semana están ambos restringidos - ninguno es un asterisco -, se combinan con O y no con Y.
Así que 0 0 1 * MON no significa el día 1 del mes cuando cae en lunes. Significa el día 1 de cada mes y, además, todos los lunes. Si solo quieres los lunes, el campo de día del mes debe ser un asterisco. Si solo quieres el día 1, el campo de día de la semana debe ser un asterisco. No existe una forma estándar de expresar la intersección con cinco campos, y la solución habitual es programar la unión y comprobar la fecha dentro del propio trabajo.
Es justo el caso que la lista de próximas ejecuciones está pensada para detectar. Leer los campos te dice lo que has escrito; leer las fechas te dice lo que va a pasar.
Zonas horarias y horario de verano
Las horas de ejecución que se muestran aquí están en la zona horaria de tu navegador. El servidor que ejecutará realmente el trabajo tiene la suya, a menudo UTC, y la diferencia entre ambas es una causa habitual de trabajos que se disparan a la hora equivocada. Comprueba la configuración del servidor, o el campo de zona horaria de tu planificador, antes de fiarte de una hora exacta.
El horario de verano añade un problema más serio. En una zona que lo aplica, un trabajo programado a las 02:30 no se ejecuta en absoluto la madrugada en que se adelantan los relojes, porque esa hora no existe, y se ejecuta dos veces la madrugada en que se atrasan. Para cualquier cosa en la que una ejecución perdida o duplicada importe - facturación, conciliación, envío de correos -, prográmalo en UTC o fuera de la franja de la una a las tres de la madrugada, que es cuando se producen los cambios.
Las implementaciones tampoco coinciden en qué hacer con los trabajos perdidos mientras una máquina estaba en reposo o apagada. Unas los omiten, otras los ejecutan al despertar y otras ejecutan de golpe todas las ocurrencias perdidas.
Extensiones que encontrarás en otros sitios
Cinco campos es el estándar, y es lo que aceptan cron en Linux, CronJob de Kubernetes y la mayoría de planificadores alojados. Varios sistemas muy usados lo amplían, y las expresiones copiadas entre ellos no siempre significan lo mismo.
Quartz, y con él el planificador de Spring, usa seis o siete campos al añadir los segundos al principio y un año opcional al final, así que una expresión de cinco campos pegada ahí se interpreta con todo desplazado una posición y se ejecuta a la hora equivocada en lugar de fallar. Quartz añade además L para último, W para el día laborable más cercano y # para el enésimo día de la semana del mes. Vixie cron, el estándar en Linux, añade @reboot. AWS EventBridge usa seis campos y exige que exactamente uno de los dos campos de día sea un signo de interrogación en lugar de un asterisco.
Esta herramienta valida y explica el estándar de cinco campos. Si tu planificador es uno de los anteriores, consulta su documentación antes de dar por hecho que una expresión significa lo mismo allí.
El entorno en el que realmente corre un cron
Fallan más tareas programadas por razones de entorno que por razones de programación horaria. Cron no carga el perfil de tu shell, así que el PATH es mínimo - a menudo solo /usr/bin y /bin - y un comando que funciona en tu terminal falla con command not found. La costumbre confiable es usar rutas absolutas para el intérprete y para el script, o definir el PATH de forma explícita al comienzo del crontab.
El directorio de trabajo es el home del usuario y no el del proyecto, de modo que las rutas relativas terminan resolviéndose en un lugar inesperado. Las variables de entorno que define tu shell de inicio de sesión no están, incluido todo lo que venía de un .env cargado por algún hook del shell. Y el signo de porcentaje tiene un significado especial en un crontab: se convierte en un salto de línea, y por eso una cadena de formato de fecha como %Y rompe un comando en silencio a menos que se escape.
La otra mitad es la salida. Todo lo que una tarea escribe en stdout o stderr se envía por correo al propietario si existe un agente de transporte de correo, y se descarta si no existe; así es como las tareas fallan en silencio durante meses. Redirige a un archivo de log que de verdad leas, o haz que la tarea informe a tu sistema de monitoreo tanto cuando tiene éxito como cuando falla.
Solapamiento, idempotencia y la ejecución que se perdió
Cron inicia una tarea a la hora indicada sin importar si la ejecución anterior terminó. Una tarea de cinco minutos programada cada cinco minutos acaba corriendo dos copias a la vez, luego tres, y la falla suele manifestarse como trabajo duplicado o como un bloqueo mutuo, no como un error de programación. Un lock - flock en Linux, un advisory lock en la base de datos o un lease en un almacén compartido - es la solución estándar, y necesita un tiempo de expiración para que una ejecución que se cayó no bloquee todas las siguientes.
Diseña cada tarea de modo que ejecutarla dos veces sea inofensivo. En la práctica eso significa registrar qué se procesó en lugar de suponer que el horario lo define: selecciona las filas que aún no se atendieron, márcalas y deja que una segunda ejecución no encuentre nada por hacer.
La imagen espejo es la ejecución que se perdió. Si la máquina estaba suspendida o el proceso falló, algunas implementaciones se saltan esa ocurrencia, otras la ejecutan tarde y otras ejecutan de golpe todas las ocurrencias perdidas. Anacron existe justamente para máquinas que no están encendidas todo el tiempo, y los planificadores de contenedores tienen sus propias políticas, que conviene leer antes de depender de una de ellas.
Alternativas modernas al crontab
Los timers de systemd reemplazan a cron en la mayoría de las distribuciones de Linux actuales y ofrecen cosas que cron nunca tuvo: orden por dependencias, límites de recursos, registro automático en el journal, retardos aleatorios para evitar avalanchas simultáneas y Persistent=true, para que una ejecución perdida ocurra en el siguiente arranque. El costo es más configuración, ya que un timer y una unidad de servicio son dos archivos en lugar de una línea.
El CronJob de Kubernetes toma la misma sintaxis de cinco campos y agrega política de concurrencia, límites de historial y manejo de plazos, que es exactamente el conjunto de problemas descrito arriba hecho explícito. Los planificadores administrados - buses de eventos en la nube, horarios de CI, timers serverless - suelen prometer entrega al menos una vez en lugar de exactamente una vez, lo que vuelve a empujar la idempotencia hacia la tarea.
Para trabajos dentro de una aplicación, una cola con un mensaje diferido suele encajar mejor que cualquier planificador, porque los reintentos, la visibilidad y el monitoreo vienen con la cola en vez de agregarse después.
Los horarios que la gente escribe en la práctica
Cada quince minutos es */15 * * * *. Cada noche a las 02:30 es 30 2 * * *. Días hábiles a las 09:00 es 0 9 * * 1-5. El primero de cada mes a medianoche es 0 0 1 * *, y para el último día del mes no existe ninguna expresión estándar: la solución habitual es correr a diario y salir salvo que mañana sea día uno.
Dos hábitos hacen que un crontab siga siendo legible más adelante. Reparte la carga en lugar de programar todo en punto: 7 3 * * * no cuesta más de escribir que 0 3 * * * y evita competir con todas las demás tareas de la máquina. Y comenta cada línea con lo que hace y quién es su responsable, porque un crontab sobrevive a la memoria de quien agregó la entrada.
Cuando un horario es genuinamente complejo, dividirlo en dos entradas simples suele ser más claro que una sola expresión ingeniosa, y la claridad es justo lo que quieres a las tres de la mañana, cuando la tarea que corrió sin ruido durante un año de pronto deja de hacerlo.
Saber si la tarea llegó a ejecutarse
La falla característica del trabajo programado es el silencio. Una tarea que falla a gritos se arregla el mismo día; una tarea que deja de ejecutarse no produce salida alguna, y nadie lo nota hasta que el informe semanal que genera falta por tercera semana seguida.
El patrón que lo resuelve es el monitoreo tipo dead man's switch: la tarea envía un ping a un servicio de monitoreo cuando termina bien, y el servicio alerta cuando ese ping no llega dentro de la ventana esperada. Eso invierte la dirección habitual de las alertas y detecta todo: un host caído, un crontab borrado, un despliegue fallido, una máquina que nunca volvió de un reinicio, porque desde afuera todos esos casos se ven idénticos, es decir, no pasa nada.
Registra qué hizo cada ejecución, no solo que ocurrió. Una línea con la hora de inicio, la de fin, la cantidad de registros procesados y el estado de salida convierte una sospecha vaga en una respuesta, y es la diferencia entre saber que una tarea corrió y saber que funcionó. Cuando una tarea nocturna procesa cero filas en silencio durante un mes, ese conteo en el log suele ser la única evidencia de cuándo empezó.
Preguntas frecuentes
- ¿Por qué mostrar las próximas ejecuciones en vez de solo una descripción?
- Porque una expresión puede ser perfectamente válida y aun así no significar lo que pretendías. Leer cinco campos te dice lo que escribiste; ver las próximas seis fechas te dice lo que va a pasar. En esa diferencia es donde se suelen cazar los errores de programación.
- ¿Qué pasa si fijo día del mes y día de la semana a la vez?
- Se combinan con O, no con Y. Así que "0 0 1 * MON" se dispara el día 1 de cada mes Y todos los lunes, no solo los lunes que caen en día 1. Esto sorprende a casi todo el mundo, es comportamiento especificado y no una rareza, y las próximas ejecuciones lo dejan a la vista.
- ¿Qué sintaxis de cron se admite?
- Cron estándar de cinco campos: minuto, hora, día del mes, mes, día de la semana. Se aceptan comodines, rangos, listas, pasos y nombres de mes y día de tres letras, además de los atajos @daily, @hourly, @weekly, @monthly y @yearly. El domingo puede escribirse como 0 o como 7.
- ¿En qué zona horaria están las ejecuciones mostradas?
- En la zona horaria de tu navegador. El cron de un servidor se ejecuta en la zona de ese servidor, que a menudo es UTC y a menudo no es la que muestra tu equipo, así que comprueba la configuración del servidor antes de fiarte de una hora exacta.
- ¿Por qué dice que una expresión nunca se ejecutará?
- Algunas combinaciones son imposibles, como el 30 de febrero. En lugar de mostrar una lista vacía, la herramienta te lo dice directamente.
Última actualización:
Incluye los pasos, el resultado esperado y el real. Elimina secretos y datos personales.
