Búsqueda de sitios web

Cómo (y por qué) reemplazar trabajos cron con temporizadores systemd


Es la hora.

Hannah Stryker/Cómo hacer geek

Uno de los cambios que introdujo systemd fue una nueva forma de programar trabajos, con más delicadeza que cron. Algunas distribuciones de Linux ya no incluyen cron. Es hora de comprobar los temporizadores de systemd.

Por qué los temporizadores systemd están reemplazando a cron

Los orígenes de cron se remontan a 1975, en la Versión 7 de Unix. Su confiabilidad pronto la convirtió en una herramienta favorita para programar tareas para que se ejecuten en fechas y horas específicas. Es cierto que su sintaxis es bastante peculiar. Si no lo usa con frecuencia, probablemente necesitará buscar los detalles más detallados cada vez que desee programar un trabajo.

En los cronogramas cron, los días y los meses están numerados comenzando por uno. Los días de la semana, sin embargo, están numerados del cero al seis, de domingo a sábado. Y en algunos sistemas, siete también significa domingo. Pero, por muy peculiar que parezca, funciona.

El administrador de servicios systemd aportó mucho más que un simple reemplazo del administrador de arranque init. Parte de lo que entregó fue un reemplazo moderno de cron, en forma de temporizadores systemd. Estos ofrecen más flexibilidad que cron y sin la necesidad de otra utilidad externa. Están integrados en todas las distribuciones de systemd.

Eso significa que los temporizadores se comportan de la misma manera en todas las instalaciones de systemd. Hay muchas versiones de cron y sustitutos similares a cron. Si necesita estandarización en varias computadoras, systemd le hace la vida más fácil. Los mismos temporizadores funcionarán de la misma manera en todos ellos. De hecho, algunas distribuciones basadas en systemd ya no incluyen cron como parte de su oferta estándar.

No sorprende que las distribuciones derivadas de Red Hat, incluido Fedora, no incluyan cron, porque systemd es una iniciativa de Red Hat. Arch y sus derivados no incluyen cron, pero eso probablemente tenga más que ver con que brindan una distribución tan mínima que puede completar con aplicaciones adecuadas. Otras distribuciones, como Solus, tampoco ven la necesidad de incluir cron. Por supuesto, puedes instalar cron en cualquier distribución que desees, pero no hay ningún argumento convincente para hacerlo.

Relacionado: Por qué systemd de Linux sigue siendo divisivo después de todos estos años

Cómo funcionan los temporizadores systemd

Con los temporizadores systemd, necesitas crear dos archivos. Uno es un archivo servicio. Cuando el servicio se ejecuta, inicia el proceso por usted. Por lo tanto, el archivo de servicio necesita conocer su proceso de destino.

El segundo archivo que necesita crear es un archivo temporizador. Esto determina cuándo se lanza el servicio. Por lo tanto, el archivo del temporizador necesita conocer su archivo de servicio.

Los temporizadores pueden ser en tiempo real o monótonos. Los eventos del calendario activan temporizadores en tiempo real. Los temporizadores monótonos se activan con cierta duración después de un evento del sistema, como el arranque. Las entradas de registro se agregan al diario del sistema para los eventos del temporizador, lo que puede ayudar con la depuración.

Puede enumerar los temporizadores en su computadora usando la opción de estado del comando systemctl. Varios temporizadores del sistema se crean automáticamente, por lo que incluso si no ha creado ningún temporizador, este comando generará resultados.

systemctl status "*timer"

Cada descripción contiene la siguiente información:

  • El nombre y la descripción del temporizador, si se proporcionó una.
  • Cargado: Muestra el estado de carga. Normalmente nuestro temporizador se lee y se carga en la memoria. Se muestra la ruta del directorio al archivo del temporizador. Es de esperar que nuestro temporizador esté "habilitado", pero podría estar "deshabilitado" temporalmente si hemos elegido apagarlo. El valor preestablecido del proveedor indica si, cuando se creó el temporizador por primera vez, estaba configurado como "habilitado" o "deshabilitado".
  • Activo: Muestra el estado activo, incluida la fecha y hora en que se activó el temporizador. Por lo general, esperaría ver un temporizador listado como "activo" y "esperando" la fecha y hora de su próximo lanzamiento.
  • Hasta: De manera confusa, esta línea no se aplica a los temporizadores. Podemos ignorarlo.
  • Disparador: Muestra el nombre del proceso que inicia el temporizador.
  • Disparadores: muestra cuándo se activará el temporizador y cuándo se iniciará el proceso.
  • Documentos: algunos temporizadores tienen documentación asociada. Esta línea es opcional y no siempre está presente.

