Si alguna vez has tenido que ejecutar un script todas las mañanas, hacer una copia de seguridad cada noche o reiniciar un servicio cada semana, sabes lo tedioso que es acordarse de hacerlo manualmente. Para eso existe cron, el programador de tareas más antiguo —y todavía el más fiable— de los sistemas Unix y Linux.
En esta guía práctica vas a aprender qué es cron, cómo funciona su sintaxis, cómo crear tus primeras tareas programadas y cómo evitar los errores más comunes. Todo con ejemplos que puedes probar en tu propio equipo.
¿Qué es cron y por qué deberías usarlo?
Cron es un demonio (un proceso que se ejecuta en segundo plano) presente en prácticamente todos los sistemas Linux y macOS. Su trabajo es simple: leer un archivo de configuración llamado crontab y ejecutar los comandos que encuentre en el momento exacto que se le haya indicado.
Lleva en el ecosistema Unix desde los años 70, y sigue siendo la herramienta más usada para automatización básica por una razón: es estable, ligera y no necesita instalación adicional. En cualquier servidor Linux que contrates, cron ya está funcionando.
¿Qué tipo de tareas se automatizan con cron?
- Copias de seguridad de bases de datos o archivos
- Limpieza de logs y archivos temporales
- Envío de correos programados
- Actualización de certificados SSL
- Generación de informes periódicos
- Publicación de contenido en blogs y redes sociales
- Monitorización de servicios y reinicio automático si caen
La sintaxis del crontab: los cinco asteriscos
El corazón de cron es el archivo crontab. Cada línea de este archivo define una tarea con un formato muy concreto:
minuto hora día-del-mes mes día-de-la-semana comando
Cinco campos de tiempo seguidos del comando a ejecutar. En orden:
| Campo | Valores | Significado |
|---|---|---|
| minuto | 0–59 | ¿En qué minuto se ejecuta? |
| hora | 0–23 | ¿En qué hora? |
| día del mes | 1–31 | ¿Qué día del mes? |
| mes | 1–12 | ¿Qué mes? |
| día de la semana | 0–7 | ¿Qué día de la semana? (0 y 7 = domingo) |
Cada campo admite asterisco (*) para indicar «todos los valores posibles», números concretos, listas separadas por comas, rangos con guion e intervalos con barra.
Ejemplos prácticos:
# Ejecutar un script todos los días a las 3:30 de la madrugada
30 3 * * * /home/usuario/backup.sh
# Ejecutar cada hora, en el minuto 0
0 * * * * /usr/bin/php /var/www/actualizar.php
# Ejecutar cada lunes a las 9 de la mañana
0 9 * * 1 /usr/local/bin/enviar-informe.sh
# Ejecutar el primer día de cada mes a medianoche
0 0 1 * * /usr/bin/renovar-certificados.sh
Atajos especiales
Para no tener que escribir los cinco campos siempre, existen atajos:
| Atajo | Equivalente | Significado |
|---|---|---|
@reboot |
— | Al arrancar el sistema |
@hourly |
0 * * * * |
Cada hora |
@daily |
0 0 * * * |
Cada día a medianoche |
@weekly |
0 0 * * 0 |
Cada domingo a medianoche |
@monthly |
0 0 1 * * |
Primer día del mes a medianoche |
Ejemplo:
@daily /home/usuario/scripts/limpiar-temporales.sh
@reboot /home/usuario/scripts/levantar-servicios.sh
Cómo crear y editar tu primer crontab
Para editar tu crontab personal, el comando es:
crontab -e
La primera vez que lo ejecutes, te preguntará qué editor quieres usar (nano, vim, etc.). Elige el que más te guste; si no sabes, nano es el más sencillo.
Una vez dentro, cada línea nueva es una tarea. Las líneas que empiezan por # son comentarios y se ignoran.
# Mi primer cron job: escribir la fecha en un archivo cada minuto
* * * * * echo "Ejecutado: $(date)" >> /tmp/mi-cron.log
Guarda y cierra el editor. Si todo está bien, verás un mensaje como «installing new crontab». Si hay errores de sintaxis, cron te avisará.
Ver tus crontabs activos
crontab -l
Esto muestra todas las tareas programadas para tu usuario. Si no tienes ninguna, no muestra nada o te dice «no crontab for usuario».
Eliminar todas tus tareas
crontab -r
Cuidado: esto borra todo tu crontab sin preguntar. No hay papelera.
Ejemplos prácticos para el día a día
Vamos a ver algunos ejemplos reales que puedes usar desde ya.
Copia de seguridad de una base de datos cada noche a las 2:00
0 2 * * * /usr/bin/mysqldump -u usuario -pcontraseña basedatos > /backups/bd-$(date +\%Y\%m\%d).sql
⚠️ Importante: el signo % en crontab debe escaparse como \%. Si no lo haces, cron interpreta el % como un salto de línea.
Limpiar archivos temporales de más de 7 días cada domingo
0 6 * * 0 find /tmp -type f -mtime +7 -delete
Reiniciar un servicio cada día a las 6 de la mañana
0 6 * * * /usr/bin/systemctl restart nginx
Publicar una entrada en un blog cada día a las 9:00
0 9 * * * /home/usuario/scripts/publicar-noticia.sh
Este ejemplo es exactamente lo que hacen los cron jobs del blog icenico.es, uno para publicar noticias de IA a las 9:00 y otro para tutoriales a las 12:00.
Redirección de salida y logs
Por defecto, cron intenta enviar por correo la salida estándar de cada tarea al usuario local. Si no tienes un servidor de correo configurado (que es lo más común en equipos de escritorio y servidores básicos), puedes recibir errores en /var/mail/usuario o simplemente perder la salida.
Solución: redirigir la salida manualmente.
# Redirigir salida estándar y errores a un archivo de log
30 4 * * * /home/usuario/scripts/backup.sh >> /var/log/backup.log 2>&1
Desglose:
- >> añade la salida estándar al final del archivo (no sobreescribe)
- 2>&1 redirige los errores (stderr, stream 2) al mismo sitio que la salida estándar (stdout, stream 1)
Si no te interesa ver la salida en absoluto (por ejemplo, si el script ya gestiona su propio logging), puedes enviarlo todo a /dev/null, el «agujero negro» de Linux:
0 * * * * /home/usuario/scripts/comprobar.sh > /dev/null 2>&1
Errores comunes y cómo evitarlos
1. Rutas absolutas
Cron ejecuta los comandos con un entorno mínimo. La variable PATH que tienes en tu terminal no está disponible. Usa siempre rutas absolutas para comandos y archivos.
# ❌ MAL: puede fallar porque cron no encuentra "php"
0 9 * * * php /ruta/script.php
# ✅ BIEN: ruta absoluta al binario
0 9 * * * /usr/bin/php /ruta/script.php
Para averiguar la ruta absoluta de un comando: which php o whereis php.
2. El porcentaje % se escapa
En crontab, el signo % tiene un significado especial (salto de línea). Si lo usas en un comando (por ejemplo, en date +%Y%m%d), debes escaparlo:
# ✅ Así se usa date en cron
0 2 * * * echo "Fecha: $(date +\%Y\%m\%d)" >> /tmp/fechas.log
3. Las variables de entorno no están
Cron no carga tu .bashrc, .zshrc ni ninguna configuración de tu shell. Si tu script depende de variables de entorno (por ejemplo, DATABASE_URL, API_KEY), tienes dos opciones:
- Cargar las variables al inicio del script:
source /home/usuario/.env - Definir variables en el propio crontab antes de los comandos
# Definir variables al inicio del crontab
PATH=/usr/local/bin:/usr/bin:/bin
[email protected]
# Y luego usarlas en los comandos
0 9 * * * /usr/bin/env | mail -s "Entorno cron" $EMAIL
4. El script funciona manualmente pero no en cron
Este es el error más frecuente. Si el script funciona cuando lo ejecutas a mano desde la terminal pero falla en cron, casi siempre es por el PATH o por las rutas relativas.
Depuración: añade logging al principio del script:
#!/bin/bash
echo "Ejecutado: $(date)" >> /tmp/mi-script.log
echo "PATH: $PATH" >> /tmp/mi-script.log
echo "PWD: $PWD" >> /tmp/mi-script.log
which php >> /tmp/mi-script.log 2>&1
Ejecuta el script manualmente una vez para confirmar que funciona, luego déjalo en cron y revisa el log al minuto siguiente.
Crontab del sistema vs crontab de usuario
Además del crontab personal (crontab -e), existen crontabs del sistema en /etc/crontab y en /etc/cron.d/. La diferencia principal es que el crontab del sistema tiene un campo adicional: el usuario que ejecutará el comando.
# Formato del crontab del sistema:
minuto hora día mes día_semana usuario comando
Ejemplo en /etc/crontab:
0 4 * * * root /usr/sbin/logrotate /etc/logrotate.conf
Para tareas cotidianas, usa siempre crontab -e. Los crontabs del sistema son para administración del propio sistema operativo.
Herramientas modernas: systemd timers
En las distribuciones Linux modernas, systemd ofrece una alternativa a cron llamada systemd timers. Son más potentes (permiten dependencias entre tareas, triggers por eventos, logging integrado con journald), pero también más verbosos: requieren crear dos archivos (un servicio y un timer) en lugar de una sola línea.
Ejemplo mínimo de un timer de systemd:
# /etc/systemd/system/mi-tarea.timer
[Unit]
Description=Ejecuta mi script cada hora
[Timer]
OnCalendar=hourly
Persistent=true
[Install]
WantedBy=timers.target
Y su servicio asociado:
# /etc/systemd/system/mi-tarea.service
[Unit]
Description=Mi script programado
[Service]
ExecStart=/home/usuario/scripts/mi-script.sh
Para la mayoría de los casos, cron sigue siendo más sencillo y directo. Los systemd timers merecen la pena cuando necesitas control fino sobre cuándo y cómo se ejecuta una tarea, o cuando ya estás usando systemd para gestionar servicios.
Conclusión
Cron es una de esas herramientas que, una vez que empiezas a usar, te preguntas cómo vivías sin ella. Su sintaxis es críptica al principio, pero con los cinco campos y los atajos especiales cubres el 99% de las necesidades de automatización del día a día.
Reglas de oro para no fallar:
- Usa siempre rutas absolutas para comandos y archivos
- Redirige la salida a un archivo de log para poder depurar
- Escapa los signos
%con\% - Prueba el script manualmente antes de ponerlo en cron
- Empieza con tiempos cortos (cada minuto) para verificar que funciona, luego ajusta al intervalo deseado
La automatización con cron te libera de tener que acordarte de tareas rutinarias y, en un servidor, es la diferencia entre tener que estar pendiente constantemente o dormir tranquilo sabiendo que todo se ejecuta solo.
¿Tienes ya una tarea repetitiva en mente? Esa es la candidata perfecta para tu primer cron job.