Por qué deberías dejar de usar Cron ya

Vistas: 0
0:00 / 0:00

Si te gusta trastear con servidores, exprimir al máximo tu sistema operativo favorito o simplemente automatizar hasta el más mínimo detalle de tu día a día tecnológico, seguro que te has topado con Cron. Este viejo amigo ha sido el rey indiscutible de la programación de tareas durante décadas. Sin embargo, los tiempos cambian, nuestras necesidades evolucionan y las herramientas modernas nos ofrecen soluciones mucho más robustas y elegantes. Hoy quiero convencerte de que le des una jubilación dorada a Cron y te pases de una vez por todas a los Systemd Timers. No te dejes asustar por las apariencias ni por la leyenda urbana de que Systemd es excesivamente complejo. Una vez que descubras el inmenso potencial de sus temporizadores, te prometo que te lo vas a pasar pipa cacharreando y no querrás volver a ver un asterisco de Cron en tu vida.

Los pecados ocultos de Cron

Para entender por qué los Systemd Timers son tan superiores, primero debemos analizar las debilidades de Cron. No se trata de criticar por criticar a un clásico que nos ha dado tanto, sino de ser realistas con los problemas cotidianos que nos encontramos al usarlo.

El drama de los fallos silenciosos

¿Cuántas veces has programado una copia de seguridad en Cron y ha fallado sin que te enteres? Cron ejecuta las tareas en absoluto silencio. Si tu script falla a mitad de proceso debido a un error de red, un fallo de permisos o la ausencia de una carpeta, Cron simplemente continuará con su vida como si nada hubiera pasado.

Para enterarte de lo ocurrido, te ves obligado a programar manualmente sistemas de registro dentro de tu script, redirigiendo la salida estándar y la salida de errores a archivos de texto con el clásico >> /var/log/backup.log 2>&1. Esto significa duplicar trabajo en cada script que decidas programar.

La nula gestión de dependencias

Cron no sabe nada sobre el estado actual de tu sistema. No sabe si estás conectado a internet, si un disco duro externo se ha montado correctamente o si la base de datos ya está lista para recibir consultas. Si le dices a Cron que se ejecute a las tres de la mañana, se ejecutará a las tres de la mañana, sin importarle si la red está caída o si el servidor está en pleno proceso de reinicio. Esto suele provocar fallos en cascada muy difíciles de depurar.

El vacío temporal de las máquinas apagadas

Imagina que programas una tarea diaria para que se ejecute a las seis de la mañana. Pero resulta que ese día enciendes tu ordenador a las siete. ¿Qué ocurre con la tarea? Exacto, se pierde en el limbo. Cron no tiene memoria; si la hora exacta de ejecución pasa y el equipo está apagado, la tarea se ignora por completo hasta el día siguiente. Esto es un dolor de cabeza constante en portátiles y ordenadores de escritorio.

La tortura del entorno gráfico

Si alguna vez has intentado que un script de Cron lance una simple notificación de escritorio usando notify-send o abra una ventana en tu pantalla, sabrás el calvario que representa. Cron se ejecuta en un entorno aislado, completamente desconectado de tu sesión de usuario y de tu servidor gráfico. Configurar las variables de entorno necesarias como DISPLAY o DBUS_SESSION_BUS_ADDRESS en Cron requiere un esfuerzo que sencillamente no compensa.

¿Qué son los Systemd Timers y por qué son mejores?

Systemd es el sistema de inicio y el gestor de servicios estándar en la inmensa mayoría de las distribuciones Linux modernas. Aunque su adopción inicial generó encendidos debates en la comunidad, hoy en día es innegable que nos facilita enormemente la vida a la hora de administrar nuestros sistemas.

Un Systemd Timer no es más que una unidad de Systemd dedicada a controlar el tiempo. En lugar de utilizar un único archivo con una sintaxis críptica para definir el cuándo y el qué, Systemd divide esta lógica en dos pequeñas piezas modulares que encajan a la perfección:

  • La unidad de servicio (.service): Esta pieza se encarga de definir el qué. Contiene las instrucciones precisas sobre qué comandos ejecutar, qué usuario los lanzará, qué dependencias requiere y qué debe ocurrir si el script falla.
  • La unidad de temporizador (.timer): Esta pieza se encarga de definir el cuándo. Actúa como un despertador inteligente que vigila el reloj del sistema o monitoriza eventos específicos y, al cumplirse las condiciones, despierta a la unidad de servicio asociada para que haga su trabajo.

