CRON — PROGRAMACION DE TAREAS EN LINUX Respaldos 0 2 * * * backup.sh Limpieza 0 3 * * 0 cleanup.sh Monitoreo */5 * * * * check.sh Renovar SSL 0 4 1 * * certbot Automatiza tareas recurrentes con programacion precisa basada en tiempo

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 (nano o vim)

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

OperadorSignificadoEjemplo
*Cualquier valor* * * * * = cada minuto
,Lista de valores1,15,30 * * * * = minutos 1, 15, 30
-Rango de valores1-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:

CadenaEquivalenteDescripcion
@rebootN/AEjecutar una vez al iniciar
@yearly0 0 1 1 *Una vez al ano (1 de enero, medianoche)
@monthly0 0 1 * *Una vez al mes (dia 1, medianoche)
@weekly0 0 * * 0Una vez a la semana (domingo, medianoche)
@daily0 0 * * *Una vez al dia (medianoche)
@hourly0 * * * *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 -r elimina todos tus cron jobs inmediatamente sin confirmacion y sin posibilidad de deshacer. Si solo quieres eliminar una entrada, usa crontab -e y 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:

DirectorioFrecuencia
/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

  1. El script debe ser ejecutable: chmod +x /etc/cron.daily/miscript
  2. El script no debe tener extension de archivo (.sh, .py, etc.) — run-parts omite archivos con puntos en el nombre por defecto en muchos sistemas
  3. 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 anacron en 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:

  1. Si /etc/cron.allow existe, solo los usuarios listados pueden usar cron
  2. Si /etc/cron.allow no existe pero /etc/cron.deny existe, todos excepto los usuarios listados pueden usar cron
  3. 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

ProgramacionExpresionDescripcion
Cada minuto* * * * *Se ejecuta cada minuto de cada dia
Cada 5 minutos*/5 * * * *Se ejecuta en los minutos 0, 5, 10, 15, …
Cada hora0 * * * *Se ejecuta al inicio de cada hora
Cada 6 horas0 */6 * * *Se ejecuta a las 0:00, 6:00, 12:00, 18:00
Diario a medianoche0 0 * * *Se ejecuta una vez al dia a las 00:00
Diario a las 2:30 AM30 2 * * *Se ejecuta una vez al dia a las 02:30
Cada lunes a las 9 AM0 9 * * 1Se ejecuta semanalmente el lunes por la manana
Dias laborales a las 8 AM0 8 * * 1-5Lunes a viernes a las 08:00
Primero del mes0 0 1 * *Medianoche del 1ro de cada mes
Cada trimestre0 0 1 1,4,7,10 *Medianoche el 1 de ene, abr, jul, oct
Dos veces al dia0 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@rebootSe 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.allow y /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.