Programación de tareas con temporizadores systemd en Linux

S ystemd es un administrador de sistemas y servicios compuesto por una colección de herramientas para realizar diferentes tareas del sistema. Una de estas herramientas son los temporizadores systemd, cuyo propósito principal es programar y ejecutar tareas durante el inicio o repetidamente después de un inicio del sistema.

Los temporizadores de Systemd son una alternativa al programador cron o anacron. Para los administradores de sistemas, la programación de tareas juega un papel crucial en la automatización de las tareas aburridas o difíciles de su sistema. Este artículo es una guía introductoria a los temporizadores del sistema, su estructura y configuraciones con ejemplos del mundo real.

Por que systemd timer

Al igual que cron, los temporizadores de systemd también pueden programar tareas para que se ejecuten con una granularidad que va desde minutos hasta meses o más. Sin embargo, los temporizadores también pueden hacer ciertas cosas que cron no puede hacer. Por ejemplo, un temporizador puede activar una secuencia de comandos para que se ejecute en un período específico después de un evento como el inicio, el inicio, la finalización de una tarea anterior o la finalización de una unidad de servicio. Otros beneficios de los temporizadores sobre cron incluyen:

  • systemd ya está disponible y no necesita instalar ningún paquete, a diferencia de cron.
  • Facilita la habilitación, deshabilitación o ejecución de tareas individuales.
  • El registro está integrado y accesible con journalctl.
  • Proporciona la capacidad de ejecutar cualquier tarea perdida o fallida en el próximo arranque.
  • Puede configurar fácilmente retrasos aleatorios.
  • Puede probar una tarea por sí sola sin esperar la programación, lo que simplifica la depuración.
  • Los trabajos se pueden adjuntar a cgroups.
  • Ofrece un manejo robusto de la zona horaria.
  • Puede configurar cada trabajo para que se ejecute en un entorno específico.

Advertencias

  • Crear una tarea puede ser más detallado que cron. Debe crear al menos dos archivos antes de ejecutar los comandos systemctl.
  • No hay un correo electrónico integrado equivalente al MAILTO de cron para enviar correos electrónicos en caso de fallas en el trabajo.

Creando una tarea

La programación de una tarea a través de un systemd requiere al menos dos archivos de unidad: unidad de servicio y unidad de temporizador. Un archivo de unidad de servicio define el comando real que se ejecutará, mientras que un archivo de unidad de temporizador define la programación.

Manifestación

Esta demostración es un ejemplo de una secuencia de comandos de Python programada por el usuario [birthday_countdown_app.py] que escribe un mensaje y una cuenta regresiva de días hasta o después de su cumpleaños en el año actual.

Crea una secuencia de comandos de Python

Cree un entorno virtual en el nombre de usuario de la casa /:

$ virtualenv venv

Comience a usar Python local:

$ source venv/bin/activate

Cree una secuencia de comandos de Python [birthday_countdown_app.py]:

$ sudo nano birthday_countdown_app.py
import datetime, time


#a birthday countdown app 





def get_birthday_from_user():


    year = 1996 #update your birth year


    month =10 #update your birth month


    day =3 #update your birth day


    birthday = datetime.date(year, month, day)


    return birthday 





def compute_days_between_dates(original_date, target_date):


    this_year = datetime.date(target_date.year, original_date.month, original_date.day)


    dt = this_year - target_date


    return dt.days 





def print_to_file(days):


    path_to_file = "/home/tuts/bc.txt" #address of output text file


    while True:


        with open(path_to_file, "a") as f:


            if days <0:


                f.write("nYou had your birthday {} days ago this year".format(-days))


                f.close()


            elif days >0:


                f.write("nIt is your birthday in {} days".format(days))


                f.close()


            else:


                f.write("nHappy Birthday!!!!")


                f.close()


         time.sleep(450) 





def main():


    bday = get_birthday_from_user()


    now = datetime.date.today()


    number_of_days = compute_days_between_dates(bday, now)


    print_to_file(number_of_days) 





main()





La secuencia de comandos de Python anterior [birthday_countdown_app.py] escribirá un mensaje y una cuenta regresiva de los días hasta o después de su cumpleaños en un archivo de texto [bc.txt] en su directorio de usuario de inicio.

Crear un archivo de unidad de servicio

El siguiente paso es crear el archivo de unidad .service que hará el trabajo real y llamará al script de Python anterior. Finalmente, configuraremos el servicio como servicio de usuario creando el archivo de unidad de servicio en / etc / systemd / user /.

$ sudo nano /etc/systemd/user/birthday_countdown.service

[Unit]


Description=Update message with a current countdown to your birthday


[Service] 





Type=simple


ExecStart=/home/tuts/venv/bin/python /home/tuts/birthday_countdown_app.py


Type=oneshot

Verifique el estado del servicio:

$ systemctl --user status birthday_countdown.service


● birthday_countdown.service


Loaded: loaded (/etc/xdg/systemd/user/birthday_countdown.service static)


Active: inactive (dead)

estado de la unidad de servicio
Verificar el estado de la unidad de servicio.

