Trabajos Cron: Sintaxis y Ejemplos Prácticos para Automatización de Tareas
Introducción
Cron es el planificador de trabajos basado en tiempo en sistemas operativos tipo Unix, permitiendo a los administradores de sistemas programar comandos o scripts para que se ejecuten automáticamente en tiempos e intervalos especificados. Comprender cron es fundamental para cualquier profesional de DevOps, ya que impulsa innumerables tareas automatizadas desde respaldos y rotación de registros hasta verificaciones de monitoreo y mantenimiento periódico.
Esta guía completa cubre todo, desde la sintaxis básica de cron hasta patrones avanzados de programación, ejemplos del mundo real, resolución de problemas y mejores prácticas para entornos de producción.
Comprendiendo los Fundamentos de Cron
¿Qué es Cron?
Cron es un demonio que se ejecuta continuamente en segundo plano, verificando cada minuto si hay trabajos programados. Lee los horarios de las tablas cron (crontabs) y ejecuta comandos en sus tiempos especificados.
Componentes de Cron
- crond: El demonio cron que ejecuta trabajos programados
- crontab: Comando para crear, editar, listar y eliminar trabajos cron
- cron.d: Directorio para archivos de trabajos cron del sistema
- /etc/crontab: Archivo crontab a nivel de sistema
- Crontabs de usuario: Horarios cron individuales de usuario
Sintaxis de Cron
Formato Básico de Cron
* * * * * command-to-execute
│ │ │ │ │
│ │ │ │ └─── Day of week (0-7, Sunday=0 or 7)
│ │ │ └───── Month (1-12)
│ │ └─────── Day of month (1-31)
│ └───────── Hour (0-23)
└─────────── Minute (0-59)
Caracteres Especiales
*(asterisco): Cualquier valor,(coma): Separador de lista de valores-(guión): Rango de valores/(barra): Valores de paso@(arroba): Cadenas especiales
Cadenas Especiales
@reboot # Run once at startup
@yearly # Run once a year (0 0 1 1 *)
@annually # Same as @yearly
@monthly # Run once a month (0 0 1 * *)
@weekly # Run once a week (0 0 * * 0)
@daily # Run once a day (0 0 * * *)
@midnight # Same as @daily
@hourly # Run once an hour (0 * * * *)
Patrones Comunes de Cron
Cada Minuto
* * * * * /path/to/script.sh
Cada 5 Minutos
*/5 * * * * /path/to/script.sh
Cada Hora
0 * * * * /path/to/script.sh
Cada Día a Medianoche
0 0 * * * /path/to/script.sh
Cada Día a las 3:30 AM
30 3 * * * /path/to/script.sh
Cada Lunes a las 9 AM
0 9 * * 1 /path/to/script.sh
Primer Día de Cada Mes
0 0 1 * * /path/to/script.sh
Cada Día Laborable a las 6 PM
0 18 * * 1-5 /path/to/script.sh
Múltiples Veces al Día
0 6,12,18 * * * /path/to/script.sh # At 6 AM, 12 PM, and 6 PM
Horario Laboral (9 AM a 5 PM, Días Laborables)
0 9-17 * * 1-5 /path/to/script.sh
Cada 15 Minutos Durante Horario Laboral
*/15 9-17 * * 1-5 /path/to/script.sh
Gestionando Trabajos Cron
Comandos Crontab
# List current user's cron jobs
crontab -l
# Edit current user's cron jobs
crontab -e
# Remove all cron jobs for current user
crontab -r
# List cron jobs for specific user (requires root)
sudo crontab -l -u username
# Edit cron jobs for specific user (requires root)
sudo crontab -e -u username
Creando Trabajos Cron
# Open crontab editor
crontab -e
# Add your cron job (example: daily backup at 2 AM)
0 2 * * * /usr/local/bin/backup.sh
# Save and exit (vi: :wq, nano: Ctrl+X, Y, Enter)
Trabajos Cron a Nivel de Sistema
# Create system cron job in /etc/cron.d/
sudo nano /etc/cron.d/custom-job
# Content:
# Backup database every day at 1 AM
0 1 * * * root /opt/scripts/db-backup.sh
# Set proper permissions
sudo chmod 644 /etc/cron.d/custom-job
Ejemplos Prácticos de Cron
1. Respaldo Diario de Base de Datos
# Cron entry
0 2 * * * /opt/scripts/mysql-backup.sh >> /var/log/mysql-backup.log 2>&1
# Script: /opt/scripts/mysql-backup.sh
#!/bin/bash
set -euo pipefail
BACKUP_DIR="/backup/mysql"
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
RETENTION_DAYS=7
mkdir -p "$BACKUP_DIR"
# Backup all databases
mysqldump --all-databases \
--single-transaction \
--routines \
--triggers | gzip > "${BACKUP_DIR}/all-databases-${TIMESTAMP}.sql.gz"
# Cleanup old backups
find "$BACKUP_DIR" -name "*.sql.gz" -mtime +$RETENTION_DAYS -delete
echo "Backup completed: $(date)"
2. Rotación de Registros
# Cron entry - Run daily at 11:55 PM
55 23 * * * /opt/scripts/rotate-logs.sh
# Script: /opt/scripts/rotate-logs.sh
#!/bin/bash
set -euo pipefail
LOG_DIRS=(
"/var/log/nginx"
"/var/log/application"
)
for dir in "${LOG_DIRS[@]}"; do
if [ -d "$dir" ]; then
# Compress logs older than 1 day
find "$dir" -name "*.log" -mtime +1 ! -name "*.gz" -exec gzip {} \;
# Delete logs older than 30 days
find "$dir" -name "*.gz" -mtime +30 -delete
fi
done
3. Verificación de Salud del Sistema
# Cron entry - Every 5 minutes
*/5 * * * * /opt/scripts/health-check.sh
# Script: /opt/scripts/health-check.sh
#!/bin/bash
set -euo pipefail
CPU_THRESHOLD=80
MEMORY_THRESHOLD=85
DISK_THRESHOLD=90
ALERT_EMAIL="[email protected]"
# Check CPU
CPU=$(top -bn1 | grep "Cpu(s)" | awk '{print $2}' | cut -d'%' -f1)
if (( $(echo "$CPU > $CPU_THRESHOLD" | bc -l) )); then
echo "High CPU: ${CPU}%" | mail -s "CPU Alert" "$ALERT_EMAIL"
fi
# Check Memory
MEMORY=$(free | grep Mem | awk '{printf("%.0f", ($3/$2) * 100)}')
if (( MEMORY > MEMORY_THRESHOLD )); then
echo "High Memory: ${MEMORY}%" | mail -s "Memory Alert" "$ALERT_EMAIL"
fi
# Check Disk
DISK=$(df -h / | tail -1 | awk '{print $5}' | sed 's/%//')
if (( DISK > DISK_THRESHOLD )); then
echo "High Disk Usage: ${DISK}%" | mail -s "Disk Alert" "$ALERT_EMAIL"
fi
4. Renovación de Certificado SSL
# Cron entry - Daily at 3 AM
0 3 * * * /opt/scripts/renew-ssl.sh
# Script: /opt/scripts/renew-ssl.sh
#!/bin/bash
set -euo pipefail
certbot renew --quiet --deploy-hook "systemctl reload nginx"
# Check certificate expiry
for domain in example.com api.example.com; do
EXPIRY=$(echo | openssl s_client -servername "$domain" \
-connect "$domain:443" 2>/dev/null | \
openssl x509 -noout -dates | grep notAfter | cut -d= -f2)
EXPIRY_EPOCH=$(date -d "$EXPIRY" +%s)
CURRENT_EPOCH=$(date +%s)
DAYS_REMAINING=$(( ($EXPIRY_EPOCH - $CURRENT_EPOCH) / 86400 ))
if (( DAYS_REMAINING < 30 )); then
echo "Certificate for $domain expires in $DAYS_REMAINING days" | \
mail -s "SSL Certificate Expiry Warning" [email protected]
fi
done
5. Monitoreo de Sitio Web
# Cron entry - Every 2 minutes
*/2 * * * * /opt/scripts/monitor-website.sh
# Script: /opt/scripts/monitor-website.sh
#!/bin/bash
set -euo pipefail
URLS=(
"https://example.com"
"https://api.example.com/health"
"https://admin.example.com"
)
LOG_FILE="/var/log/website-monitor.log"
for url in "${URLS[@]}"; do
if ! curl -f -s -o /dev/null -w "%{http_code}" --max-time 10 "$url" | grep -q "200"; then
echo "[$(date)] FAILED: $url" | tee -a "$LOG_FILE"
echo "Website $url is down" | mail -s "Website Down Alert" [email protected]
else
echo "[$(date)] OK: $url" >> "$LOG_FILE"
fi
done
6. Actualizaciones de Seguridad Automáticas
# Cron entry - Daily at 4 AM
0 4 * * * /opt/scripts/security-updates.sh
# Script: /opt/scripts/security-updates.sh
#!/bin/bash
set -euo pipefail
LOG_FILE="/var/log/security-updates.log"
{
echo "Starting security updates: $(date)"
# Ubuntu/Debian
if command -v apt-get &>/dev/null; then
apt-get update
apt-get upgrade -y --only-upgrade
apt-get autoremove -y
apt-get autoclean
fi
# CentOS/Rocky Linux
if command -v yum &>/dev/null; then
yum update -y --security
yum autoremove -y
fi
echo "Security updates completed: $(date)"
} | tee -a "$LOG_FILE"
# Check if reboot required
if [ -f /var/run/reboot-required ]; then
echo "Reboot required after updates" | mail -s "Reboot Required" [email protected]
fi
7. Limpieza de Espacio en Disco
# Cron entry - Weekly on Sunday at 1 AM
0 1 * * 0 /opt/scripts/cleanup-disk.sh
# Script: /opt/scripts/cleanup-disk.sh
#!/bin/bash
set -euo pipefail
# Remove old temporary files
find /tmp -type f -atime +7 -delete
find /var/tmp -type f -atime +7 -delete
# Clean package manager cache
apt-get clean 2>/dev/null || yum clean all 2>/dev/null
# Remove old log files
find /var/log -name "*.log.*" -mtime +30 -delete
find /var/log -name "*.gz" -mtime +30 -delete
# Clean Docker resources
docker system prune -af --volumes --filter "until=720h" 2>/dev/null || true
# Remove old kernels (Ubuntu/Debian)
if command -v apt-get &>/dev/null; then
apt-get autoremove --purge -y
fi
echo "Disk cleanup completed: $(date)"
8. Optimización de Base de Datos
# Cron entry - Weekly on Saturday at 2 AM
0 2 * * 6 /opt/scripts/optimize-database.sh
# Script: /opt/scripts/optimize-database.sh
#!/bin/bash
set -euo pipefail
DB_USER="admin"
DB_PASS="password"
# MySQL/MariaDB optimization
mysql -u"$DB_USER" -p"$DB_PASS" -e "SHOW DATABASES;" | \
grep -Ev "Database|information_schema|performance_schema|mysql" | \
while read -r db; do
echo "Optimizing database: $db"
mysqlcheck -u"$DB_USER" -p"$DB_PASS" --optimize --skip-write-binlog "$db"
done
# PostgreSQL vacuum
sudo -u postgres psql -c "VACUUM ANALYZE;"
echo "Database optimization completed: $(date)"
Variables de Entorno en Cron
Cron se ejecuta con un entorno mínimo. Establece las variables requeridas:
# Set PATH and other variables at the top of crontab
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
SHELL=/bin/bash
[email protected]
# Then your cron jobs
0 2 * * * /opt/scripts/backup.sh
Manejo de Salida
Redirigir Salida a Archivo de Registro
# Append stdout and stderr to log file
0 2 * * * /opt/scripts/backup.sh >> /var/log/backup.log 2>&1
# Separate stdout and stderr
0 2 * * * /opt/scripts/backup.sh >> /var/log/backup.log 2>> /var/log/backup-error.log
# Discard all output
0 2 * * * /opt/scripts/backup.sh > /dev/null 2>&1
Salida por Correo Electrónico
# Set MAILTO at top of crontab
[email protected]
# Cron will email output
0 2 * * * /opt/scripts/backup.sh
# Or use mail command in script
0 2 * * * /opt/scripts/backup.sh | mail -s "Backup Report" [email protected]
Resolución de Problemas de Trabajos Cron
Verificar si Cron está Ejecutándose
# Check cron service status
systemctl status cron # Debian/Ubuntu
systemctl status crond # CentOS/Rocky Linux
# Check if cron daemon is running
ps aux | grep cron
# Restart cron if needed
sudo systemctl restart cron
Ver Registros de Cron
# View cron execution log
tail -f /var/log/syslog | grep CRON # Debian/Ubuntu
tail -f /var/log/cron # CentOS/Rocky Linux
# View recent cron activity
grep CRON /var/log/syslog | tail -20 # Debian/Ubuntu
tail -20 /var/log/cron # CentOS/Rocky Linux
Problemas Comunes y Soluciones
Problema: El trabajo cron no se ejecuta
# Verify cron syntax
# Use online tools: crontab.guru
# Check cron service
systemctl status cron
# Check user crontab
crontab -l
# Check system logs
grep CRON /var/log/syslog
Problema: El script funciona manualmente pero no en cron
# Use absolute paths
# Bad: backup.sh
# Good: /opt/scripts/backup.sh
# Set PATH in crontab
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
# Use full paths in script
/usr/bin/mysql instead of mysql
Problema: Permisos denegados
# Check script permissions
chmod +x /opt/scripts/backup.sh
# Check file ownership
chown user:user /opt/scripts/backup.sh
# Run as specific user
sudo crontab -e -u username
Probando Trabajos Cron
# Test script manually
bash -x /opt/scripts/backup.sh
# Test with cron's environment
env -i HOME=$HOME LOGNAME=$LOGNAME PATH=/usr/bin:/bin SHELL=/bin/bash /bin/sh -c '/opt/scripts/backup.sh'
# Temporary frequent execution for testing
* * * * * /opt/scripts/test-script.sh
# After testing, remove or change to desired schedule
Mejores Prácticas
1. Usar Rutas Absolutas
# Bad
0 2 * * * backup.sh
# Good
0 2 * * * /opt/scripts/backup.sh
2. Establecer Variables de Entorno
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
SHELL=/bin/bash
[email protected]
3. Implementar Registro
0 2 * * * /opt/scripts/backup.sh >> /var/log/backup.log 2>&1
4. Agregar Comentarios
# Daily database backup at 2 AM
0 2 * * * /opt/scripts/db-backup.sh
# Clean temporary files every Sunday
0 1 * * 0 /opt/scripts/cleanup.sh
5. Manejar Errores
#!/bin/bash
set -euo pipefail
# Error handling in script
trap 'echo "Error occurred"' ERR
# Your script logic
6. Usar Bloqueo
Prevenir múltiples instancias:
#!/bin/bash
LOCKFILE="/var/run/backup.lock"
# Check if already running
if [ -f "$LOCKFILE" ]; then
echo "Script already running"
exit 1
fi
# Create lock file
touch "$LOCKFILE"
# Cleanup on exit
trap "rm -f $LOCKFILE" EXIT
# Your script logic
7. Monitorear Ejecución
# Log start and end times
#!/bin/bash
echo "Started: $(date)" >> /var/log/script.log
# Your script logic
echo "Completed: $(date)" >> /var/log/script.log
Consideraciones de Seguridad
Permisos de Archivos
# Crontab files should not be world-readable
chmod 600 ~/.crontab
# Script files should have appropriate permissions
chmod 750 /opt/scripts/backup.sh
# Restrict directory access
chmod 750 /opt/scripts
Datos Sensibles
# Don't put passwords in crontab or scripts
# Use environment files or secret management
source /etc/backup.conf # Contains DB_PASS
# Or use .my.cnf for MySQL
mysqldump --defaults-file=/root/.my.cnf
Aislamiento de Usuario
# Run jobs as specific users
sudo crontab -e -u backup-user
# Use dedicated service accounts
# Don't run everything as root
Alternativa: Anacron
Para sistemas que no siempre están encendidos:
# Install anacron
sudo apt-get install anacron
# Edit /etc/anacrontab
1 5 daily-backup /opt/scripts/backup.sh
7 10 weekly-cleanup /opt/scripts/cleanup.sh
Conclusión
Cron es una herramienta esencial para automatizar tareas rutinarias en entornos Linux. Esta guía cubrió todo, desde la sintaxis básica hasta patrones avanzados y ejemplos listos para producción. Domina estos conceptos para automatizar efectivamente el mantenimiento de tu infraestructura, monitoreo y tareas operacionales.
Puntos clave:
- Comprender la sintaxis y caracteres especiales de cron
- Usar rutas absolutas y establecer variables de entorno
- Implementar registro completo
- Manejar errores con gracia
- Probar exhaustivamente antes de producción
- Monitorear la ejecución de trabajos cron
- Seguir mejores prácticas de seguridad
- Documentar tus tareas programadas
Recuerda que aunque cron es poderoso, los sistemas modernos pueden beneficiarse de los temporizadores systemd para necesidades de programación más avanzadas. Considera tus requisitos y elige la herramienta adecuada para tus necesidades de automatización.


