293 - Aventuras y desventuras con Systemd
¿Como ejecutar instancias de usuario de Systemd sin la presencia de usuario?¿Como personalizar una determinada unidad de Systemd?
Como sabes, por lo que te he ido contando en las últimas semanas, estoy aumentando el contenido audiovisual, en concreto en YouTube. Creo, sinceramente, que era la pata que le faltaba al proyecto atareao.es, para completar la formación e información. No se que opinas tu a este respecto. Sin embargo, como bien sabes, no quiero dedicar tiempo a publicar directamente en redes sociales, sino que este trabajo, prefiero delegarlo por completo en la automatización de procesos. Esto no bien sabes, no es algo nuevo, o algo que no te haya contado ya… Es mas, yo diría que te he dado bastante la turra, como dice Pedro, con este tema. En este sentido, hoy te quiero hablar sobre automatización, Systemd y las sesiones de usuario.
Aventuras y desventuras con Systemd
De cron a Systemd
En diferentes ocasiones ya te he hablado sobre mi migración de cron a Systemd. Esto lo puedes encontrar en el tutorial sobre Systemd y en particular en el capítulo titulado Reemplazando cron con Systemd Timer.
No solo esto, sino que también te insistí recientemente el episodio 279 del podcast sobre programar tareas en Linux.
Igualmente te estuve hablando de diferentes servicios. Sobre uno de ellos, en concreto n8n te hablé en el episodio el episodio 281 del podcast, en el que te indiqué mi flujo de trabajo para automatizar la redes sociales.
Sin embargo, desde ese episodio al día de hoy, he cambiado tanto los lugares de publicación, es decir, las redes sociales, como, el proceso de publicación. Te quiero explicar tanto el que como el como.
Mis problemas con los horarios
Como te decía el primer paso ha sido cambiar el proceso de publicación de n8n a que corra directamente como un servicio implementado en Python. El servicio está compuesto por el propio servicio en sí, y un timer
. El servicio es el siguiente,
[Unit]
Description=Publisher
[Service]
Type=oneshot
ExecStart=/usr/bin/python3 /home/lorenzo/procesos/yt2tw/src/publisher.py
Mientras que el timer tiene el siguiente aspecto,
[Unit]
Description=Publisher
[Timer]
OnCalendar=*-*-* 19:00:00
Persistent=true
Unit=publisher.service
[Install]
WantedBy=timers.target
Estos dos archivos se encuentran en el directorio ~/.config/systemd/user
, y una vez copiados allí, tan solo tienes que ejecutar la siguiente instrucción,
systemctl --user daemon-reload
Hasta aquí, todo es relativamente normal. El problema me lo encontré con que no publicaba exactamente a la hora que yo quería. Inicialmente esto lo achaqué al tiempo que tarda en descargar el archivo de YouTube y procesarlo. Sin embargo, ni siquiera era lo hora correcta. Se solía retrasar en torno a las dos horas. Esto lo asocié, erroneamente a la diferencia entre la hora local y la hora UTC. Todo sin, por supuesto, pararme a pensar si era el horario de invierno o verano, o ni siquiera si se tenía que adelantar o retrasar… simplemente me hice mi composición de lugar y ya está.
La solución siempre está en el log
Sin embargo, al ver que estos retrasos no eran constantes, decidí hacer, lo que tenía que haber hecho desde un principio, añadir un log. Pensando que no era un proceso importante no había añadido ese log
y fue un error estúpido. Porque tener log
, de cualquier proceso, no cuesta prácticamente nada, y sobre todo, teniendo en cuenta que el rotado de logs seguro que ya lo tienes configurado.
Fue en ese momento, al leer los logs, donde me di cuenta que el proceso se iniciaba cuando accedía al VPS, que es donde tenía este servicio corriendo.
El problema se encontraba en que las instancias de systemd de usuario se inician cuando el usuario inicia una sesión y se matan cuando el usuario cierra la sesión. En ocasiones, como es este caso, resulta interesante, que la instancia de systemd del usuario se inicie cuando se inicia el servidor y continúe, incluso cuando se cierra la sesión. Para hacer esto, simplemente tienes que ejecutar la siguiente instrucción,
loginctl enable-linger <username>
Donde tendrás que sustituir <username>
por el nombre del usuario sobre el que quieres mantener la instancia en funcionamiento.
De cualquier forma, estoy preparando un artículo detallado sobre este problema para que sepas de que se trata y puedas leer mas información al respecto.
¿Porque no utilizar un servicio de root?
Inicialmente podrías haber pensado que la solución mas sencilla pasaba por haber utilizado un servicio de root
. Pero como he comentado en mas de una ocasión, lo mejor es restringir los permisos de cada usuario y servicio al máximo.
Si no necesitamos ganar derechos de administrador para hacer una tarea, ¿porque ganarlos?¿De verdad que para publicar en redes sociales es necesario hacerlo con root? Ahora cuando lo lees, seguro que te parece tan absurdo como a mi.
Esto no solo se aplicaría a los servicios de Systemd, también sería igual de absurdo aplicar esto a cron
.
Variables de entorno en Systemd
El siguiente problema, no está relacionado con la publicación en redes sociales, pero si que está relacionado con Systemd
, y las variables de entorno.
Implemente un servicio en Python que hacía post
directamente sobre una url
, sin necesidad de proxy, ni nada por el estilo. Hasta que recientemente fue necesario utilizar proxy.
Ni corto ni perezoso me puse a implementar el proxy en Python, para todos los servicios. Comencé a hacer pruebas y aquello no funcionaba para atrás. La solución era mucho mas sencilla. No era necesario ninguna implementación adicional. Simplemente se trataba de añadir una variable de entorno para este servicio.
Para hacer esto, solo tienes que ejecutar,
systemctl --user edit <servicio>
Esto lo que hace es crear un directorio, ~/.config/systemd/user/publisher.service.d/
. Esto crea un archivo, normalmente llamado override.conf
, y dentro de ese archivo puedes añadir o sobre escribir cualquier parte de la unidad. Por ejemplo,
[Service]
Environment=https_proxy=https://192.168.1.110:8080
Desde luego que podría haberlo hecho directamente sobre el propio servicio. Sin embargo, la ventaja de hacerlo así, es que el archivo del servicio es independiente de la instalación que hagas, y puedes personalizarlo para cada una de ellas.
Conclusión
Ya has visto mis aventuras y desventuras con Systemd. No se si me queda algún proceso automatizado ejecutado desde cron
, pero en ese caso, no dudes que le queda poco de vida, porque la migración a Systemd es inmediata.
Espero que te haya gustado este nuevo episodio del podcast. Si puedes, te agradecería una valoración en iVoox y/o en Apple Podcast.
Imagen de portada de Damaris Isenschmid en Unsplash