Debido a que los temporizadores son en realidad servicios controlados por tiempo, podemos usar el comando systemctl para controlarlos.

Creando un temporizador systemd simple

La palabra escrita es un medio estático, lo que dificulta ilustrar un proceso que se desencadena en un momento específico. Lo que haremos es crear un script que nuestro nuevo temporizador iniciará y le pediremos que escriba una marca de tiempo en un archivo de registro. Eso nos dirá que nuestro servicio está funcionando y cuándo se activó por última vez.

Usaremos el comando de fecha para generar la marca de tiempo y la redirigiremos a un archivo llamado "timer.log" en nuestro directorio de inicio.

Crearemos el script en el directorio “/usr/local/bin/”. Estamos usando el editor "gedit", pero puedes usar el editor que prefieras.

sudo gedit /usr/local/bin/geek-timer.sh 

Copie estas líneas en su editor, guarde el archivo como "geek-timer.sh" y cierre su editor.

#!/bin/bash
echo "Timer fired: $(date)" >> /home/dave/timer.log

Necesitaremos hacer que nuestro script sea ejecutable.

sudo chmod +x /usr/local/bin/geek-timer.sh

Comprobemos que nuestro script hace lo que debe hacer.

geek-timer.sh
cat timer.log

Eso verifica que nuestro script se ejecute como se esperaba y coloca una marca de tiempo en el archivo "timer.log".

Ahora crearemos un archivo de servicio para definir el servicio que queremos que se inicie cuando se active el temporizador.

sudo gedit /etc/systemd/system/geek-timer.service 

Copie estas líneas en su editor, guarde el archivo como “/etc/systemd/system/geek-timer.service” y cierre su editor.

[Unit]
Description="How-To Geek systemd timer"
Requires=geek-timer.timer
[Service]
Type=simple
ExecStart=/usr/local/bin/geek-timer.sh
User=dave

La sección “[Unidad]” contiene dos líneas. La línea "Descripción=" es una línea simple que dice para qué sirve su servicio. La línea "Requires=" indica que este servicio se basa en el archivo de temporizador "geek-timer.timer". Crearemos este archivo a continuación.

Hay un poco más en la sección "[Servicio]". El “Type=" es "simple", lo que significa que se trata de un servicio básico. Otras opciones incluyen "oneshot", lo que significaría que el servicio se ejecutó solo una vez.

La línea “ExecStart=" indica qué proceso debe iniciar el servicio. Esto apunta a nuestro script que creamos anteriormente.

La línea “Usuario =” define qué usuario debe ejecutar el comando. Sin esto, el proceso sería iniciado por root.

Ahora crearemos el archivo del temporizador. Esto define cuándo se lanza el servicio. Es una buena práctica utilizar el mismo nombre base para los archivos del servidor y del temporizador, con diferentes extensiones.

sudo gedit /etc/systemd/system/geek-timer.timer

Copie estas líneas en su editor, guarde el archivo como “/etc/systemd/system/geek-timer.timer” y cierre su editor.

[Unit]
Description="Timer for the geek-timer.service"
[Timer]
Unit=geek-timer.service
OnBootSec=5min
OnUnitActiveSec=1min
[Install]
WantedBy=timers.target

La sección "[Unidad]" contiene una línea de texto "Descripción=". La sección “[Temporizador]” contiene tres configuraciones. La línea "Unit=" indica qué servicio debe iniciarse cuando se activa este temporizador. La línea "OnBootSec=" le indica al sistema que inicie el servicio cinco minutos después de que se inicia la computadora. La línea "OnUnitActiveSec=" le indica al temporizador que inicie el servicio un minuto después de su última activación.

En otras palabras, cinco minutos después de que se inicia la computadora, se iniciará el servicio. Luego el servicio se repetirá con un intervalo de un minuto.

En la sección "[Instalar]", incluimos una línea "WantedBy=" que especifica "timers.target". "timers.target" es una unidad de destino especial que configura todas las unidades de temporizador que están activas después del arranque y es adecuada para todos los temporizadores básicos de systemd.

Podemos usar el comando systemctl status para ver nuestro nuevo temporizador.

systemctl status geek-timer.service

No se informan errores, lo cual es bueno. Está inactivo porque no hemos iniciado el servicio. Incluso si reiniciamos ahora, nuestro servicio y temporizador no estarán habilitados. Comencemos y habilitemos nuestro temporizador.

