--- title: "Cómo programar tareas con cron en Ubuntu 24.04" description: "Aprende la sintaxis de cron y programa tareas en Ubuntu 24.04 con crontab y /etc/cron.d, controla el entorno, evita solapamientos con flock y revisa los logs." category: "Herramientas de Automatización" language: es source: https://cubepath.com/es/docs/herramientas-de-automatización/trabajos-cron-sintaxis-y-ejemplos-practicos updated: 2026-09-25 --- # Cómo programar tareas con cron en Ubuntu 24.04 Cron es el planificador clásico de Unix: un demonio que cada minuto revisa las tablas de tareas (crontabs) y ejecuta los comandos cuya hora coincide. Sigue siendo la forma más sencilla de lanzar copias de seguridad, limpiezas o sincronizaciones periódicas. En este tutorial aprenderás la sintaxis de cron y programarás tareas en Ubuntu 24.04, tanto de usuario como de sistema, controlando su entorno, su salida y los solapamientos. ## Requisitos previos Para seguir esta guía necesitas: - Un servidor con Ubuntu 24.04 LTS, por ejemplo un VPS de CubePath. En Debian 12 todo funciona igual. - Un usuario no root con privilegios `sudo`. ## Paso 1: Comprobar que cron está activo Ubuntu instala y arranca cron por defecto. Comprueba el estado del servicio: ```bash systemctl status cron ``` ```output ● cron.service - Regular background program processing daemon Loaded: loaded (/usr/lib/systemd/system/cron.service; enabled; preset: enabled) Active: active (running) since Thu 2026-09-25 09:12:44 UTC; 1h 3min ago ``` Si no aparece instalado (algunas imágenes mínimas lo omiten), instálalo y actívalo: ```bash sudo apt install cron sudo systemctl enable --now cron ``` Cron usa la zona horaria del sistema. Compruébala antes de programar nada, porque `0 3 * * *` significa las 03:00 de esa zona: ```bash timedatectl | grep "Time zone" ``` ```output Time zone: Etc/UTC (UTC, +0000) ``` Si la cambias con `sudo timedatectl set-timezone Europe/Madrid`, reinicia cron después con `sudo systemctl restart cron` para que la aplique. ## Paso 2: Entender la sintaxis de cron Cada línea de un crontab tiene cinco campos de tiempo seguidos del comando: ```text minuto hora día_del_mes mes día_de_la_semana comando ``` | Posición | Campo | Valores permitidos | |---|---|---| | 1 | Minuto | 0-59 | | 2 | Hora | 0-23 | | 3 | Día del mes | 1-31 | | 4 | Mes | 1-12 o `jan`-`dec` | | 5 | Día de la semana | 0-7 (0 y 7 son domingo) o `sun`-`sat` | Dentro de cada campo puedes usar: - `*`: cualquier valor. - `,`: lista de valores, como `1,15`. - `-`: rango, como `1-5`. - `/`: intervalo, como `*/10` (cada 10) o `9-17/2` (de 9 a 17 cada 2). Algunos ejemplos habituales: | Expresión | Cuándo se ejecuta | |---|---| | `*/5 * * * *` | Cada 5 minutos | | `0 * * * *` | Al principio de cada hora | | `30 3 * * *` | Todos los días a las 03:30 | | `0 9 * * 1` | Los lunes a las 09:00 | | `0 18 * * 1-5` | De lunes a viernes a las 18:00 | | `*/15 9-17 * * 1-5` | Cada 15 minutos en horario laboral | | `0 0 1 * *` | El día 1 de cada mes a medianoche | | `0 6,18 * * *` | A las 06:00 y a las 18:00 | También existen atajos que sustituyen a los cinco campos: `@hourly`, `@daily`, `@weekly`, `@monthly`, `@yearly` y `@reboot` (una vez al arrancar cron). Hay dos reglas que causan muchos errores: - Si indicas a la vez día del mes y día de la semana, cron ejecuta la tarea cuando se cumple **cualquiera** de los dos, no ambos. `0 0 13 * 5` se ejecuta todos los días 13 y todos los viernes. - El carácter `%` en el comando se convierte en un salto de línea. Para usarlo, por ejemplo en `date +%F`, escríbelo como `\%`. ## Paso 3: Crear tu primera tarea con crontab Cada usuario tiene su propio crontab, que se edita con `crontab -e`. La primera vez te pedirá que elijas un editor; `nano` es la opción más sencilla: ```bash crontab -e ``` Añade al final del archivo una tarea de prueba que escriba la fecha cada minuto. Sustituye `your_user` por tu nombre de usuario: ```text * * * * * /usr/bin/date >> /home/your_user/cron-test.log 2>&1 ``` Guarda y cierra. Cron verifica la sintaxis al guardar y muestra `crontab: installing new crontab`. Lista tu crontab para confirmarlo: ```bash crontab -l | tail -n 1 ``` ```output * * * * * /usr/bin/date >> /home/your_user/cron-test.log 2>&1 ``` Espera un par de minutos y revisa el archivo: ```bash cat ~/cron-test.log ``` ```output Thu Sep 25 10:21:01 UTC 2026 Thu Sep 25 10:22:01 UTC 2026 ``` Cuando hayas comprobado que funciona, vuelve a `crontab -e` y borra la línea de prueba. Evita `crontab -r`: borra todo tu crontab sin pedir confirmación. Como administrador puedes ver o editar el crontab de otro usuario con `sudo crontab -u otro_usuario -l` o `sudo crontab -u otro_usuario -e`. ## Paso 4: Controlar el entorno de las tareas Cron no carga tu `.bashrc` ni tu perfil. Las tareas se ejecutan con `/bin/sh` y un `PATH` mínimo (`/usr/bin:/bin`), por eso un comando que funciona en la terminal puede fallar en cron con `command not found`. Hay dos soluciones, y conviene aplicar ambas: 1. Usar rutas absolutas en los comandos y scripts (`/usr/local/bin/mi-script`, no `mi-script`). 2. Declarar las variables al principio del crontab. Abre de nuevo tu crontab y añade estas líneas al principio: ```text SHELL=/bin/bash PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin MAILTO="" ``` `MAILTO=""` desactiva el envío de la salida por correo. Sin un servidor de correo configurado esos mensajes no llegan a ninguna parte, así que es mejor redirigir la salida explícitamente, como verás en el paso 7. Para reproducir el entorno de cron al probar un script, ejecútalo con un entorno vacío: ```bash env -i HOME="$HOME" PATH=/usr/bin:/bin /bin/sh -c '/usr/local/bin/mi-script' ``` Si falla así, fallará también en cron. ## Paso 5: Crear tareas del sistema en /etc/cron.d Para tareas que forman parte de la configuración del servidor (y que quieres gestionar como archivos, por ejemplo con Ansible), usa `/etc/cron.d`. Su formato tiene un campo más: el usuario que ejecuta el comando, entre la hora y el comando. Crea un archivo para una copia de seguridad diaria: ```bash sudo nano /etc/cron.d/local-backup ``` ```text SHELL=/bin/bash PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin # Copia de seguridad diaria a las 02:30 30 2 * * * root /usr/local/sbin/local-backup >> /var/log/local-backup.log 2>&1 ``` Ten en cuenta estas reglas, porque si no se cumplen cron ignora el archivo sin avisar: - El nombre solo puede contener letras, números, guiones y guiones bajos. Un archivo llamado `backup.cron` o `backup.sh` no se ejecuta. - El archivo debe pertenecer a root y no ser escribible por otros usuarios. - La última línea debe terminar con un salto de línea. Ajusta los permisos: ```bash sudo chmod 644 /etc/cron.d/local-backup ``` No hace falta reiniciar cron: detecta los cambios en `/etc/cron.d` y en los crontabs automáticamente. Además existen los directorios `/etc/cron.hourly`, `/etc/cron.daily`, `/etc/cron.weekly` y `/etc/cron.monthly`, donde basta con dejar un script ejecutable (con las mismas reglas de nombre). Para ver qué scripts se ejecutarían en `cron.daily`: ```bash run-parts --test /etc/cron.daily ``` ```output /etc/cron.daily/apt-compat /etc/cron.daily/dpkg /etc/cron.daily/logrotate ``` ## Paso 6: Evitar ejecuciones solapadas con flock Si una tarea tarda más que su intervalo, cron lanza otra copia aunque la anterior no haya terminado. Dos sincronizaciones escribiendo a la vez en el mismo destino pueden corromper datos. `flock`, incluido en Ubuntu, resuelve esto con un bloqueo de archivo: ```text */10 * * * * /usr/bin/flock -n /tmp/sync.lock /usr/local/bin/sync-data >> /home/your_user/sync.log 2>&1 ``` Con `-n`, si el bloqueo ya está tomado, `flock` termina de inmediato sin ejecutar el comando. El bloqueo se libera solo cuando termina el proceso, incluso si falla, así que no quedan archivos de bloqueo huérfanos como ocurre con los scripts que crean un `.pid` a mano. Para comprobar el comportamiento, abre dos terminales. En la primera toma el bloqueo durante 30 segundos: ```bash flock -n /tmp/sync.lock sleep 30 ``` En la segunda, intenta tomarlo mientras tanto: ```bash flock -n /tmp/sync.lock echo "ejecutado"; echo "código: $?" ``` ```output código: 1 ``` El comando no se ha ejecutado porque la primera instancia sigue en marcha. ## Paso 7: Registrar la salida y revisar los logs Por defecto la salida de una tarea se envía por correo al usuario, lo que sin un servidor de correo equivale a perderla. Redirígela siempre: | Redirección | Resultado | |---|---| | `>> /ruta/tarea.log 2>&1` | Añade la salida estándar y los errores a un archivo | | `2>&1 \| /usr/bin/logger -t mi-tarea` | Envía todo al journal con la etiqueta `mi-tarea` | | `> /dev/null 2>&1` | Descarta la salida (solo si de verdad no la necesitas) | Enviar la salida al journal evita tener que rotar archivos de log propios. Por ejemplo: ```text 0 4 * * * /usr/local/bin/sync-data 2>&1 | /usr/bin/logger -t sync-data ``` Y se consulta con: ```bash journalctl -t sync-data --since today ``` El propio demonio de cron registra cada ejecución en el journal. Para ver las últimas: ```bash journalctl -u cron -n 20 --no-pager ``` ```output sep 25 10:22:01 servidor CRON[5120]: pam_unix(cron:session): session opened for user your_user(uid=1000) by your_user(uid=0) sep 25 10:22:01 servidor CRON[5121]: (your_user) CMD (/usr/bin/date >> /home/your_user/cron-test.log 2>&1) sep 25 10:22:01 servidor CRON[5120]: pam_unix(cron:session): session closed for user your_user ``` La línea `CMD` confirma que cron lanzó el comando. Si aparece pero la tarea no hizo lo esperado, el problema está en el comando o en su entorno, no en la programación. ## Solución de problemas **La tarea no aparece en `journalctl -u cron`**: cron no la ha lanzado. Revisa la expresión de tiempo, que el archivo de `/etc/cron.d` cumpla las reglas de nombre y permisos del paso 5, y que la zona horaria sea la que esperas. **`command not found` o el script funciona a mano pero no en cron**: es el `PATH` reducido. Usa rutas absolutas o define `PATH` en el crontab, como en el paso 4. **El comando se corta en un `%`**: cron lo interpreta como salto de línea. Escápalo como `\%` o mueve el comando a un script. **`Permission denied`**: el script no es ejecutable o el usuario de la tarea no puede leer o escribir las rutas que usa. Comprueba con `ls -l` y ejecuta el script como ese usuario: `sudo -u otro_usuario /ruta/script`. ## Conclusión Has aprendido la sintaxis de cron, has programado tareas de usuario con `crontab -e` y de sistema en `/etc/cron.d`, has fijado su entorno, has evitado solapamientos con `flock` y sabes dónde mirar cuando una tarea no se ejecuta. Como siguientes pasos puedes: - Probar los temporizadores de systemd para tareas que necesiten dependencias entre servicios o recuperar ejecuciones perdidas con el servidor apagado. - Escribir los scripts que ejecuta cron con modo estricto (`set -euo pipefail`) para que los fallos no pasen desapercibidos. - Monitorizar las tareas críticas con un servicio de heartbeat que avise cuando una tarea deja de ejecutarse.