Esta separación modular es una ventaja inmensa. Significa que puedes probar tu script de forma independiente ejecutando el servicio manualmente en cualquier momento, sin tener que esperar a que llegue la hora señalada por el temporizador.

Las ventajas definitivas de Systemd frente a Cron

Al adoptar los temporizadores de Systemd, tu sistema Linux adquiere automáticamente una serie de superpoderes que antes requerían complejas carambolas de programación:

  • Logs centralizados con Journald: Olvídate de añadir redirecciones de salida en tus scripts. Systemd recoge de forma nativa todo lo que tu script escriba en la salida estándar o de error y lo almacena de forma estructurada. Puedes consultarlo al instante, filtrar por fechas o ver las últimas líneas en tiempo real.
  • Persistencia inteligente: Gracias a la directiva Persistent=true, si el temporizador debía dispararse cuando el ordenador estaba apagado, Systemd lo detecta en el momento de arrancar y ejecuta la tarea de inmediato.
  • Lógica de reintentos: Puedes configurar el servicio para que, si el script falla por un error puntual, intente volver a ejecutarse automáticamente tras un intervalo definido de segundos.
  • Aleatorización horaria integrada: Systemd te permite añadir un margen aleatorio al inicio de la tarea mediante RandomizedDelaySec. Si administras decenas de servidores y necesitas que actualicen sus paquetes a diario, esta opción evitará que todos colapsen tu servidor de descargas al unísono.
  • Integración absoluta de dependencias: Puedes indicarle a tu servicio que solo se ejecute después de que el servicio de red esté totalmente operativo, o después de que se monte un disco específico.

La anatomía de un Systemd Timer

Para dominar esta potente herramienta, necesitamos entender cómo se estructuran sus archivos de configuración. Estos archivos utilizan el formato estándar de las unidades de Systemd (estilo INI), que es sumamente legible.

El archivo de Servicio (.service)

Este archivo define la acción. Por lo general, si se trata de tareas programadas que se ejecutan y terminan de inmediato (como un script de copia de seguridad), utilizaremos un servicio de tipo oneshot.

A continuación, vemos un ejemplo básico de su estructura:

[Unit]
Description=Mi script de copia de seguridad diaria
After=network-online.target
Wants=network-online.target

[Service]
Type=oneshot
ExecStart=/usr/local/bin/mi_backup.sh
User=lorenzo

Desglosemos las directivas clave:

  • Description: Una frase sencilla que describe qué hace el servicio. Nos vendrá de perlas cuando usemos comandos de monitorización.
  • After / Wants: Aquí definimos que el servicio depende de que la red esté completamente activa antes de empezar a ejecutarse.
  • Type=oneshot: Indica a Systemd que este servicio realiza una tarea concreta y finaliza. No se queda corriendo en segundo plano como un servidor web o una base de datos.
  • ExecStart: La ruta absoluta al ejecutable o script que queremos arrancar. Recuerda que Systemd no utiliza el entorno típico de tu terminal de usuario, por lo que las rutas absolutas son obligatorias tanto para el script como para los comandos dentro de él.
  • User: El usuario del sistema bajo cuyo contexto se ejecutará el script.

El archivo de Timer (.timer)

Este archivo define el momento exacto en el que el despertador enviará la señal al servicio. Por convención, el temporizador debe llamarse exactamente igual que el archivo de servicio, cambiando únicamente la extensión. Es decir, si tu servicio es mi_backup.service, tu temporizador debe llamarse mi_backup.timer.

Aquí tienes su estructura fundamental:

[Unit]
Description=Despertador para la copia de seguridad diaria

[Timer]
OnCalendar=*-*-* 03:00:00
Persistent=true
Unit=mi_backup.service

[Install]
WantedBy=timers.target

Desglosemos estas directivas:

  • OnCalendar: Define la regla temporal utilizando un formato sumamente potente y flexible. En este caso, *-* 03:00:00* significa que se ejecutará todos los días del año a las tres de la madrugada.
  • Persistent=true: El salvavidas de las copias de seguridad. Si el ordenador estaba apagado a las tres de la madrugada, ejecutará la tarea en cuanto el sistema arranque de nuevo.
  • Unit: Especifica explícitamente qué servicio debe despertar este temporizador. Si el archivo del temporizador se llama exactamente igual que el servicio, esta línea se puede omitir, pero siempre es buena idea incluirla para evitar confusiones.
  • [Install] / WantedBy=timers.target: Le indica a Systemd que este temporizador debe activarse junto con el resto de temporizadores del sistema durante el proceso de arranque normal del equipo.