sudo systemctl enable geek-timer.timer
sudo systemctl start geek-timer.timer

Reinicié la computadora de prueba para ver si se respetaba el período de gracia de cinco minutos después del inicio y verifiqué su estado una vez más.

systemctl status geek-timer.service

Esto muestra que la PC se inició a las 12:18 y nuestro temporizador se activará a las 12:23. Nuestra opción solicitada cinco minutos después del arranque se está manejando correctamente. Esperé a que transcurrieran los cinco minutos y luego rápidamente ejecuté el mismo comando.

systemctl status geek-timer.service

Podemos ver que el tiempo de activación ha avanzado un minuto de 12:23 a 12:24. Esto significa que ahora estamos en la "fase de repetición de cada minuto" de nuestro cronómetro.

Al revisar nuestro archivo de registro unos minutos más tarde, se muestra el tiempo de activación inicial de 12:23, luego los lanzamientos posteriores ocurren con aproximadamente un minuto de diferencia.

cat timer.log

Relacionado: Cómo enumerar servicios de Linux con systemctl

Ajustando los tiempos

Los tiempos de activación de eventos repetidos son ligeramente confusos. Por eso dije que los eventos en el archivo de registro están separados por aproximadamente un minuto. Hay un pequeño elemento aleatorio agregado al tiempo de activación para garantizar que los temporizadores que están programados para activarse exactamente al mismo tiempo se activen de forma escalonada. Por lo general, para tareas como iniciar una copia de seguridad u otras actividades de limpieza del sistema, eso es lo suficientemente preciso.

Si necesita tener una resolución más ajustada, puede utilizar la sincronización de microsegundos. Agregar esta línea a la sección “[Temporizador]” de su archivo de temporizador configura el sistema para que utilice una resolución de un microsegundo.

AccuracySec=1us

Estas son las configuraciones de precisión que puede utilizar y cómo puede consultarlas.

  • Microsegundos: nosotros, µs mseg, ms
  • Segundos: segundos, segundo, seg, s
  • Minutos: minutos, minuto, min, m
  • Horas: horas, hora, hr, h
  • Días: días, día, d
  • Semanas: semanas, semana, w
  • Meses: meses, mes, M
  • Años: años, año, y

Para que el temporizador se active en una hora y fecha determinadas se logra utilizando la configuración "OnCalendar". Esto va en la sección “[Temporizador]” del archivo del temporizador. El formato general es:

OnCalendar=DayOfTheWeek YYYY-MM-DD HH:MM:SS

El día de la semana es opcional. Cualquiera de los demás valores debe reemplazarse por un asterisco '*' para significar "cada", como cada minuto o cada hora. Puede utilizar nombres o números para los días y meses, y listas separadas por comas para representar selecciones de valores. Los rangos de valores se indican mediante el uso de dos puntos “..” para separar el inicio y los valores de un rango.

Esto configuraría un temporizador para que se active a la 01:15 del primer viernes de cada mes.

OnCalendar=Fri *-*-1..7 01:15:00

Este ejecutaría un proceso a las 19:00 horas todos los días.

OnCalendar=*-*-* 19:00:00

Un temporizador puede tener más de un tiempo de activación configurado. Esto ejecutaría un proceso en un horario diferente los días hábiles que el fin de semana.

OnCalendar=Mon..Fri 23:00:00
OnCalendar=Sat,Sun 19:00:00

La página de manual de hora de systemd contiene una descripción completa de los formatos de hora y muchos consejos y trucos útiles.

Gran flexibilidad y facilidad de uso

Gran parte de la flexibilidad de los temporizadores systemd reside en la forma en que puede atender eventos extraños del calendario. Por ejemplo, para configurar un temporizador para que se active a las 15:00 todos los días excepto los viernes, puede utilizar este formato:

Mon..Thu,Sat,Sun *-*-* 15:00:00

Al combinar listas y rangos separados por comas, le resultará fácil crear activadores en tiempo real para todo tipo de requisitos complicados.

Una vez que tenga la idea de crear un servicio para iniciar su proceso y un archivo de temporizador para controlar el inicio del servicio, habrá recorrido el 90 por ciento del camino para comprender los temporizadores de systemd. El último 10 por ciento está abrazando el elegante poder de los eventos del calendario.

Relacionado: Cómo ejecutar un programa de Linux al iniciar con systemd

Artículos relacionados: