Saltar al contenido principal

Guías / Solucionarlo: guías para los errores que aparecen de verdad

Expresiones cron: los cinco campos, con ejemplos

Una expresión cron son cinco campos separados por espacios que dicen cuándo se ejecuta una tarea: minuto, hora, día del mes, mes y día de la semana. Leído de izquierda a derecha, 30 2 * * 1 significa en el minuto 30 de la hora 2 de cualquier día de cualquier mes, si ese día es lunes.

Los cinco campos

Toda línea de cron estándar de Unix empieza con los mismos cinco campos, seguidos del comando que hay que ejecutar.

* * * * *  command to run
| | | | |
| | | | +-- day of week  (0-7, 0 and 7 both mean Sunday, or SUN-SAT)
| | | +---- month        (1-12, or JAN-DEC)
| | +------ day of month (1-31)
| +-------- hour         (0-23)
+---------- minute       (0-59)

Un campo contiene una de cuatro cosas: un asterisco que significa todos los valores, un número suelto, una lista o un rango. Las horas usan un reloj de 24 horas sin AM ni PM, así que las 6 de la tarde son 18. El domingo es a la vez 0 y 7 porque históricamente los sistemas no se pusieron de acuerdo, y cron acepta cualquiera de los dos.

Algunos programadores de tareas añaden campos. Quartz, que usan muchos frameworks de Java, pone un campo de segundos al principio y añade un año opcional al final, así que una expresión de seis o siete campos copiada de una referencia de Quartz no funcionará en un crontab de Linux. Comprueba para qué variante estás escribiendo antes de copiar una expresión de ningún sitio.

Los caracteres especiales

  • * coincide con todos los valores del campo. * * * * * se ejecuta cada minuto.
  • , enumera valores. 0 8,13,20 * * * se ejecuta a las 08:00, las 13:00 y las 20:00.
  • - indica un rango. 0 9-17 * * * se ejecuta en punto desde las 09:00 hasta las 17:00.
  • / avanza a saltos dentro de un rango. */15 * * * * se ejecuta en los minutos 0, 15, 30 y 45. Puedes combinarlo con un rango: 0 9-17/2 * * * se ejecuta a las 9, 11, 13, 15 y 17.
  • Nombres. De MON a SUN y de JAN a DEC funcionan en los dos últimos campos y se leen mejor que los números. No se pueden usar dentro de un salto.

Hay otros cuatro caracteres que aparecen sin parar en los tutoriales y que no existen en el cron estándar. L para el último día, W para el día laborable más cercano, # para el enésimo día de la semana del mes y ? en lugar de un asterisco son extensiones de Quartz. Una expresión como 0 0 L * * la rechazará un crontab de Linux. Para ejecutar algo el último día del mes allí, ejecútalo a diario y deja que el comando decida:

0 0 * * * [ "$(date -d tomorrow +\%d)" = "01" ] && /usr/local/bin/month-end.sh

Fíjate en las barras invertidas de esa línea. El signo de porcentaje tiene un significado especial en un crontab, que es el quinto error de la lista de abajo.

Cron también acepta seis cadenas abreviadas en lugar de los cinco campos: @yearly (también escrito @annually), @monthly, @weekly, @daily (también @midnight), @hourly y @reboot, que se ejecuta una vez al arrancar cron en lugar de a una hora del reloj. @reboot no está soportado en todas partes.

Horarios habituales

Cuándo quieres que se ejecuteExpresión
Cada minuto* * * * *
Cada 5 minutos*/5 * * * *
Cada 30 minutos0,30 * * * *
Cada hora, en punto0 * * * *
Cada 2 horas0 */2 * * *
Todos los días a medianoche0 0 * * *
Todos los días a las 02:3030 2 * * *
Dos veces al día, a las 08:00 y las 20:000 8,20 * * *
De lunes a viernes a las 09:000 9 * * MON-FRI
Cada hora en horario laboral, de lunes a viernes0 9-17 * * MON-FRI
Todos los lunes a las 07:000 7 * * MON
Todos los domingos a las 03:1515 3 * * SUN
El día 1 de cada mes a las 06:000 6 1 * *
Trimestral, el 1 de enero, abril, julio y octubre0 0 1 1,4,7,10 *

