Automatizar tareas repetitivas es una de las formas más simples de ahorrar tiempo y evitar errores en un servidor Linux. Si cada día tienes que lanzar una copia de seguridad, limpiar archivos temporales, generar un informe, sincronizar datos o ejecutar un script de mantenimiento, cron permite programarlo para que ocurra solo.
Cron es una herramienta clásica Linux que ejecuta comandos en momentos concretos. Su ventaja principal es que es sencilla, está disponible en casi cualquier sistema y funciona muy bien para trabajos periódicos. Su dificultad habitual no está en instalarla, sino en entender bien la sintaxis, el entorno de ejecución y la forma correcta de registrar errores.
En esta guía veremos qué es cron, cómo funciona crontab, cómo escribir horarios comunes, qué diferencias hay entre el crontab de usuario y el crontab del sistema, cómo evitar problemas con rutas y variables de entorno, cómo guardar logs, cómo programar backups y scripts, qué permisos revisar, cómo solucionar fallos y cuándo conviene usar systemd timers en lugar de cron.
👉 Y recuerda, si quieres aprender más de Linux, pincha en este curso de Linux gratis
👉 También te dejo por aquí una guía de comandos Linux por categorías
Qué es cron
Cron es un demonio del sistema. Esto significa que se ejecuta en segundo plano y revisa de forma periódica si hay tareas pendientes. Cuando llega la hora configurada, cron lanza el comando indicado.
Cada tarea programada suele llamarse cron job. La lista de tareas se guarda en archivos llamados crontabs. Un crontab contiene líneas con dos partes:
- Cuándo se ejecuta la tarea.
- Qué comando se ejecuta.
Un ejemplo sencillo:
0 2 * * * /usr/local/bin/backup.shEsta línea ejecuta el script /usr/local/bin/backup.sh todos los días a las 02:00.
Cron no está pensado solo para administradores de sistemas. También puede ser útil para desarrolladores, creadores de contenido, equipos de datos, gestores de tiendas online o cualquier persona que tenga tareas repetitivas en un servidor.
Cómo funciona la sintaxis de crontab
La sintaxis más común de cron tiene cinco campos de tiempo y después el comando:
* * * * * comando
| | | | |
| | | | +-- día de la semana (0-7, donde 0 y 7 suelen ser domingo)
| | | +---- mes (1-12)
| | +------ día del mes (1-31)
| +-------- hora (0-23)
+---------- minuto (0-59)Los cinco campos se leen de izquierda a derecha:
minuto hora día_del_mes mes día_de_la_semanaPor ejemplo:
30 6 * * 1 /home/usuario/scripts/informe-semanal.shEsto significa: minuto 30, hora 6, cualquier día del mes, cualquier mes, lunes. En lenguaje normal: cada lunes a las 06:30.
El asterisco
El asterisco significa «todos los valores posibles» para ese campo.
* * * * * comandoEjecuta el comando cada minuto. Es útil para pruebas muy concretas, pero en producción hay que usarlo con cuidado porque puede generar demasiada carga.
Valores concretos
Puedes indicar un valor fijo:
15 9 * * * comandoEjecuta el comando todos los días a las 09:15.
Listas
Puedes indicar varios valores separados por comas:
0 9,13,18 * * * comandoEjecuta el comando a las 09:00, 13:00 y 18:00.
Rangos
Puedes indicar un rango con guion:
0 8-18 * * 1-5 comandoEjecuta el comando cada hora, de 08:00 a 18:00, de lunes a viernes.
Intervalos
Puedes usar una barra para expresar «cada X unidades»:
*/10 * * * * comandoEjecuta el comando cada 10 minutos.
También puedes combinar rangos e intervalos:
*/15 9-17 * * 1-5 comandoEjecuta el comando cada 15 minutos entre las 09:00 y las 17:59, de lunes a viernes.
Horarios comunes con cron
Estos ejemplos cubren muchos casos habituales:
# Cada minuto
* * * * * comando
# Cada 5 minutos
*/5 * * * * comando
# Cada hora, en el minuto 0
0 * * * * comando
# Todos los días a medianoche
0 0 * * * comando
# Todos los días a las 02:30
30 2 * * * comando
# Cada lunes a las 08:00
0 8 * * 1 comando
# De lunes a viernes a las 09:00
0 9 * * 1-5 comando
# El día 1 de cada mes a las 03:00
0 3 1 * * comando
# Cada domingo a las 23:30
30 23 * * 0 comandoAlgunas implementaciones de cron también aceptan atajos:
@hourly comando
@daily comando
@weekly comando
@monthly comando
@yearly comando
@reboot comando@reboot ejecuta el comando al arrancar el sistema. Es cómodo para tareas simples, pero no reemplaza a un servicio bien definido cuando necesitas reinicios controlados, dependencias de red o supervisión.
Crontab de usuario
Cada usuario puede tener su propio crontab. Para editarlo:
crontab -ePara listar las tareas del usuario actual:
crontab -lPara eliminar todo el crontab del usuario actual:
crontab -rEste último comando debe usarse con mucha precaución porque borra todas las tareas programadas de ese usuario.
El crontab de usuario no incluye un campo para indicar el usuario que ejecuta la tarea. La tarea se ejecuta como el usuario dueño del crontab.
Ejemplo:
0 2 * * * /home/ana/scripts/backup-proyecto.shSi Ana añade esa línea con crontab -e, el script se ejecutará con los permisos de Ana.
Crontab del sistema
Además de los crontabs de usuario, Linux puede tener archivos de cron del sistema, como:
/etc/crontab
/etc/cron.d/
/etc/cron.hourly/
/etc/cron.daily/
/etc/cron.weekly/
/etc/cron.monthly/La diferencia importante es que /etc/crontab y los archivos dentro de /etc/cron.d/ suelen incluir un campo adicional para el usuario:
0 2 * * * root /usr/local/sbin/backup-global.shAquí el formato es:
minuto hora día_del_mes mes día_de_la_semana usuario comandoEse campo root indica que el comando se ejecuta como root.
Esta diferencia causa muchos errores. Una línea válida en /etc/crontab puede no ser válida en crontab -e, y al revés.
En general:
- Usa crontab -e para tareas de un usuario concreto.
- Usa /etc/cron.d/ o /etc/crontab para tareas de administración del sistema.
- Evita ejecutar como root si no es necesario.
- Mantén cada tarea del sistema en un archivo claro y documentado dentro de /etc/cron.d/ cuando sea posible.
El problema del entorno: cron no es tu terminal
Uno de los fallos más frecuentes al automatizar tareas con cron es asumir que el comando se ejecutará con el mismo entorno que en una sesión interactiva.
Cuando abres una terminal, tu shell carga archivos como .bashrc, .profile o .zshrc. Ahí suelen definirse variables, alias, rutas y configuraciones. Cron normalmente no carga todo eso.
Por eso un comando que funciona en la terminal puede fallar en cron.
Ejemplo problemático:
0 2 * * * python backup.pyPuede fallar porque cron no sabe dónde está python, no está en el directorio correcto o no encuentra backup.py.
Una versión más fiable:
0 2 * * * cd /home/usuario/proyecto && /usr/bin/python3 /home/usuario/proyecto/backup.pyMejor todavía, mover la lógica a un script:
#!/usr/bin/env bash
set -euo pipefail
cd /home/usuario/proyecto
/usr/bin/python3 backup.pyY en cron:
0 2 * * * /home/usuario/scripts/backup-proyecto.shUsa rutas absolutas
En cron conviene usar rutas absolutas casi siempre:
0 1 * * * /usr/bin/php /var/www/html/artisan schedule:runEn lugar de:
0 1 * * * php artisan schedule:runPara encontrar la ruta de un binario:
which php
which python3
which rsyncTambién puedes usar:
command -v python3Si tu script depende de variables de entorno, defínelas dentro del propio script o al principio del crontab.
Ejemplo:
SHELL=/bin/bash
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
0 2 * * * /home/usuario/scripts/tarea.shNo abuses de variables sensibles en crontab. Si necesitas credenciales, suele ser mejor usar archivos de configuración con permisos restrictivos, gestores de secretos o variables cargadas por un script controlado.
Registrar la salida y los errores
Por defecto, si cron tiene una salida y el sistema está configurado para correo local, puede intentar enviar un email al usuario. En muchos servidores modernos esto no está bien configurado, así que los errores pueden pasar desapercibidos.
Es buena práctica redirigir la salida a un archivo de log:
0 2 * * * /home/usuario/scripts/backup.sh >> /var/log/backup.log 2>&1Esto hace dos cosas:
- >> /var/log/backup.log añade la salida estándar al archivo.
- 2>&1 envía los errores al mismo destino.
Si no tienes permisos para escribir en /var/log, usa un directorio del usuario:
0 2 * * * /home/usuario/scripts/backup.sh >> /home/usuario/logs/backup.log 2>&1Para evitar logs infinitos, configura rotación de logs con logrotate o haz que el script escriba solo información útil.
También puedes incluir marcas de tiempo:
#!/usr/bin/env bash
set -euo pipefail
echo "[$(date -Iseconds)] Iniciando backup"
rsync -a /var/www/html/ /backups/web/
echo "[$(date -Iseconds)] Backup terminado"Un log sin fechas sirve de poco cuando investigas una incidencia.
Dónde mirar cuando algo falla
Los logs dependen de la distribución. Lugares comunes:
/var/log/syslog
/var/log/cron
/var/log/messages
journalctlEn sistemas con systemd:
journalctl -u cronO, según la distribución:
journalctl -u crondTambién puedes buscar menciones a cron:
grep CRON /var/log/syslogSi redirigiste la salida de tu tarea, revisa además tu propio archivo de log:
tail -n 100 /home/usuario/logs/backup.logErrores frecuentes con cron
Estos son los problemas más comunes:
El comando funciona en terminal, pero no en cron
Casi siempre se debe a entorno, rutas relativas o variables no cargadas. Usa rutas absolutas, define PATH y cambia al directorio correcto dentro del script.
El script no se ejecuta
Comprueba permisos, propietario, ruta exacta, bit de ejecución y formato del archivo. Si el script fue editado en Windows, puede tener finales de línea incompatibles. Puedes revisarlo con:
file script.shEl log está vacío
Puede que el comando ni siquiera se esté lanzando, que el usuario no tenga permisos para escribir el log o que la redirección esté mal escrita. Prueba con una tarea simple:
* * * * * date >> /tmp/prueba-cron.log 2>&1Espera uno o dos minutos y revisa:
cat /tmp/prueba-cron.logLa tarea se ejecuta a una hora inesperada
Revisa la zona horaria del servidor:
timedatectlTambién confirma si la hora esperada está en UTC o en hora local. En servidores, este detalle causa confusiones frecuentes.
La tarea se ejecuta dos veces
Puede estar definida en dos sitios: en el crontab del usuario, en /etc/crontab, en /etc/cron.d/ o dentro de un scheduler de la propia aplicación. Busca duplicados antes de culpar a cron.
Así evitas que una tarea colgada se acumule durante horas.
mers suelen ser más robustos.
Checklist antes de dejar un cron job en producción
Antes de considerar terminada una automatización con cron, revisa:
- El comando usa rutas absolutas.
- El script se puede ejecutar manualmente.
- El usuario correcto tiene permisos suficientes.
- La tarea no necesita privilegios innecesarios.
- Hay logs de salida y de error.
- Los logs no crecerán sin control.
- El horario está confirmado con la zona horaria del servidor.
- No hay duplicados en otros crontabs.
- Hay bloqueo si la tarea no debe solaparse.
- Los comandos destructivos tienen validaciones.
- El script devuelve códigos de salida útiles.
- Existe una forma clara de comprobar si funcionó.
Conclusión
La automatización de tareas con cron es una habilidad básica pero muy poderosa para administrar servidores y proyectos. Con una sola línea puedes programar backups, limpiezas, informes, sincronizaciones y procesos recurrentes.
Como regla general, empieza simple: escribe un script que funcione manualmente, usa cron solo para programarlo, registra la salida y revisa los logs. Si la tarea empieza a necesitar dependencias, supervisión o recuperación de ejecuciones perdidas, plantéate pasarla a systemd timers.
