CronDrive
Guías

Cron y zonas horarias: por qué un job se ejecuta a otra hora

Actualizada el 16 de octubre de 2026

Cron sigue el horario en la zona horaria del sistema donde se ejecuta, que puede no ser la tuya. Cuando un job programado para las 08:00 se ejecuta a las 11:00, o una hora antes después de un cambio de horario, la causa suele estar aquí.

Qué zona horaria usa cron

La del sistema, como estaba cuando cron se inició. Para verla en el servidor:

timedatectl | grep "Time zone"
date

En un contenedor, sin timedatectl, date muestra la hora y la abreviatura de la zona. Compárala con la hora que esperas: si el servidor está en UTC y escribiste el horario en tu hora local, la diferencia es tu desfase con UTC.

Cambia la zona horaria del servidor

sudo timedatectl set-timezone America/Santiago
sudo systemctl restart cron     # crond en RHEL, Fedora y Rocky

Reinicia cron después del cambio. En Debian y Ubuntu, los jobs ven la nueva hora de inmediato, pero cron sigue el horario en la zona anterior hasta que se reinicia.

Cambiar la zona del servidor también cambia las horas de sus logs y de los otros programas que corren ahí. La otra opción es dejar el servidor en UTC y escribir el horario en UTC: en el probador de cron, elige una zona horaria para ver cuándo se ejecuta una expresión ahí.

Son objetivos distintos. Un servidor en UTC no tiene horario de verano, pero un horario fijo en UTC se ejecuta a otra hora local cuando tu zona cambia la hora. Si el job tiene que ejecutarse a las 08:00 locales todo el año, deja su horario en la zona local, con alguna de las opciones de abajo.

Una zona horaria para un crontab

  • cronie (RHEL, Fedora, Rocky, AlmaLinux) acepta CRON_TZ al principio del crontab. Las líneas de abajo siguen esa zona, y los logs mantienen la hora del servidor:

    CRON_TZ=America/Santiago
    0 8 * * 1-5 /ruta/al/reporte.sh
  • El cron de Debian y Ubuntu no lo acepta. Una línea TZ= en el crontab solo cambia la zona horaria de los comandos, no cuándo se ejecutan. Su manual sugiere ejecutar el job cada hora y revisar la hora en el comando. Revisa ahí también el día: los campos de días se siguen leyendo en la zona del servidor, y cuando en UTC ya es sábado, en Santiago todavía puede ser viernes.

    TZ=America/Santiago
    0 * * * * [ "$(date +\%H)" = 08 ] && [ "$(date +\%u)" -le 5 ] && /ruta/al/reporte.sh

    date +%u da el día de la semana, de 1 (lunes) a 7 (domingo), en la zona de TZ. Los % van escapados con \: en una línea de crontab, un % solo termina el comando.

Docker, Kubernetes y systemd

  • En un contenedor de Docker, cron usa la zona del contenedor, normalmente UTC. Instala tzdata y define TZ al iniciarlo: los detalles están en cómo ejecutar cron jobs en un contenedor de Docker.

  • Un CronJob de Kubernetes recibe su zona horaria en spec.timeZone, desde Kubernetes 1.27. Sin ella, el horario sigue la zona del controller manager del cluster, normalmente UTC:

    spec:
      schedule: "0 8 * * 1-5"
      timeZone: "America/Santiago"
  • Un timer de systemd acepta la zona en OnCalendar. systemd-analyze calendar muestra la próxima ejecución, también en UTC:

    OnCalendar=Mon..Fri *-*-* 08:00:00 America/Santiago

El horario de verano

El cron de Debian y Ubuntu, y cronie, tratan de forma especial un cambio de menos de tres horas, pero solo para los jobs que se ejecutan a una hora específica:

  • Cuando el reloj se adelanta, los jobs que caían en el tiempo saltado se ejecutan justo después del cambio. Un job a las 02:30 en una zona que salta de las 02:00 a las 03:00 se ejecuta cerca de las 03:00.
  • Cuando el reloj se atrasa, los jobs que caen en el tiempo repetido no se ejecutan dos veces.
  • Los jobs con * en la hora o en el minuto, como cada 15 minutos o cada hora, siguen la nueva hora como siempre.

Para un job que debe ejecutarse exactamente una vez al día a una hora precisa, evita la hora del cambio en tu zona. Si lo que importa es la hora en UTC, deja su horario en UTC, que no tiene horario de verano. Otros programadores de tareas, como systemd o Kubernetes, tienen sus propias reglas: revisa su documentación.

Entérate cuando se ejecute a otra hora

En CronDrive, elige la misma zona horaria que usa el programador para interpretar la expresión cron: la del servidor, la de CRON_TZ, la del contenedor o la de spec.timeZone. El formulario muestra la hora actual en esa zona, para compararla con date donde se ejecuta el job. Si después el job se ejecuta a otra hora y queda fuera de las esperas que configuraste, CronDrive te avisa que no se inició o no terminó a tiempo.

CronDrive te avisa por email, o en Slack, cuando un job con este horario falla, o no se inicia o no termina a tiempo. Gratis hasta 15 jobs.

Lo que verías con este horario

Un ejemplo con las últimas ejecuciones de este horario y resultados inventados: una falló y otra no se ejecutó.

Horas en UTC.

Hora
jue 15 oct, 08:00 A tiempo Inició 08:00, terminó 08:13, duró 13 min.
mié 14 oct, 08:00 No se ejecutó Alertas enviadas a las 08:05 y 08:30.
mar 13 oct, 08:00 A tiempo Inició 08:00, terminó 08:14, duró 14 min.
lun 12 oct, 08:00 Falló con código 1 Alerta enviada a las 08:04. Inició 08:00, terminó 08:04, duró 4 min.
vie 9 oct, 08:00 A tiempo Inició 08:00, terminó 08:13, duró 13 min.
jue 8 oct, 08:00 A tiempo Inició 08:00, terminó 08:14, duró 14 min.

La alerta de la ejecución que falló

Email de CronDrive, lun 12 oct, 08:04

Falló (código 1): "Tu job"

El job "Tu job" falló con el código de salida 1.

Si conectas Slack, el mismo mensaje llega a tu canal.

El cambio en tu crontab

0 8 * * 1-5 curl -fsS -m 10 https://job.crondrive.com/uG2Exw/start/$$; /path/to/job.sh; curl -fsS -m 10 https://job.crondrive.com/uG2Exw/end/$?/$$

Dos llamadas alrededor de tu comando, en la misma línea. La línea de tu job trae su propio token.

Monitorear este horario