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.
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)
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".
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
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".
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