Entendiendo el formato de tiempo en Systemd

Uno de los mayores atractivos de los Systemd Timers es la tremenda flexibilidad de sus expresiones temporales. Al contrario que Cron, cuyas columnas de asteriscos pueden inducir a errores, Systemd nos permite definir fechas y horas de forma intuitiva.

El formato de calendario (OnCalendar)

El formato general de una directiva OnCalendar sigue el siguiente patrón de izquierda a derecha:

DíaDeLaSemana Año-Mes-Día Hora:Minuto:Segundo

Si queremos ignorar alguno de los campos para que la tarea se ejecute de forma repetitiva, simplemente utilizamos un asterisco (*).

Veamos algunos ejemplos prácticos para entenderlo fácilmente:

  • Todos los días a las 15:30: OnCalendar=*-*-* 15:30:00
  • Todos los lunes a las 08:00: OnCalendar=Mon *-*-* 08:00:00
  • El primer día de cada mes a medianoche: OnCalendar=*-*-01 00:00:00
  • Los días de diario (lunes a viernes) a las 22:00: OnCalendar=Mon..Fri *-*-* 22:00:00
  • Cada hora en punto: OnCalendar=*-*-* *:00:00

Además, Systemd nos ofrece una serie de atajos textuales comodísimos para evitarnos tener que recordar expresiones complejas:

  • minutely: Cada minuto.
  • hourly: Cada hora en punto.
  • daily: Todos los días a medianoche.
  • weekly: Todos los domingos a medianoche.
  • monthly: El primer día de cada mes a medianoche.

El truco definitivo: systemd-analyze calendar

¿No estás seguro de si tu patrón horario funciona exactamente como crees? Systemd incluye una herramienta fantástica que te ahorrará tener que esperar horas para comprobarlo. Se trata del comando systemd-analyze calendar.

Si ejecutas este comando pasándole tu expresión horaria entre comillas simples, el sistema la analizará, la traducirá al formato normalizado y te mostrará una lista detallada con las próximas ejecuciones exactas en el calendario:

systemd-analyze calendar 'Mon *-*-* 03:00:00'

Este comando te devolverá una salida limpia indicándote exactamente qué día de la semana, qué mes, a qué hora exacta y cuántos días faltan para las próximas ejecuciones. Es una de esas herramientas absolutamente imprescindibles para cualquiera que disfrute automatizando cosas en Linux.

Disparadores relativos y dinámicos

A veces no necesitas que una tarea se ejecute en una fecha u hora concreta del calendario. En ocasiones, lo que quieres es que se ejecute en relación a otros eventos del sistema. Para estos casos, Systemd pone a tu disposición disparadores relativos sumamente útiles:

  • OnBootSec: Ejecuta la tarea un tiempo determinado después de que el sistema se haya iniciado. Por ejemplo, OnBootSec=15min arrancará tu tarea quince minutos después de pulsar el botón de encendido de tu ordenador.
  • OnUnitActiveSec: Ejecuta la tarea en intervalos regulares basándose en cuándo se activó por última vez el servicio. Si configuras OnUnitActiveSec=1h, la tarea se ejecutará de forma continua cada hora una vez que se haya iniciado por primera vez.

Automatización en el espacio de usuario (Sin usar Root ni Sudo)

Este es, sin lugar a dudas, uno de los secretos mejor guardados de Systemd y uno de mis apartados favoritos a la hora de cacharrear en mi propio escritorio. Para automatizar tareas personales, no tienes ninguna necesidad de utilizar privilegios de administrador ni de trastear con el sistema global.

Puedes configurar y ejecutar servicios y temporizadores de Systemd directamente en tu contexto de usuario. Esto tiene ventajas colosales:

  • Los archivos se guardan en tu propia carpeta de usuario, en concreto en la ruta ~/.config/systemd/user/.
  • Tu entorno de configuración personal (tus dotfiles) se mantiene limpio y fácil de replicar en otros ordenadores. Solo necesitas copiar tu carpeta de configuración para llevarte todas tus automatizaciones personales.
  • Las tareas se ejecutan bajo tu usuario, por lo que tienen acceso completo y directo a tu pantalla, tus notificaciones de escritorio, tu servidor de audio y tus directorios personales sin necesidad de lidiar con problemas de permisos.

