Programación de tareas con temporizadores systemd en Linux

Systemd 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.

Índice

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 el horario.

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

Crea 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()


El script 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:

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 el [Unit] La sección 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 cuando 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.
  • los [Install] La sección 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 de 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 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.

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

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 útiles de programación para guiarlo en el camino.

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

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Subir