Notas:
  • El &ampltnombre de usuario&ampgt debe ser su dirección @HOME.
  • El “usuario” en la ruta del archivo de la unidad de servicio es literalmente la cadena “usuario”.
  • El nombre del servicio y el temporizador pueden ser el mismo nombre excepto para la extensión. Se asegurará de que los archivos se encuentren automáticamente entre sí sin tener que hacer referencia explícita a los nombres de archivo. La extensión del archivo de la unidad de servicio debe ser .service, mientras que la extensión del archivo de la unidad del temporizador debe ser .timer.
  • La descripción en la sección [Unidad] explica el servicio.
  • La opción ExecStart en la sección [Servicio] configura el comando para que se ejecute y debe proporcionar una dirección absoluta sin variables. Por ejemplo, especificamos / home / tuts / venv / bin / python /home/tuts/birthday_countdown_app.py como la ruta completa del entorno virtual y el archivo de script de Python.
  • Una excepción a las direcciones absolutas para las unidades de usuario es “% h” para $ HOME. Entonces, por ejemplo, puedes usar:
    %h/venv/bin/python %h/birthday_countdown_app.py
  • Sustituir% h por $ HOME solo se recomienda para archivos de unidad de usuario, no para unidades del sistema. Esto se debe a que las unidades del sistema siempre interpretarán “% h” como “/ root” cuando se ejecuten en el entorno del sistema.
  • La opción [Tipo] está configurada en one-shot, lo que le dice al systemd que ejecute nuestro comando y que el servicio no debe considerarse “muerto” solo porque finaliza.

Crea una unidad de temporizador systemd

El siguiente paso es crear un archivo de unidad .timer que programe la unidad .service. Créelo con el mismo nombre y ubicación que su archivo .service.

$ sudo nano /etc/systemd/user/birthday_countdown.timer
Temporizadores de cuenta regresiva
[Unit]


Description=Schedule a message every 1 hour


RefuseManualStart=no # Allow manual starts


RefuseManualStop=no # Allow manual stops 





[Timer]


#Execute job if it missed a run due to machine being off


Persistent=true


#Run 120 seconds after boot for the first time


OnBootSec=120


#Run every 1 hour thereafter


OnUnitActiveSec=1h


#File describing job to execute


Unit=birthday_countdown.service 





[Install]


WantedBy=timers.target





Notas:
  • La descripción en la sección [Unidad] explica el temporizador.
  • Utilice RefuseManualStart y RefuseManualStop para permitir arranques y paradas manuales.
  • Use Persistent = true para que el servicio se active en el próximo arranque si estaba programado para ejecutarse en un período en el que el servidor está apagado o en instancias en las que hay una falla en la red o en el servidor. Tenga en cuenta que el valor predeterminado siempre es falso.
  • OnBootSec = se refiere al tiempo transcurrido desde el inicio del sistema. También puede usar OnStartupSec =, que se refiere al tiempo transcurrido desde el inicio del administrador de servicios.
  • Utilice OnUnitActiveSec = para activar el servicio en un momento específico después de que se activó por última vez. También puede usar OnUnitInactiveSec = para especificar una hora después de que el servicio se desactivó por última vez.
  • Use Unit = para especificar el archivo .service que describe la tarea a ejecutar.
  • La sección [Instalar] le permite a systemd saber que timers.target quiere el temporizador que activa el temporizador de arranque.
  • En el ejemplo anterior, el servicio se ejecutará 120 segundos después del inicio y se ejecutará cada 1 hora después de eso.
OnCalendar

También puede especificar el horario usando OnCalendar, que es mucho más flexible y sencillo.

[Unit]


Description=Schedule a message daily


RefuseManualStart=no # Allow manual starts


RefuseManualStop=no # Allow manual stops 





[Timer]


#Execute job if it missed a run due to machine being off


Persistent=true


OnCalendar=daily


Persistent=true


RandomizedDelaySec=1h


Unit=birthday_countdown.service





[Install]


WantedBy=timers.target
Notas:
  • OnCalendar se usa diariamente para ejecutar el servicio a la medianoche. Sin embargo, para mayor flexibilidad, RandomizedDelaySec = 1h indica al systemd que elija un lanzamiento en un momento aleatorio dentro de 1 hora antes de la medianoche. RandomizedDelaySec puede ser esencial si tiene muchos temporizadores funcionando con OnCalendar = daily.
  • También puede consultar las abreviaturas de intervalo de tiempo systemd que le permiten indicar 3600 segundos como 1h y así sucesivamente.

Habilitar el servicio de usuario

Habilite el servicio de usuario para probar el servicio que creó y asegúrese de que todo funcione.

$ systemctl --user enable birthday_countdown.service


  Created symlink /home/tuts/.config/systemd/user/timers.target.wants/birthday_countdown.service 


   → /etc/xdg/systemd/user/birthday_countdown.service.

Pruebe el servicio con el siguiente comando:

$ systemctl --user start birthday_countdown.service

Verifique el archivo de salida ($ HOME / bc.txt) para asegurarse de que el script esté funcionando correctamente. Debe haber un solo mensaje de entrada “Es tu cumpleaños en x días”.