El secreto del comando Linger

Si estás configurando temporizadores de usuario en un servidor remoto o un VPS, te encontrarás con un pequeño inconveniente por defecto: cuando cierras tu sesión SSH, el gestor de Systemd del usuario se detiene y tus temporizadores dejan de funcionar.

Para solucionar esto de forma definitiva, existe un comando mágico que solo requiere privilegios de administrador una única vez. Se trata de habilitar el linger para tu usuario:

sudo loginctl enable-linger lorenzo

Al activar esta opción, el sistema operativo mantendrá en funcionamiento el gestor de Systemd para tu usuario de forma permanente desde el arranque del equipo hasta que se apague, independientemente de si tienes una sesión interactiva abierta o no. Es el truco clave para montar servidores personales estables y ligeros.

Guía de comandos esenciales para gestionar Timers

La gestión de los Systemd Timers se realiza mediante la conocida herramienta systemctl. Si estás configurando tareas en el sistema global, utilizarás los comandos de forma habitual con sudo. Pero si estás usando temporizadores de usuario en tu home, simplemente añade el parámetro –user sin emplear la palabra sudo.

Listar los temporizadores activos

Para ver un listado completo de todos los temporizadores que están corriendo en tu sistema, la hora de su última ejecución, cuándo se volverán a activar y cuánto tiempo falta para ello, utiliza el siguiente comando:

systemctl list-timers

Si estás administrando tus tareas personales en tu espacio de usuario, el comando equivalente será:

systemctl --user list-timers

Habilitar y arrancar un temporizador

Para poner en marcha un nuevo temporizador que acabas de escribir, debes realizar dos pasos que se pueden simplificar en un único comando gracias al parámetro –now:

sudo systemctl enable --now mi_tarea.timer

Esto habilitará el temporizador para que arranque automáticamente en los próximos reinicios y lo activará de forma inmediata en la sesión actual. Recuerda aplicar el comando siempre sobre el archivo .timer y no sobre el .service. El temporizador ya se encargará de despertar al servicio cuando corresponda.

Comprobar el estado y ver los logs

Si quieres comprobar que tu temporizador está cargado correctamente y ver un pequeño resumen de sus últimas actividades, ejecuta:

systemctl status mi_tarea.timer

Y para examinar en profundidad el registro de salida (los logs) de tu servicio asociado, utiliza el potente visor de logs de Systemd pasándole el nombre de la unidad de servicio:

journalctl -u mi_tarea.service

Si quieres monitorizar la ejecución en tiempo real, puedes añadir el parámetro -f:

journalctl -f -u mi_tarea.service

Ejemplos Prácticos Completos (Listos para copiar y pegar)

La mejor forma de aprender es metiéndose de lleno en el barro y experimentando. A continuación, te presento una colección de recetas prácticas con casos de uso reales de mi día a día, listas para que las adaptes a tus necesidades.

Ejemplo 1: Copia de seguridad nocturna con persistencia

Este es el ejemplo clásico de salvaguarda de datos. Queremos realizar una copia de seguridad todos los días a las tres de la madrugada, asegurándonos de que si el ordenador estaba apagado, la copia se realice nada más encenderlo.

Primero creamos el archivo del servicio:

# Ruta: ~/.config/systemd/user/backup-personal.service
[Unit]
Description=Copia de seguridad de mis documentos importantes

[Service]
Type=oneshot
ExecStart=/home/lorenzo/bin/hacer-backup.sh

A continuación, creamos el archivo del temporizador asociado:

# Ruta: ~/.config/systemd/user/backup-personal.timer
[Unit]
Description=Temporizador diario para la copia de seguridad personal

[Timer]
OnCalendar=*-*-* 03:00:00
Persistent=true

[Install]
WantedBy=timers.target

Finalmente, para que el sistema reconozca los nuevos archivos de configuración y active la automatización, ejecutamos estos comandos en la terminal de nuestro usuario:

systemctl --user daemon-reload
systemctl --user enable --now backup-personal.timer

Ejemplo 2: Limpieza semanal automática de logs del Journal y APT

