¿Qué es Cron? Una perspectiva histórica
Cron es uno de los utilitarios más antiguos y duraderos del universo Unix. Fue escrito por Ken Thompson como parte de Unix V7 (1979) en los laboratorios Bell. El nombre "cron" proviene de la palabra griega chronos (χρόνος), que significa "tiempo".
El demonio cron original se despertaba cada minuto, escaneaba una lista de tareas programadas y ejecutaba cualquiera cuya hora hubiera llegado. Este diseño elegantemente simple —una tabla de expresiones de tiempo emparejadas con comandos— resultó tan eficaz que se convirtió en el estándar de facto para la programación en todos los sistemas Unix. Las distribuciones Linux modernas incluyen descendientes como Vixie Cron (Paul Vixie, 1988), cronie y fcron, mientras que macOS usa launchd internamente. La influencia de cron también se extendió a los frameworks de aplicaciones: Quartz Scheduler (Java), APScheduler (Python), node-cron (Node.js) y plataformas cloud como AWS EventBridge, todas adoptan su sintaxis de expresiones.
Sintaxis Estándar de 5 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 o JAN–DEC)
│ │ │ │ ┌─ día de semana (0–7 o SUN–SAT; 0 y 7 = domingo)
│ │ │ │ │
* * * * * comando
Descripción de Cada Campo
| Campo | Valores Permitidos | Descripción |
|---|---|---|
| Minuto | 0–59 | El minuto de la hora en que se ejecuta la tarea |
| Hora | 0–23 | La hora del día (reloj de 24 horas) |
| Día del mes | 1–31 | El día del mes en que se ejecuta |
| Mes | 1–12 o JAN–DEC | El mes del año |
| Día de semana | 0–7 o SUN–SAT | El día de la semana (0 y 7 = domingo) |
Importante: Cuando tanto el día del mes como el día de semana son distintos de *, cron usa lógica OR: si cualquiera de las dos condiciones coincide, el trabajo se ejecuta. Esto sorprende a muchos principiantes.
Sintaxis Extendida de 6 Campos (con Segundos)
Algunos schedulers —notablemente Quartz Scheduler (Java), Spring Framework y varias plataformas cloud— añaden un campo de segundos al inicio:
┌─────────── segundo (0–59)
│ ┌───────── minuto (0–59)
│ │ ┌─────── hora (0–23)
│ │ │ ┌───── día del mes (1–31)
│ │ │ │ ┌─── mes (1–12)
│ │ │ │ │ ┌─ día semana (1–7 en Quartz; 1=domingo)
│ │ │ │ │ │
0 * * * * ?
Tenga en cuenta que Quartz numera los días de la semana de forma diferente (1=domingo, 7=sábado), al contrario de Unix cron donde tanto 0 como 7 representan el domingo.
Caracteres Especiales Explicados
* — Cualquier Valor
Coincide con todos los valores posibles de ese campo. * * * * * se ejecuta cada minuto.
, — Lista de Valores
Especifica múltiples valores discretos. 0 9,12,18 * * * se ejecuta todos los días a las 9:00, 12:00 y 18:00.
- — Rango
Especifica un rango inclusivo. 0 9-17 * * 1-5 se ejecuta cada hora entre las 9:00 y las 17:00, de lunes a viernes.
/ — Valores de Paso
*/n significa "cada n unidades". */15 * * * * se ejecuta cada 15 minutos. También se puede combinar con rangos: 10-50/10 significa 10, 20, 30, 40, 50.
? — Sin Valor Específico (solo Quartz/Spring)
Se usa en el campo de día del mes o día de semana para indicar "no importa". Como especificar ambos campos es ambiguo, uno de ellos debe ser ?.
L — Último (solo Quartz/Spring)
En el día del mes: el último día del mes. En el día de semana: la última ocurrencia de ese día en el mes. 0 0 L * ? se ejecuta el último día de cada mes a medianoche.
W — Día Laborable Más Cercano (solo Quartz/Spring)
15W en día del mes significa el día laborable más cercano al día 15. Si el 15 es sábado, se ejecuta el viernes 14; si es domingo, el lunes 16.
# — Enésima Ocurrencia del Día de Semana (solo Quartz/Spring)
2#3 significa el tercer martes del mes. Formato: <día>#<ocurrencia>. 0 10 ? * 2#1 se ejecuta el primer lunes de cada mes a las 10:00.
Alias de Tiempo Especiales
La mayoría de las implementaciones de cron soportan los siguientes atajos convenientes:
| Alias | Equivalente | Descripción |
|---|---|---|
@yearly |
0 0 1 1 * |
Una vez al año, el 1 de enero a medianoche |
@annually |
0 0 1 1 * |
Igual que @yearly |
@monthly |
0 0 1 * * |
El primer día de cada mes a medianoche |
@weekly |
0 0 * * 0 |
Cada domingo a medianoche |
@daily |
0 0 * * * |
Cada día a medianoche |
@midnight |
0 0 * * * |
Igual que @daily |
@hourly |
0 * * * * |
Cada hora en el minuto 0 |
@reboot |
— | Se ejecuta una vez al inicio del sistema |
Ejemplos Comunes de Expresiones Cron
| Expresión | Significado |
|---|---|
* * * * * |
Cada minuto |
0 * * * * |
Cada hora (al minuto 0) |
*/15 * * * * |
Cada 15 minutos |
0 0 * * * |
Cada día a medianoche |
30 2 * * * |
Cada día a las 2:30 AM |
0 9-17 * * 1-5 |
Cada hora de 9:00 a 17:00, solo días laborables |
0 0 * * 0 |
Cada domingo a medianoche |
0 0 1 * * |
El primer día de cada mes a medianoche |
0 0 1 1 * |
El 1 de enero a medianoche (una vez al año) |
0 6 * * 1-5 |
Días laborables a las 6:00 AM |
0 */6 * * * |
Cada 6 horas |
Trabajando con Crontab en Linux
# Editar tu crontab personal
crontab -e
# Ver las entradas del crontab actual
crontab -l
# Eliminar tu crontab completamente
crontab -r
# Editar el crontab de otro usuario (solo root)
crontab -u username -e
Ejemplo de Archivo Crontab
# Variables de entorno al inicio
SHELL=/bin/bash
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
[email protected]
# Ejecutar backup cada día a las 2:30 AM
30 2 * * * /usr/local/bin/backup.sh
# Limpiar cada domingo a medianoche, con registro
0 0 * * 0 /usr/local/bin/cleanup.sh >> /var/log/cleanup.log 2>&1
# Verificación de salud cada 15 minutos
*/15 * * * * /usr/local/bin/health-check.sh
# Cron con zona horaria (extensión GNU cron / cronie)
CRON_TZ=America/Mexico_City
0 9 * * 1-5 /usr/local/bin/informe-matutino.sh
Ubicaciones de Cron a Nivel del Sistema
/etc/crontab— crontab del sistema con un campo de nombre de usuario adicional/etc/cron.d/— archivos cron específicos para paquetes y servicios/etc/cron.daily/,/etc/cron.hourly/,/etc/cron.weekly/,/etc/cron.monthly/— los scripts aquí se ejecutan con esa frecuencia medianterun-parts
Cron en macOS y Windows
macOS: launchd
macOS abandonó el demonio cron en favor de launchd. Aunque cron sigue funcionando, Apple prefiere archivos .plist en ~/Library/LaunchAgents/ (tareas de usuario) o /Library/LaunchDaemons/ (tareas del sistema). Sin embargo, muchos desarrolladores aún usan cron por su simplicidad.
Windows: Programador de Tareas
Windows usa el Programador de Tareas (schtasks) con su propia configuración XML. WSL (Subsistema de Windows para Linux) proporciona un entorno Linux completo con cron nativo.
Schedulers a Nivel de Aplicación
Node.js — node-cron
const cron = require('node-cron');
// Programar a las 2:30 AM diariamente con zona horaria
cron.schedule('30 2 * * *', async () => {
await ejecutarBackupDiario();
}, {
timezone: "America/Mexico_City"
});
Python — APScheduler
from apscheduler.schedulers.blocking import BlockingScheduler
from apscheduler.triggers.cron import CronTrigger
scheduler = BlockingScheduler()
@scheduler.scheduled_job(CronTrigger.from_crontab('0 9 * * 1-5'))
def tarea_matutina():
print("¡Buenos días! Es un día laborable.")
scheduler.start()
Java — Quartz Scheduler
Quartz utiliza expresiones de 6 campos (segundo, minuto, hora, día del mes, mes, día de semana) y soporta los caracteres avanzados (L, W, #, ?).
// Quartz: cada día laborable a las 9:00 AM
CronScheduleBuilder schedule = CronScheduleBuilder.cronSchedule("0 0 9 ? * MON-FRI");
Schedulers Cloud y Contenedores
AWS EventBridge Scheduler
Soporta expresiones cron de 6 campos (UTC). El campo de día del mes o día de semana debe ser ?:
cron(0 2 * * ? *) # Cada día a las 2 AM UTC
Google Cloud Scheduler
Usa la sintaxis Unix estándar de 5 campos con soporte de zona horaria.
Kubernetes CronJob
apiVersion: batch/v1
kind: CronJob
metadata:
name: backup-diario
spec:
schedule: "0 2 * * *"
concurrencyPolicy: Forbid
jobTemplate:
spec:
template:
spec:
containers:
- name: backup
image: backup-image:latest
restartPolicy: OnFailure
concurrencyPolicy: Forbid evita que las ejecuciones se superpongan si una tarea tarda más que su intervalo.
Manejo de Zonas Horarias
Cron se ejecuta en la zona horaria del sistema, que en servidores suele ser UTC. Una tarea programada para 0 9 * * * en un servidor UTC se ejecutará a las 9:00 UTC, que puede ser las 4:00 AM o las 10:00 PM en la zona horaria del usuario.
Buenas prácticas para zonas horarias:
- Usar
CRON_TZ=en el crontab para especificar explícitamente la zona horaria - Aprovechar los campos de zona horaria en plataformas cloud (GCP Cloud Scheduler, Kubernetes
spec.timeZone) - Considerar UTC fijo para evitar problemas con el horario de verano (DST):
0 2 * * *puede ejecutarse dos veces o no ejecutarse durante las transiciones DST - Documentar siempre qué zona horaria corresponde a cada expresión cron
Consideraciones de Seguridad
Las tareas cron suelen ejecutarse con privilegios elevados y son una superficie de ataque común.
Principio de mínimo privilegio: Ejecutar bajo el usuario con los mínimos privilegios necesarios, evitando root cuando sea posible.
Sin credenciales en el código: Nunca incluir contraseñas, claves API o tokens directamente en el crontab o los scripts. Usar archivos de variables de entorno con permisos restringidos (chmod 600) o gestores de secretos (AWS Secrets Manager, HashiCorp Vault).
Permisos de scripts: Asegurarse de que los scripts cron no sean modificables por otros usuarios.
chmod 750 /usr/local/bin/backup.sh
chown root:staff /usr/local/bin/backup.sh
Monitoreo y alertas: Usar MAILTO= para recibir errores, y servicios como Healthchecks.io o Cronitor para alertar cuando una tarea no se ejecuta según lo programado.
Registro de auditoría: Registrar todas las ejecuciones con marcas de tiempo en un sistema de logs centralizado.
Mejores Prácticas
Diseñar tareas idempotentes: Una tarea que puede ejecutarse múltiples veces con el mismo resultado facilita la recuperación ante fallos.
Usar bloqueo de archivos para evitar solapamientos: Si una tarea lenta puede seguir ejecutándose cuando llegue el próximo disparador, usar flock:
*/5 * * * * flock -n /var/lock/myjob.lock /usr/local/bin/myjob.sh
Redirigir la salida explícitamente:
0 3 * * * /usr/local/bin/backup.sh >> /var/log/backup.log 2>&1
Verificar expresiones antes de desplegar: Usar la herramienta Cron Parser para confirmar que la expresión se dispara exactamente cuando se espera.
Versionar los crontabs: Almacenar los archivos crontab en Git junto con el código de infraestructura y desplegarlos con herramientas como Ansible o Puppet.
Preguntas Frecuentes
P: ¿Por qué mi tarea cron no se ejecuta?
Las causas más comunes son: (1) permisos de ejecución incorrectos en el script, (2) el script depende de variables de entorno no disponibles en el entorno mínimo de cron, (3) problemas con PATH — cron no carga el PATH de tu shell, usar rutas absolutas, (4) el demonio cron no está en ejecución (systemctl status cron).
P: ¿Cuál es la diferencia entre */5 y 0/5?
En cron estándar de Unix, */5 significa cada 5 minutos comenzando desde 0 (0, 5, 10, ..., 55). 0/5 no es sintaxis estándar de Unix cron, pero es usada en Quartz/AWS con el mismo significado.
P: ¿Puede cron ejecutar una tarea cada segundo?
La granularidad mínima de cron estándar es un minuto. Para programación sub-minuto, usar schedulers de aplicación como Quartz, APScheduler con disparadores de intervalo, o temporizadores systemd.
P: ¿Cómo ejecutar una tarea el último día del mes?
En cron estándar no hay operador nativo para "último día". La solución habitual es verificar si el día siguiente es el primero: [ "$(date +\%d -d tomorrow)" = "01" ] && /ruta/script.sh. En Quartz cron, usar L en el campo de día del mes.
P: ¿Cuál es la diferencia entre 0 0 * * 0 y @weekly?
Son equivalentes: ambos se ejecutan a medianoche los domingos. @weekly es un alias mnemónico definido en la mayoría de las implementaciones modernas de cron.
P: ¿Cómo depuro un script que funciona en la terminal pero falla en cron?
Cron ejecuta con un entorno mínimo (normalmente solo HOME, LOGNAME, PATH=/usr/bin:/bin, SHELL=/bin/sh). Agregar #!/bin/bash y set -e al script, usar rutas absolutas para todos los comandos, y registrar stdout/stderr en un archivo de log.
Resumen
Cron ha impulsado la automatización Unix desde 1979 y sigue siendo el mecanismo de programación más utilizado en la actualidad. Ya sea administrando un servidor Linux individual, orquestando cargas de trabajo en Kubernetes o configurando disparadores de eventos en la nube, comprender profundamente la sintaxis cron ahorrará horas de depuración y prevendrá errores de programación costosos.
Puntos clave:
- La sintaxis estándar de 5 campos cubre la gran mayoría de los casos de uso
- Usar
/para pasos,,para listas,-para rangos - Considerar siempre la zona horaria — preferir UTC en servidores
- Aplicar principios de seguridad: mínimo privilegio, sin credenciales en el código, monitoreo
- Verificar expresiones con una herramienta de parseo antes de desplegar a producción
Descripción General
Las tareas Cron son el corazón de la automatización moderna, pero su sintaxis puede resultar abrumadora incluso para administradores de sistemas experimentados. Nuestro Analizador de Cron en Línea está diseñado para eliminar las conjeturas en la programación. Al traducir expresiones cron crípticas a un lenguaje claro y legible para los humanos, esta herramienta garantiza que sus tareas programadas se ejecuten exactamente cuando usted lo deseaba. Ya sea que esté administrando copias de seguridad, scripts de limpieza o correos electrónicos automatizados, la precisión es primordial.
Características Principales
- Traducción en Tiempo Real: Vea instantáneamente lo que significa su expresión cron en español (o el idioma que prefiera).
- Próximas Horas de Ejecución: Vea una lista de las próximas 5 o más horas de ejecución programadas para verificar su lógica.
- Soporte para Todos los Campos: Maneja formatos cron estándar, incluyendo variaciones de segundos (6 campos) y años (7 campos).
- Resaltado de Sintaxis: Las pistas visuales le ayudan a identificar minutos, horas, días, meses y semanas.
Cómo Usar
- Entrada: Pegue o escriba su expresión cron en el campo principal.
- Observar: La traducción legible para humanos se actualiza automáticamente a medida que escribe.
- Verificar: Consulte la lista de "Próximas horas de ejecución" para asegurarse de que coincida con sus requisitos.
- Copiar: Utilice los ejemplos proporcionados si está comenzando desde cero.
Casos de Uso Comunes
- Mantenimiento del Servidor: Programación de copias de seguridad de bases de datos nocturnas o rotaciones de registros.
- Desarrollo Web: Configuración de tareas recurrentes en segundo plano en frameworks como Laravel o Django.
- DevOps: Configuración de canales de CI/CD y verificaciones de estado automatizadas.
- Productividad Personal: Gestión de recordatorios recurrentes o ejecuciones de scripts en máquinas locales.
Trasfondo Técnico
Las expresiones cron constan de 5 a 7 campos separados por espacios en blanco. Cada campo representa una unidad de tiempo: minuto, hora, día del mes, mes y día de la semana. Nuestro analizador utiliza un robusto motor lógico que maneja caracteres especiales como * (cualquiera), , (lista), - (rango), / (incremento) y L (último). Calcula con precisión las próximas ocurrencias teniendo en cuenta los años bisiestos y la duración de los meses.
Preguntas Frecuentes
- ¿Soporta segundos? Sí, admite expresiones cron de 6 campos que incluyen segundos.
- ¿Puede manejar alias no estándar como @daily? Sí, se admiten los alias comunes.
- ¿Tiene en cuenta la zona horaria? Por defecto, los cálculos se basan en UTC, pero puede ajustar su perspectiva en consecuencia.
Limitaciones
- Implementaciones Variadas: Diferentes sistemas (por ejemplo, Quartz, AWS, Jenkins) tienen ligeras variaciones en la sintaxis de cron; verifique siempre con su plataforma específica.
- Casos Borde: "Último día del mes" (L) y "Día laborable más cercano" (W) pueden comportarse de manera diferente según el sistema operativo.