Errores que dejan la tarea a la hora equivocada

  1. Rellenar los dos campos de día. Este es el que pilla a todo el mundo. Cuando el día del mes y el día de la semana tienen los dos algo distinto de un asterisco, cron ejecuta la tarea cuando coincide cualquiera de los dos, no los dos a la vez. 0 0 13 * FRI se ejecuta todos los días 13 y todos los viernes, no el viernes 13.
  2. Un salto que no divide el rango. */7 * * * * se dispara en los minutos 0, 7, 14, 21, 28, 35, 42, 49 y 56, y luego vuelve a empezar en 0. El hueco al cambiar de hora es de cuatro minutos, no de siete. La misma trampa aplica a */40 en el campo de minutos y a cualquier salto que no sea divisor de 60.
  3. Poner el salto en el campo equivocado. */2 * * * * es cada dos minutos. 0 */2 * * * es cada dos horas. Quitar el 0 inicial convierte una tarea horaria en una que se ejecuta 30 veces más a menudo.
  4. Dar por hecho el entorno. Cron le da a la tarea un entorno mínimo, normalmente poco más que PATH=/usr/bin:/bin y SHELL=/bin/sh. Un script que funciona en tu shell falla en cron porque llama a algo que está en /usr/local/bin. Usa rutas absolutas para el comando y dentro de él.
  5. Un signo de porcentaje sin escapar. En un crontab, % se convierte en un salto de línea y todo lo que va después del primero se le entrega al comando como entrada estándar. Un date +%Y-%m-%d dentro de una línea de crontab hay que escribirlo date +\%Y-\%m-\%d.
  6. Ignorar la salida. Todo lo que la tarea imprime se envía por correo al dueño del crontab, y en una máquina sin correo configurado se descarta. Mándalo a algún sitio donde vayas a leerlo: 0 3 * * * /usr/local/bin/backup.sh >> /var/log/backup.log 2>&1
  7. Dejar que las ejecuciones se solapen. Cron lanza la siguiente ejecución a su hora tanto si la anterior terminó como si no. Envuelve las tareas largas en un bloqueo: */5 * * * * flock -n /tmp/sync.lock /usr/local/bin/sync.sh
  8. Olvidarse de los cambios de hora. Cron usa la hora local de la máquina. Los días en que cambia la hora, la franja de las 02:00 o no existe o pasa dos veces, así que una tarea programada dentro de ella puede saltarse o ejecutarse dos veces según la implementación de cron. Pon los servidores en UTC, o programa fuera de esa franja.
  9. Teclear crontab -r. Borra el crontab entero sin pedir confirmación, y está a una tecla de crontab -e. Guarda el crontab en el control de versiones e instálalo desde un archivo.

Verifícalo desde fuera

Una expresión que se analiza sin errores no es lo mismo que una tarea que se ejecutó. Comprueba las dos cosas, en la máquina y después desde fuera de ella.

En la máquina, confirma qué está instalado, qué dice el reloj y si cron llegó a lanzar la tarea:

crontab -l
timedatectl
grep CRON /var/log/syslog | tail -20
journalctl -u cron -u crond --since "2 hours ago"

La línea del registro demuestra que cron lanzó el comando. No dice nada sobre si el comando funcionó, y por eso importa la redirección a un archivo de registro del apartado de errores.

Después comprueba el resultado como lo haría un usuario, desde fuera del servidor. La mayoría de las tareas programadas existen para cambiar algo observable: un feed que debería llevar la fecha de hoy, un sitemap que debería haberse reescrito, una exportación que debería haber aparecido. Pídelo y lee las cabeceras:

curl -sI https://example.com/exports/daily.json
curl -s https://example.com/health/last-run

La cabecera Last-Modified te dice si el archivo es reciente, y lo hace sin acceso al shell. Lanzar la misma petición desde varias ubicaciones con la verificación HTTP separa una tarea que no se ejecutó de una página que está en caché en un nodo de una región y solo allí está obsoleta. Esa distinción es invisible desde un solo curl en el propio servidor.

Saber cuándo una tarea programada deja de ejecutarse

Una tarea de cron que deja de ejecutarse no produce nada de lo que darse cuenta. No hay página de error ni petición fallida, así que nada dispara una alerta salvo que algo esté vigilando esa ausencia. Lo que se monitorea es el efecto de la tarea y no la tarea: un archivo de estado que reescribe, una marca de tiempo que publica, un endpoint que informa de su última ejecución correcta. Una verificación programada contra ese endpoint convierte un fallo silencioso en una notificación, y HostTracker las envía por correo electrónico, SMS, llamada de voz, Slack, Telegram y otros canales, con 13 tipos de monitor. Cómo se configura una está en la guía de la verificación HTTP, el resto de las guías de diagnóstico están en el grupo de soluciones, y la lista completa de tipos de verificación está en la página de funcionalidades.

Compruébalo ahora

Ejecuta la comprobación gratuita en tu propio sitio, sin necesidad de cuenta.

Features

Monitoriza esto de forma permanente

Recibe un aviso en cuanto algo falle: HostTracker comprueba desde más de 300 ubicaciones y te avisa por correo, SMS, Slack, Telegram y más.

Funciones de HostTracker

Más en esta sección: Solucionarlo: guías para los errores que aparecen de verdad