En los servidores de desarrollo solemos acumular una enorme cantidad de registros de logs innecesarios o paquetes antiguos en la caché de APT. Podemos crear una tarea semanal de mantenimiento del sistema global.

Creamos el archivo de servicio:

# Ruta: /etc/systemd/system/mantenimiento-sistema.service
[Unit]
Description=Limpieza semanal de logs de Journald y cache de APT

[Service]
Type=oneshot
ExecStart=/usr/bin/journalctl --vacuum-time=7d
ExecStart=/usr/bin/apt-get clean

Como habrás observado en el archivo anterior, una de las grandes ventajas de usar servicios de tipo oneshot es que podemos definir múltiples directivas ExecStart. Systemd las ejecutará secuencialmente, una tras otra, en el orden estricto en el que las hayas escrito.

Creamos el temporizador semanal:

# Ruta: /etc/systemd/system/mantenimiento-sistema.timer
[Unit]
Description=Temporizador semanal para mantenimiento de logs y APT

[Timer]
OnCalendar=weekly
Persistent=true

[Install]
WantedBy=timers.target

Para activarlo en el sistema global, empleamos sudo:

sudo systemctl daemon-reload
sudo systemctl enable --now mantenimiento-sistema.timer

Ejemplo 3: Actualización diaria de paquetes con retraso aleatorio

Si tienes una red con múltiples máquinas virtuales o servidores locales y quieres automatizar la actualización de los repositorios sin colapsar el ancho de banda ni el rendimiento al mismo tiempo, esta es la solución idónea.

Creamos el archivo de servicio:

# Ruta: /etc/systemd/system/actualizacion-paquetes.service
[Unit]
Description=Actualizacion de repositorios de paquetes
After=network-online.target

[Service]
Type=oneshot
ExecStart=/usr/bin/apt-get update

Creamos el temporizador con retardo aleatorio:

# Ruta: /etc/systemd/system/actualizacion-paquetes.timer
[Unit]
Description=Temporizador diario con retardo aleatorio para actualizacion

[Timer]
OnCalendar=*-*-* 06:00:00
RandomizedDelaySec=1800
Persistent=true

[Install]
WantedBy=timers.target

En este caso, la directiva RandomizedDelaySec=1800 (que equivale a 30 minutos) le indica al temporizador que, al llegar las seis de la mañana, se esperará un tiempo aleatorio de entre cero segundos y media hora antes de lanzar la actualización. Esto distribuye estupendamente la carga en entornos de red con muchos equipos.

Ejemplo 4: Recordatorio de salud con notificación de escritorio nativa

Pasar demasiadas horas delante de la pantalla no es bueno para la salud. Con esta sencilla receta, configuraremos una tarea de usuario para que nos muestre una notificación interactiva en nuestro escritorio cada dos horas durante la jornada laboral.

Creamos el archivo de servicio de usuario:

# Ruta: ~/.config/systemd/user/recordatorio-salud.service
[Unit]
Description=Lanza una notificacion de recordatorio en pantalla

[Service]
Type=oneshot
ExecStart=/usr/bin/notify-send -i dialog-information "¡Hora de estirar!" "Levántate de la silla, estira las piernas y bebe un vaso de agua."

Creamos el temporizador asociado:

# Ruta: ~/.config/systemd/user/recordatorio-salud.timer
[Unit]
Description=Temporizador para recordatorios de salud en horas de oficina

[Timer]
OnCalendar=Mon..Fri *-*-* 09,11,13,15,17:00:00

[Install]
WantedBy=timers.target

Fíjate en lo increíblemente limpio que resulta. No necesitamos lidiar con ninguna variable de entorno gráfico ni configuraciones oscuras. Al ejecutarse en el espacio del usuario, la notificación flotará de forma nativa en tu escritorio en las horas especificadas de lunes a viernes.

Ejemplo 5: Sincronización continua de carpetas locales con rsync

Este ejemplo viene de perlas si utilizas un servidor local para generar contenidos o almacenar notas y quieres traer de forma automatizada esos archivos a tu ordenador personal cada hora de forma sutil.

Creamos el archivo de servicio:

# Ruta: ~/.config/systemd/user/sincronizar-notas.service
[Unit]
Description=Sincroniza notas personales con el servidor local
After=network.target