Salida de archivo de texto
Salida de archivo de texto [bc.txt]

Activar e iniciar el temporizador

Una vez que haya probado el servicio, inicie y habilite el servicio con los siguientes comandos:

$ systemctl --user enable birthday_timer.timer 


  Created symlink /home/tuts/.config/systemd/user/timers.target.wants/birthday_countdown.timer 


   → /etc/xdg/systemd/user/birthday_countdown.timer
$ systemctl --user start birthday_timer.timer

Los comandos de activación e inicio indican al temporizador que inicie el servicio cuando esté programado.

$ systemctl --user status birthday_countdown.timer

unidad de temporizador de estado
Verifique el estado de la unidad del temporizador.

Después de dejar que el temporizador funcione durante unas horas, ahora puede verificar el archivo de salida ($ HOME / bc.txt). Debe haber varias líneas con el mensaje “Es tu cumpleaños en x días”.

Salida de archivo de texto
Salida de archivo de texto [bc.txt]

Otras operaciones esenciales

Verifique y controle el servicio y depure los mensajes de error de la unidad de servicio:

$ systemctl --user status birthday_countdown


$ systemctl --user list-unit-files

Detenga manualmente el servicio:

$ systemctl --user stop birthday_countdown.service

Detenga y desactive permanentemente el servicio y el temporizador:

$ systemctl --user stop birthday_countdown.timer


$ systemctl --user disable birthday_countdown.timer


$ systemctl --user stop birthday_countdown.service


$ systemctl --user disable birthday_countdown.service

Vuelva a cargar el demonio de configuración:

$ systemctl --user daemon-reload

Restablecer notificaciones de fallas:

$ systemctl --user reset-failed

Programar sugerencias y ajustes

Expresiones de calendario

Las expresiones de OnCalendar lo simplifican y le brindan más flexibilidad en la programación de temporizadores y servicios.

Los siguientes ejemplos ilustran algunos horarios típicos que puede especificar.

En el minuto, en cada minuto, en cada hora de cada día:

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

A la hora, cada hora de todos los días:

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

Cotidiano:

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

10 am todos los días:

OnCalendar=*-*-* 08:00:00

Días de semana a las 6 am en la costa este de EE. UU .:

OnCalendar=Mon..Fri *-*-* 02:00 America/New_York

A la medianoche del primer día de cada año:

OnCalendar=*-01-01 00:00:00 UTC

Medianoche del primer día de cada año en su zona horaria:

OnCalendar=*-01-01 00:00:00 or OnCalendar=yearly

Para ejecutarse a las 10:10:10 del tercer o séptimo día de cualquier mes del año 2021, pero solo si ese día es lunes o viernes.

OnCalendar=Mon,Fri 2021-*-3,7 10:10:10

Notas:

  • En los ejemplos anteriores, * se usa para denotar “todos”. Podría denotar cada fecha, cada hora y zona horaria.
  • OnCalendar también proporciona las expresiones abreviadas minuciosas, diarias, horarias, mensuales, semanales, anuales, trimestrales o semestrales.
  • Utilice timedatectl list-timezones para enumerar las posibles zonas horarias.

calendario systemd-analyse

systemd-analyse calendar le permite probar cualquiera de sus horarios antes de especificar en OnCalendar =.

Por ejemplo, verifique la validez de un servicio programado para ejecutarse todos los lunes, jueves y viernes a las 10 pm UTC.

systemd-analyze calendar "Mon,Thu,Fri *-1..11-* 22:00 UTC"

A continuación, enumere varias iteraciones cuando se ejecutará el servicio:

systemd-analyze calendar --iterations=12 "Mon,Wed,Fri *-1..11-* 23:00 UTC"

Verifique varias iteraciones en un año calendario específico con la opción –base-time:

systemd-analyze calendar --base-time=2022-01-01 --iterations=12 "Mon,Wed,Fri *-1..11-* 23:00 UTC"

Una vez que su expresión de prueba de calendario se compruebe correctamente, ahora puede configurar OnCalendar = con confianza en su horario deseado.

Más información:
consulte esta documentación oficial y páginas de manual para obtener más detalles y ajustes sobre el dominio de los temporizadores de systemd.

  • man systemd.timer
  • man systemd.service
  • systemd: una herramienta práctica para administradores de sistemas
  • systemd-analizar

Resumen

El artículo presenta los temporizadores systemd y cómo programar trabajos del sistema como alternativa a cron. La estructura de un archivo de unidad .service y .timers, que define horarios de temporizador con temporizadores de cuenta regresiva y expresiones de calendario a través de palabras clave como OnBootSec = o OnCalendar =. Finalmente, destacamos cómo solucionar problemas de expresión de calendario con systemd-analyse, operaciones adecuadas de systemctl y algunos consejos prácticos de programación para guiarlo en el camino.

Utilizo temporizadores systemd, pero si te apetece cron, mira nuestra guía de introducción sobre la programación de trabajos con cron.

Leave a Comment

Your email address will not be published. Required fields are marked *

Hazlo Linux