Automatizar tareas repetitivas es una parte fundamental de la administracion de servidores Linux. Ya sea que necesites respaldos nocturnos de bases de datos, rotacion semanal de logs, o verificaciones de estado minuto a minuto, cron es el programador de tareas basado en tiempo que se encarga de todo. Ha sido parte central de los sistemas tipo Unix desde los anos 70, y cada distribucion Linux lo incluye.
Esta guia cubre todo desde la sintaxis basica de crontab hasta tecnicas avanzadas como gestion de variables de entorno, registro de salida, restricciones de seguridad y patrones de programacion del mundo real. Al terminar, podras programar, depurar y mantener cron jobs con confianza en cualquier sistema Linux.
Requisitos Previos
Antes de comenzar, asegurate de tener lo siguiente:
- Un sistema Linux (Ubuntu, Debian, CentOS, RHEL o cualquier distribucion)
- Una terminal con acceso shell (local o SSH)
- Una cuenta de usuario no root con privilegios
sudo - Familiaridad basica con la linea de comandos y un editor de texto (
nanoovim)
Verifica que cron este instalado y funcionando:
# Check if cron is active
systemctl status cron
# On RHEL/CentOS, the service is called crond
systemctl status crond
Si cron no esta instalado, instalalo:
# Debian/Ubuntu
sudo apt update && sudo apt install -y cron
# RHEL/CentOS/Fedora
sudo dnf install -y cronie
# Enable and start the service
sudo systemctl enable cron && sudo systemctl start cron
Que Es Cron?
Cron es un demonio de programacion de tareas basado en tiempo que se encuentra en practicamente todos los sistemas Unix y Linux. El nombre proviene de la palabra griega chronos (tiempo). Cron lee archivos de configuracion llamados crontabs (tablas cron) y ejecuta comandos en intervalos especificados — una vez por minuto, una vez por hora, una vez al dia, o cualquier combinacion de campos de tiempo que definas.
Cron resuelve un problema simple pero critico: las tareas que necesitan ocurrir regularmente no deberian depender de que alguien recuerde ejecutarlas. Respaldos automatizados, limpieza de logs, monitoreo del sistema, renovacion de certificados y mantenimiento de bases de datos son todas tareas que pertenecen a cron.
Como Funciona Cron
Entender la arquitectura te ayuda a depurar problemas mas rapido.
El Demonio Cron
El demonio cron (crond o cron) inicia al arranque y se ejecuta continuamente en segundo plano. Cada minuto, se activa y revisa todos los archivos crontab en busca de trabajos programados para el momento actual. Si encuentra una coincidencia, ejecuta el comando.
# Verify the daemon is running
ps aux | grep cron
Crontabs de Usuario
Cada usuario en el sistema puede tener su propio crontab. Estos se almacenan en /var/spool/cron/crontabs/ (Debian/Ubuntu) o /var/spool/cron/ (RHEL/CentOS). Nunca deberias editar estos archivos directamente — siempre usa el comando crontab.
El Crontab del Sistema
El archivo /etc/crontab es el crontab a nivel de sistema. A diferencia de los crontabs de usuario, incluye un campo de nombre de usuario entre los campos de tiempo y el comando:
# /etc/crontab format (note the username field)
# m h dom mon dow user command
17 * * * * root cd / && run-parts --report /etc/cron.hourly
25 6 * * * root test -x /usr/sbin/anacron || run-parts --report /etc/cron.daily
El Directorio /etc/cron.d/
Los mantenedores de paquetes y administradores del sistema pueden colocar archivos cron individuales en /etc/cron.d/. Estos siguen el mismo formato que /etc/crontab (con el campo de nombre de usuario). Esta es la forma preferida de agregar cron jobs a nivel de sistema porque los archivos estan aislados y son faciles de gestionar.
Sintaxis de Crontab Explicada
Cada entrada de crontab es una sola linea con cinco campos de tiempo y fecha seguidos del comando a ejecutar:
┌───────────── minuto (0–59)
│ ┌───────────── hora (0–23)
│ │ ┌───────────── dia del mes (1–31)
│ │ │ ┌───────────── mes (1–12 o jan–dec)
│ │ │ │ ┌───────────── dia de la semana (0–7, 0 y 7 = Domingo, o sun–sat)
│ │ │ │ │
* * * * * comando_a_ejecutar
Valores de Campo y Operadores
| Operador | Significado | Ejemplo |
|---|---|---|
* | Cualquier valor | * * * * * = cada minuto |
, | Lista de valores | 1,15,30 * * * * = minutos 1, 15, 30 |
- | Rango de valores | 1-5 * * * * = minutos 1 a 5 |
/ | Valores de paso | */10 * * * * = cada 10 minutos |
Ejemplos de Especificaciones de Tiempo
# Every minute
* * * * * /ruta/al/script.sh
# Every day at 2:30 AM
30 2 * * * /ruta/al/script.sh
# Every Monday at 5:00 PM
0 17 * * 1 /ruta/al/script.sh
# Every 15 minutes
*/15 * * * * /ruta/al/script.sh
# First day of every month at midnight
0 0 1 * * /ruta/al/script.sh
# Every weekday (Mon-Fri) at 8:00 AM
0 8 * * 1-5 /ruta/al/script.sh
# Every 6 hours
0 */6 * * * /ruta/al/script.sh
# January 1st at midnight
0 0 1 1 * /ruta/al/script.sh
Cadenas Especiales
Cron tambien soporta cadenas abreviadas para programaciones comunes:
| Cadena | Equivalente | Descripcion |
|---|---|---|
@reboot | N/A | Ejecutar una vez al iniciar |
@yearly | 0 0 1 1 * | Una vez al ano (1 de enero, medianoche) |
@monthly | 0 0 1 * * | Una vez al mes (dia 1, medianoche) |
@weekly | 0 0 * * 0 | Una vez a la semana (domingo, medianoche) |
@daily | 0 0 * * * | Una vez al dia (medianoche) |
@hourly | 0 * * * * | Una vez por hora (minuto 0) |
# Run a script at every system reboot
@reboot /home/usuario/tareas-inicio.sh
# Daily log rotation
@daily /usr/local/bin/rotar-logs.sh
Gestion de Crontab
El comando crontab es tu interfaz principal para crear y gestionar tareas programadas.
Editar Tu Crontab
# Open your crontab in the default editor
crontab -e
# Edit another user's crontab (requires root)
sudo crontab -u www-data -e
La primera vez que ejecutas crontab -e, te pedira que elijas un editor. Selecciona nano si no estas familiarizado con vim.
Listar Trabajos Actuales
# List your cron jobs
crontab -l
# List another user's cron jobs
sudo crontab -u www-data -l
# List the system crontab
cat /etc/crontab
Eliminar un Crontab
# Remove your entire crontab (use with caution)
crontab -r
# Interactive removal -- asks for confirmation
crontab -i -r
# Remove another user's crontab
sudo crontab -u username -r
Advertencia:
crontab -relimina todos tus cron jobs inmediatamente sin confirmacion y sin posibilidad de deshacer. Si solo quieres eliminar una entrada, usacrontab -ey borra la linea especifica.
Respaldar Tu Crontab
Siempre respalda tu crontab antes de hacer cambios:
# Save current crontab to a file
crontab -l > ~/crontab-backup-$(date +%Y%m%d).txt
# Restore from backup
crontab ~/crontab-backup-20260124.txt
Variables de Entorno en Cron
Una de las causas mas comunes de fallas en cron jobs es el entorno. Los cron jobs se ejecutan con un entorno minimo que es muy diferente a tu shell interactivo. Tus archivos ~/.bashrc, ~/.bash_profile y scripts de inicio de sesion no se cargan.
El Entorno Predeterminado de Cron
Por defecto, cron tipicamente establece solo:
SHELL=/bin/sh
PATH=/usr/bin:/bin
HOME=/home/username
LOGNAME=username
Nota que /usr/local/bin, /snap/bin y otros directorios que esperarias en tu PATH estan ausentes. Por esto un comando que funciona perfectamente en tu terminal puede fallar silenciosamente en cron.
Establecer Variables en Crontab
Puedes definir variables de entorno en la parte superior de tu crontab:
# Set a complete PATH
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
# Set the shell
SHELL=/bin/bash
# Set email for cron output
MAILTO=admin@example.com
# Your cron jobs below
0 2 * * * /home/usuario/backup.sh
Usar Rutas Completas en Comandos
El enfoque mas seguro es siempre usar rutas absolutas para cada comando en tus cron jobs:
# Bad -- relies on PATH
0 2 * * * mysqldump mydb > /tmp/backup.sql
# Good -- uses full path
0 2 * * * /usr/bin/mysqldump mydb > /tmp/backup.sql
Puedes encontrar la ruta completa de cualquier comando con which:
which mysqldump
# Output: /usr/bin/mysqldump
which python3
# Output: /usr/bin/python3
Salida y Registro de Logs
Por defecto, cron envia por correo cualquier salida (stdout y stderr) de un trabajo al buzon de correo local del propietario del crontab. En la mayoria de servidores, esto no se lee. Un registro adecuado de logs es esencial.
Redirigir Salida a un Archivo de Log
# Redirect stdout and stderr to a log file
0 2 * * * /home/usuario/backup.sh >> /var/log/backup.log 2>&1
# Separate stdout and stderr into different files
0 2 * * * /home/usuario/backup.sh >> /var/log/backup.log 2>> /var/log/backup-errors.log
# Discard all output (silent execution)
0 2 * * * /home/usuario/backup.sh > /dev/null 2>&1
Buena Practica: Nunca descartes la salida durante el desarrollo y las pruebas. Una vez que tu cron job este probado y estable, puedes redirigir solo stderr y descartar stdout:
command > /dev/null 2>> /var/log/errors.log.
Usar MAILTO para Notificaciones por Correo
La variable MAILTO controla a donde cron envia la salida de los trabajos:
# Send output to a specific email address
MAILTO=admin@example.com
# Send to multiple recipients
MAILTO=admin@example.com,devops@example.com
# Disable email entirely
MAILTO=""
# All jobs below inherit the MAILTO setting
0 2 * * * /home/usuario/backup.sh
Para que el correo funcione, tu servidor necesita un agente de transferencia de correo (MTA) funcional como postfix o sendmail.
Revisar el Log de Cron
Cron registra cada ejecucion de trabajo en syslog. Este es tu primer recurso al depurar:
# View cron entries in syslog (Debian/Ubuntu)
grep CRON /var/log/syslog
# View cron entries on RHEL/CentOS
grep CRON /var/log/cron
# Follow the log in real time
tail -f /var/log/syslog | grep CRON
Una entrada tipica del log se ve asi:
Jan 24 02:00:01 server CRON[12345]: (user) CMD (/home/user/backup.sh)
Esto confirma que el trabajo fue disparado. Si el comando no aparece en el log, el problema esta en la sintaxis del crontab o en el demonio mismo.
Ejemplos Practicos
Ejemplo 1: Respaldo Automatizado de Base de Datos
# Back up a MySQL database every night at 2:00 AM
0 2 * * * /usr/bin/mysqldump -u dbuser -p'SecurePass123' mydb | /usr/bin/gzip > /backup/mysql/mydb-$(date +\%Y\%m\%d).sql.gz 2>> /var/log/mysql-backup.log
Nota: En crontab, debes escapar los signos de porcentaje (
%) con una barra invertida (\%) porque cron interpreta%como un salto de linea. Este es uno de los errores mas comunes con cron.
Un enfoque mas robusto usa un script envolvente:
#!/bin/bash
# /home/usuario/scripts/mysql-backup.sh
BACKUP_DIR="/backup/mysql"
DB_NAME="mydb"
DATE=$(date +%Y%m%d_%H%M%S)
LOG="/var/log/mysql-backup.log"
echo "[$DATE] Starting backup of $DB_NAME" >> "$LOG"
/usr/bin/mysqldump -u dbuser -p'SecurePass123' "$DB_NAME" | /usr/bin/gzip > "$BACKUP_DIR/${DB_NAME}-${DATE}.sql.gz"
if [ $? -eq 0 ]; then
echo "[$DATE] Backup completed successfully" >> "$LOG"
else
echo "[$DATE] ERROR: Backup failed" >> "$LOG"
fi
# Delete backups older than 30 days
find "$BACKUP_DIR" -name "*.sql.gz" -mtime +30 -delete
# Crontab entry for the wrapper script
0 2 * * * /home/usuario/scripts/mysql-backup.sh
Ejemplo 2: Limpieza de Logs
# Delete log files older than 7 days every Sunday at 3:00 AM
0 3 * * 0 /usr/bin/find /var/log/myapp -name "*.log" -mtime +7 -delete >> /var/log/cleanup.log 2>&1
# Compress logs older than 1 day, every day at 4:00 AM
0 4 * * * /usr/bin/find /var/log/myapp -name "*.log" -mtime +1 ! -name "*.gz" -exec /usr/bin/gzip {} \; 2>> /var/log/cleanup-errors.log
Ejemplo 3: Monitoreo del Sistema
# Check disk usage every 5 minutes, alert if above 90%
*/5 * * * * /home/usuario/scripts/disk-check.sh
El script de monitoreo:
#!/bin/bash
# /home/usuario/scripts/disk-check.sh
THRESHOLD=90
df -H | awk 'NR>1 {print $5 " " $6}' | while read usage mount; do
percent=$(echo "$usage" | tr -d '%')
if [ "$percent" -ge "$THRESHOLD" ]; then
echo "ADVERTENCIA: Uso de disco en $mount es ${usage}" | \
/usr/bin/mail -s "Alerta de Disco: $mount al ${usage}" admin@example.com
fi
done
Ejemplo 4: Renovacion de Certificados SSL
# Attempt certificate renewal twice daily (Let's Encrypt recommendation)
0 4,16 * * * /usr/bin/certbot renew --quiet --deploy-hook "systemctl reload nginx" >> /var/log/certbot-renew.log 2>&1
Ejemplo 5: Verificacion de Actualizaciones del Sistema
# Check for available updates every morning at 6:00 AM
0 6 * * * /usr/bin/apt update -qq && /usr/bin/apt list --upgradable 2>/dev/null | /usr/bin/mail -s "Reporte de Actualizaciones Disponibles" admin@example.com
Directorios de Cron
Las distribuciones Linux proporcionan un conjunto de directorios para scripts que deben ejecutarse en intervalos predefinidos. Simplemente coloca un script ejecutable en el directorio apropiado:
| Directorio | Frecuencia |
|---|---|
/etc/cron.hourly/ | Cada hora |
/etc/cron.daily/ | Cada dia |
/etc/cron.weekly/ | Cada semana |
/etc/cron.monthly/ | Cada mes |
# List all scripts in cron.daily
ls -la /etc/cron.daily/
Requisitos para Scripts en Directorios Cron
- El script debe ser ejecutable:
chmod +x /etc/cron.daily/miscript - El script no debe tener extension de archivo (
.sh,.py, etc.) —run-partsomite archivos con puntos en el nombre por defecto en muchos sistemas - El script debe comenzar con un shebang apropiado:
#!/bin/bash
# Create a daily cleanup script
sudo nano /etc/cron.daily/cleanup-temp
# Add content:
#!/bin/bash
find /tmp -type f -mtime +7 -delete
# Make it executable
sudo chmod +x /etc/cron.daily/cleanup-temp
Nota: Estos directorios son gestionados por
anacronen muchas distribuciones, lo que asegura que los trabajos perdidos se ejecuten despues de que el sistema vuelva a estar en linea. Esto es particularmente util para laptops y escritorios que no estan encendidos 24/7.
Consideraciones de Seguridad
Controlar Acceso con cron.allow y cron.deny
Puedes restringir que usuarios tienen permiso para crear cron jobs:
# /etc/cron.allow -- only listed users can use cron
echo "admin" | sudo tee /etc/cron.allow
echo "deploy" | sudo tee -a /etc/cron.allow
# /etc/cron.deny -- listed users are blocked from using cron
echo "guest" | sudo tee /etc/cron.deny
La logica es:
- Si
/etc/cron.allowexiste, solo los usuarios listados pueden usar cron - Si
/etc/cron.allowno existe pero/etc/cron.denyexiste, todos excepto los usuarios listados pueden usar cron - Si ninguno de los archivos existe, el comportamiento predeterminado depende de la distribucion (frecuentemente solo root)
Permisos de Archivos
Los cron jobs se ejecutan con los permisos del usuario propietario del crontab. Mantiene tus scripts seguros:
# Ensure scripts are owned by the correct user and not world-writable
chmod 750 /home/usuario/scripts/backup.sh
chown usuario:usuario /home/usuario/scripts/backup.sh
# Never store passwords in crontab -- use config files with restricted permissions
chmod 600 /home/usuario/.my.cnf
Evitar Ejecutar Cron Jobs como Root
Siempre que sea posible, crea un usuario de servicio dedicado para tareas cron:
# Create a dedicated backup user
sudo useradd -r -s /usr/sbin/nologin backupuser
# Set up its crontab
sudo crontab -u backupuser -e
Referencia Rapida de Sintaxis de Crontab
| Programacion | Expresion | Descripcion |
|---|---|---|
| Cada minuto | * * * * * | Se ejecuta cada minuto de cada dia |
| Cada 5 minutos | */5 * * * * | Se ejecuta en los minutos 0, 5, 10, 15, … |
| Cada hora | 0 * * * * | Se ejecuta al inicio de cada hora |
| Cada 6 horas | 0 */6 * * * | Se ejecuta a las 0:00, 6:00, 12:00, 18:00 |
| Diario a medianoche | 0 0 * * * | Se ejecuta una vez al dia a las 00:00 |
| Diario a las 2:30 AM | 30 2 * * * | Se ejecuta una vez al dia a las 02:30 |
| Cada lunes a las 9 AM | 0 9 * * 1 | Se ejecuta semanalmente el lunes por la manana |
| Dias laborales a las 8 AM | 0 8 * * 1-5 | Lunes a viernes a las 08:00 |
| Primero del mes | 0 0 1 * * | Medianoche del 1ro de cada mes |
| Cada trimestre | 0 0 1 1,4,7,10 * | Medianoche el 1 de ene, abr, jul, oct |
| Dos veces al dia | 0 4,16 * * * | Se ejecuta a las 4:00 AM y 4:00 PM |
| Cada 30 minutos | */30 * * * * | Se ejecuta a los :00 y :30 de cada hora |
| Al reiniciar | @reboot | Se ejecuta una vez cuando el sistema inicia |
Solucion de Problemas
Problema: El Cron Job Funciona en la Terminal pero No en Cron
Causa: Diferencias en PATH. Tu shell interactivo tiene un PATH rico; cron no.
Solucion: Usa rutas absolutas para todos los comandos, o establece PATH en la parte superior de tu crontab:
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
Problema: Los Signos de Porcentaje Rompen los Comandos
Causa: Cron interpreta % como un caracter de salto de linea.
Solucion: Escapa todos los signos de porcentaje con una barra invertida:
# Wrong
0 2 * * * /usr/bin/date +%Y%m%d
# Correct
0 2 * * * /usr/bin/date +\%Y\%m\%d
Problema: Errores de Permiso Denegado
Causa: El script no es ejecutable o el usuario no tiene acceso.
Solucion:
# Make the script executable
chmod +x /home/usuario/scripts/miscript.sh
# Verify ownership
ls -la /home/usuario/scripts/miscript.sh
Problema: Problemas de Zona Horaria
Causa: Cron usa la zona horaria del sistema por defecto. Si tu servidor esta configurado en UTC pero esperas hora local, los trabajos se ejecutan a horas inesperadas.
Solucion:
# Check system timezone
timedatectl
# Set timezone
sudo timedatectl set-timezone America/Mexico_City
# Or set TZ in crontab for per-job timezone
TZ=America/Mexico_City
0 9 * * * /home/usuario/reporte-matutino.sh
Problema: El Trabajo Se Ejecuta pero No Produce Salida
Causa: La salida se esta enviando al correo local, que nadie lee, o la salida se descarta.
Solucion: Redirige la salida a un archivo de log:
0 2 * * * /home/usuario/backup.sh >> /var/log/backup.log 2>&1
Problema: El Demonio Cron No Esta Corriendo
Solucion:
# Check status
sudo systemctl status cron
# Start it
sudo systemctl start cron
# Enable at boot
sudo systemctl enable cron
Resumen
Cron es la columna vertebral de la automatizacion en Linux. Con cinco simples campos de tiempo y un comando, puedes programar virtualmente cualquier tarea para que se ejecute en cualquier intervalo. Los puntos clave para recordar son:
- Siempre usa rutas absolutas para comandos en cron jobs
- Escapa los signos de porcentaje (
\%) en las entradas de crontab - Redirige la salida a archivos de log para depuracion y auditoria
- Establece variables de entorno (especialmente PATH) en la parte superior de tu crontab
- Respalda tu crontab antes de hacer cambios
- Revisa syslog (
grep CRON /var/log/syslog) cuando un trabajo no se ejecuta como se esperaba - Restringe el acceso con
/etc/cron.allowy/etc/cron.deny
Cron trabaja en conjunto con otras practicas de administracion de servidores. Para asegurar el servidor que ejecuta tus cron jobs, consulta la Lista de Verificacion de Seguridad para Servidores Linux y Endurecimiento SSH: 12 Pasos para Asegurar tu Servidor Linux.