[Service]
Type=oneshot
ExecStart=/usr/bin/rsync -avz --delete lorenzo@servidor-local:/home/lorenzo/notas/ /home/lorenzo/Documentos/notas/

Creamos el temporizador dinámico:

# Ruta: ~/.config/systemd/user/sincronizar-notas.timer
[Unit]
Description=Sincroniza notas cada hora con margen inicial

[Timer]
OnBootSec=1min
OnUnitActiveSec=1h

[Install]
WantedBy=timers.target

Esta configuración es una maravilla de la automatización relativa. En lugar de fijarse a una hora de reloj, el script se ejecutará un minuto después de que enciendas tu equipo (OnBootSec=1min) para dar tiempo a que se conecte el wifi, y a partir de ese instante se repetirá puntualmente cada hora (OnUnitActiveSec=1h).

Ejemplo 6: Renovación automática de certificados SSL (Let’s Encrypt)

Si tienes un servidor web personal expuesto a internet, sabrás que los certificados de Let’s Encrypt caducan cada noventa días. En lugar de renovarlos manualmente, podemos crear una automatización del sistema para que compruebe su estado los días 1 y 15 de cada mes a las cuatro de la madrugada.

Creamos el archivo de servicio de sistema:

# Ruta: /etc/systemd/system/renovar-certificados.service
[Unit]
Description=Renovacion de certificados SSL con Certbot
After=network-online.target

[Service]
Type=oneshot
ExecStart=/usr/bin/certbot renew --post-hook "systemctl reload nginx"

Creamos el temporizador quincenal:

# Ruta: /etc/systemd/system/renovar-certificados.timer
[Unit]
Description=Temporizador quincenal para comprobar y renovar certificados

[Timer]
OnCalendar=*-*-01,15 04:00:00
Persistent=true

[Install]
WantedBy=timers.target

De esta manera, te aseguras de que tus certificados nunca caduquen de manera totalmente desatendida. Si el proceso de renovación de Certbot detecta que el certificado está próximo a expirar, lo renovará y recargará tu servidor Nginx automáticamente de forma transparente.

Ejemplo 7: Cambiador dinámico de fondo de pantalla con la imagen de Bing

¿Quieres tener un escritorio fresco y dinámico todos los días? Podemos crear un temporizador que descargue la preciosa imagen de portada de Bing diaria y la establezca como fondo de pantalla de tu entorno gráfico en tu sesión personal de usuario.

Creamos el servicio de usuario:

# Ruta: ~/.config/systemd/user/bing-wallpaper.service
[Unit]
Description=Descarga y establece el fondo de pantalla diario de Bing

[Service]
Type=oneshot
ExecStart=/home/lorenzo/bin/descargar-bing-wallpaper.sh

Creamos el temporizador diario:

# Ruta: ~/.config/systemd/user/bing-wallpaper.timer
[Unit]
Description=Temporizador diario para actualizar el fondo de pantalla

[Timer]
OnCalendar=*-*-* 08:30:00
Persistent=true

[Install]
WantedBy=timers.target

Tu script descargar-bing-wallpaper.sh solo tendrá que conectarse al API público de Bing, descargar la imagen en una carpeta temporal y llamar al comando de tu entorno de escritorio para cambiar la imagen (por ejemplo, con gsettings para GNOME). Gracias a la persistencia, si abres tu portátil por primera vez a las diez de la mañana, tu fondo se actualizará al instante de arrancar.

Ejemplo 8: Servicio de alertas global en caso de fallos (OnFailure)

Uno de los mayores lamentos de los usuarios de Cron es el no enterarse cuando las cosas van mal. Systemd nos ofrece una directiva fantástica llamada OnFailure que nos permite disparar un servicio especial si una de nuestras tareas críticas falla.

Primero, creamos el servicio genérico de notificación de fallos:

# Ruta: ~/.config/systemd/user/notificar-error@.service
[Unit]
Description=Envia un aviso visual si una tarea de Systemd falla

[Service]
Type=oneshot
ExecStart=/usr/bin/notify-send -u critical "Fallo en el sistema" "La tarea %I ha fallado. Revisa los logs con journalctl."

Presta atención al símbolo %I en el comando ExecStart. Esto es una variable especial de Systemd que se sustituirá automáticamente por el nombre del servicio que haya provocado el fallo.

Ahora, en cualquiera de tus servicios críticos (por ejemplo, tu copia de seguridad), simplemente añade la directiva OnFailure en la sección [Unit]:

