Una expresión cron es una línea de cinco campos separados por espacios que describe cuándo debe ejecutarse una tarea: minuto, hora, día del mes, mes y día de la semana. 0 9 * * 1-5 significa «a las 9:00 de lunes a viernes». La misma sintaxis la usan el crontab de Linux y macOS, GitHub Actions, Kubernetes y la mayoría de planificadores, con pequeñas diferencias que conviene conocer.
Este artículo explica cada campo, los cuatro caracteres especiales, los casos que más confunden (el domingo como 0 o 7, la combinación de día del mes y día de la semana, las zonas horarias) y recopila ejemplos que puedes copiar.
Los cinco campos
┌───────────── minuto (0-59)
│ ┌───────────── hora (0-23)
│ │ ┌───────────── día del mes (1-31)
│ │ │ ┌───────────── mes (1-12 o ene-dic)
│ │ │ │ ┌───────────── día de la semana (0-6, domingo = 0; también 7 = domingo y lun-dom)
│ │ │ │ │
* * * * * comando
El orden es siempre el mismo. Los nombres abreviados en inglés (jan, mon) están admitidos en la mayoría de implementaciones, pero los números funcionan en todas, así que son la opción segura.
Los cuatro caracteres especiales
| Carácter | Significado | Ejemplo |
|---|---|---|
* |
Cualquier valor | * * * * * cada minuto |
, |
Lista de valores | 0 9,18 * * * a las 9:00 y a las 18:00 |
- |
Rango | 0 9 * * 1-5 a las 9:00 de lunes a viernes |
/ |
Paso | */15 * * * * cada 15 minutos (0, 15, 30, 45) |
Se pueden combinar: 0 8-20/2 * * 1-5 ejecuta cada dos horas entre las 8:00 y las 20:00 los días laborables. Un detalle del paso: */15 en el campo de minutos empieza en 0; si escribes 5/15 (válido en algunas implementaciones, no en POSIX) empezaría en el minuto 5.
Ejemplos listos para copiar
| Expresión | Cuándo se ejecuta |
|---|---|
*/5 * * * * |
Cada 5 minutos |
0 * * * * |
Cada hora, en punto |
30 2 * * * |
Todos los días a las 2:30 |
0 9 * * 1-5 |
De lunes a viernes a las 9:00 |
0 10 * * 6,0 |
Sábados y domingos a las 10:00 |
0 0 1 * * |
El día 1 de cada mes a medianoche |
0 0 1 1 * |
El 1 de enero a medianoche |
0 6 * * 1 |
Los lunes a las 6:00 |
0 */6 * * * |
Cada 6 horas (0:00, 6:00, 12:00, 18:00) |
15 14 1 * * |
El día 1 de cada mes a las 14:15 |
Si quieres comprobar una expresión antes de ponerla en producción, la herramienta de expresiones cron de AIMRAN Tools la traduce a lenguaje natural y muestra las próximas ejecuciones, lo que evita la típica sorpresa de descubrir el error cuando la tarea ya no se ha ejecutado.
Los tres puntos que más confunden
1. Día del mes y día de la semana se combinan con «o»
Según crontab(5), si ambos campos tienen un valor distinto de *, la tarea se ejecuta cuando se cumple cualquiera de los dos. 0 9 13 * 5 no significa «el viernes 13», sino «todos los días 13 a las 9:00 y además todos los viernes a las 9:00». Para «el viernes 13» hace falta comprobar el día de la semana dentro del propio comando.
2. El domingo es 0 (y normalmente también 7)
El estándar POSIX define el domingo como 0. Vixie cron (el habitual en Linux) acepta además 7. Otros planificadores no, así que usa 0 si quieres portabilidad.
3. La zona horaria no está en la expresión
Una expresión cron no lleva zona horaria: se interpreta en la del sistema que la ejecuta. En GitHub Actions es siempre UTC, por lo que 0 9 * * 1-5 se ejecuta a las 9:00 UTC (11:00 en España en verano). En Kubernetes puedes añadir timeZone: "Europe/Madrid" a la especificación del CronJob. En un servidor Linux depende de la configuración del sistema o de la variable CRON_TZ si el cron la soporta.
Diferencias entre entornos
| Entorno | Particularidades |
|---|---|
Linux / macOS (crontab -e) |
Cinco campos. Vixie cron admite atajos como @daily, @hourly, @weekly, @monthly, @reboot. La salida se envía por correo local si no se redirige. |
GitHub Actions (on: schedule) |
Cinco campos entre comillas, UTC, intervalo mínimo de 5 minutos. Las ejecuciones pueden retrasarse en momentos de mucha carga y el programador se desactiva en repositorios sin actividad durante 60 días. |
Kubernetes (CronJob) |
Cinco campos, admite timeZone, atajos @hourly etc., y políticas de concurrencia (concurrencyPolicy). |
| Algunas herramientas (Quartz, Spring, ciertos servicios cloud) | Añaden un sexto campo de segundos al principio o un séptimo de año. Copiar una expresión de cinco campos ahí la desplaza y cambia por completo su significado. |
Buenas prácticas
- Comprueba la expresión con una herramienta que muestre las próximas ejecuciones antes de guardarla.
- Documenta la intención en un comentario encima (
# backup diario 2:30), porque la expresión por sí sola no se lee a primera vista. - Evita las horas en punto si no es necesario: muchas tareas se concentran a las
0 0 * * *y a las0 * * * *; desplazar unos minutos reparte la carga (es lo que hacen los propios planificadores en la nube). - Redirige la salida (
>> /var/log/tarea.log 2>&1) para que el cron no acumule correos y puedas depurar. - Haz la tarea idempotente: si cron la lanza dos veces o se solapa con la anterior, no debería romper nada. Un lock (
flock -n) evita solapamientos.
Conclusión
Cinco campos, cuatro símbolos y tres trampas: el «o» entre día del mes y día de la semana, el domingo como 0 y la zona horaria del sistema. Con eso cubres casi cualquier programación. Y antes de confiar en una expresión, verifícala: dos minutos con un comprobador ahorran una tarea que no se ejecutó a las 2:30 de la madrugada.