# Añadir esto a tu servicio critico
[Unit]
Description=Mi servicio de copia de seguridad critica
OnFailure=notificar-error@%n.service

A partir de este momento, si tu script de copia de seguridad devuelve un código de error de salida diferente de cero, Systemd se dará cuenta de inmediato, despertará al servicio de notificación y verás flotar un aviso urgente en tu pantalla con el nombre exacto del servicio que ha sufrido el percance. Esto es automatizar de forma verdaderamente profesional.

Errores comunes al configurar Systemd Timers (Y cómo resolverlos)

A pesar de que el proceso es sumamente placentero, al principio es normal tropezar con algunas piedras en el camino. Estos son los errores más comunes que suelo encontrarme y cómo puedes solucionarlos sin perder los estribos:

El error de las rutas relativas

Es el fallo más habitual de todos. En tus scripts interactivos de consola estás acostumbrado a ejecutar comandos llamándolos por su nombre básico, confiando en la variable de entorno PATH. Pero Systemd arranca los procesos en un entorno mínimo y limpio.

Si en tu archivo de servicio o dentro de tu script escribes rsync o notify-send a secas, lo más probable es que falle porque Systemd no sabe dónde encontrarlos. Acuérdate de usar siempre la ruta absoluta completa para todos tus ejecutables, como /usr/bin/rsync o /usr/bin/notify-send. Puedes localizar la ruta exacta de cualquier herramienta en tu consola utilizando el comando which rsync.

Olvidarse de recargar el demonio de Systemd

Cuando creas un nuevo archivo de unidad o modificas un archivo .timer o .service existente, Systemd no se entera del cambio de forma automática. Sigue manteniendo en memoria la configuración antigua.

Para forzar al sistema a que lea tus nuevos archivos del disco, debes ejecutar siempre el comando de recarga:

# Para servicios de sistema
sudo systemctl daemon-reload

# Para servicios de usuario
systemctl --user daemon-reload

Si haces una modificación y notas que Systemd sigue actuando con la lógica anterior, el culpable es casi con toda seguridad el olvido de este comando.

Confundir enable con start

Es muy habitual cometer el desliz de escribir systemctl start mi_tarea.timer pensando que con eso ya queda programada para el futuro.

  • start: Arranca el temporizador de forma inmediata y puntual para la sesión actual del sistema. Si apagas el equipo, la programación se perderá en el siguiente arranque.
  • enable: Registra el temporizador en la secuencia de inicio del sistema operativo para que se active de forma automática cada vez que enciendas el ordenador.

Para evitar confusiones y asegurarte de que tu temporizador empiece a funcionar en el momento y sobreviva a futuros reinicios, hazte el hábito de usar siempre el parámetro conjunto --now:

systemctl --user enable --now mi_tarea.timer

El misterio de los permisos del script

Si tu servicio de Systemd intenta lanzar un script escrito por ti y en los logs de journalctl observas un mensaje de error estilo Permission denied, el problema no es de Systemd, sino del archivo de tu script.

No olvides que para que el sistema pueda ejecutar tu archivo .sh, este debe poseer los permisos de ejecución adecuados. Puedes otorgárselos de forma sencilla con el comando de terminal:

chmod +x /home/lorenzo/bin/mi_script.sh

Conclusión

La transición de Cron a los Systemd Timers puede parecer que requiere un poquito más de esfuerzo inicial porque nos vemos obligados a redactar dos pequeños archivos de texto en lugar de concentrarlo todo en una única línea confusa de un crontab. Pero te garantizo que los beneficios superan con creces cualquier inversión de tiempo inicial.

La tranquilidad de contar con logs centralizados sin esfuerzo, la maravillosa persistencia que asegura que tus tareas de escritorio se ejecuten aunque enciendas el ordenador más tarde, la gestión inteligente de dependencias de red y la inmensa seguridad y comodidad de ejecutar tareas personales en el espacio de usuario, hacen que Systemd sea el claro vencedor en el campo de la automatización moderna en Linux.

Así que no lo pienses más. Dedica una tarde a cacharrear con estas recetas que te he propuesto, ábrele la puerta a los temporizadores en tu propio sistema operativo y dale a tu viejo Cron el descanso que tan merecidamente se ha ganado.


Enlaces recomendados

Deja una respuesta