A pile of endless side projects

A tiny blog on stuff I do

Servicehandler: una libreria per ghermirli...

2020-06-28

Mi piacerebbe parlare di un altro progettino che mi ha tenuto occupato ultimamente (oltre ad ITAQA, su cui sto ancora lavorando!): lo sviluppo di una piccola libreria Python in grado di gestire ed orchestrare servizi (o daemon) in Linux.

Bot fantastici e dove hostarli

Ultimamente ho sviluppato quattro bot di Telegram usando la stupenda libreria python-telegram-bot.
Per chi non sa cosa sia un bot di Telegram rimando a questa pagina (in inglese). Brevemente, in questo contesto un bot è un’applicazione in grado di interagire con utenti/gruppi direttamente su Telegram, rispondendo a messaggi ed accettando comandi.

Alcuni di questi bot saranno probabilmente oggetto di post futuri, per ora però voglio parlare del loro hosting e della loro gestione.

Hardware

Un bot è un’applicazione come un’altra (in questo caso specifico, uno script Python). Per poter interagire con essa in qualunque momento, occorre che sia costantemente in esecuzione. Due sono le soluzioni possibili:

Per diversi motivi1 ho optato per la seconda soluzione: hosting su Raspberry PI Zero W. Con 512MB di RAM ed una CPU single core da 1GHz, non è esattamente un computer da TOP500, ma considerando le poche risorse di cui necessitano i miei bot, è abbastanza. I punti forti dello Zero sono l’ingombro minimo, il modulo WiFi integrato e la possibilità di alimentarlo tramite Micro-USB (utilizzando un semplice caricatore da cellulare).

Software

Scelto l’hardware ed installata una distro Linux come Raspberry Pi OS (conosciuto in passato come Raspbian) occorre configurare i vari bot in modo che vengano eseguiti automaticamente all’avvio del sistema.

Il modo più semplice per avviare applicazioni automaticamente è creare dei servizi ad-hoc. Per far ciò si può sfruttare systemd, suite di configurazione/amministrazione nativa di ogni sistema Linux. Per ogni nuovo servizio uno unit file va scritto e posizionato in /usr/lib/systemd/user/:

[Unit]
Description=Il mio bot

[Service]
ExecStart=/usr/bin/python3 /home/user/bot/main.py
Environment=PATH=/bin:/usr/bin:/usr/local/bin
WorkingDirectory=/home/user/bot/

[Install]
WantedBy=multi-user.target

Finalmente, è sufficiente indicare quali servizi vanno avviati automaticamente utilizzando il comando systemctl --user enable MyBot.service.

Tutto fatto. Basta avviare il Raspberry, dimenticarsene, ed avere tutto funzionante alla perfezione per sempre.

Fantastico.

Non fosse per un piccolo dettaglio: spesso2 le cose non vanno come previsto, quindi potrebbe essere utile dover riavviare i bot, controllare i loro log, terminarli forzatamente se necessario, e così via. Tutte cose facili da effettuare quando connessi alla stessa rete del Raspberry, più complesse da remoto.3

Sarebbe fantastico poter effettuare queste operazioni in modo semplice da qualsiasi posto, magari… creando un altro bot…

Sarà un umile gestore di altri bot, con un nome modesto ed un’immagine profilo sobria. Non vorrei creare un malvagio sovrano indiscusso.

Mh.

Una libreria per ghermirli e nel buio incatenarli

Un malvagio bot con brame di potere bot controllore4 non può fare nulla se non è in grado di interagire e controllare servizi systemd. Ciò che serve è una libreria in grado di wrappare systemctl.

Chi ha già usato Python sa perfettamente che esiste una libreria per qualsiasi cosa.5 Ho cercato in giro qualcosa che facesse al caso mio. Non avendo trovato nulla che corrispondesse a ciò che mi serviva, ho deciso quindi di crearne una.

systemd-servicehandler

La libreria si chiama systemd-servicehandler, o più semplicemente servicehandler.6

(Sono molto orgoglioso del banner)

Stato attuale

servicehandler è in fase sperimentale, non è nulla di superlativo ma attualmente funziona. Vanno indubbiamente ancora implementate alcune funzionalità, aggiunti test ed effettuati alcuni miglioramenti.

Non esistendo ancora una libreria simile ho deciso di impacchettarla e distribuirla su PyPI (servicehandler su PyPI), in modo che possa essere utilizzata da altri sviluppatori tramite pip (pip install servicehandler).

Attualmente le funzionalità di base (astrazione di servizi e metodi per il controllo7) sono implementate, rendendo possibile controllare un bot (o un qualsiasi servizio) in questo modo:

import servicehandler as sh

# Crea un oggetto ServiceHandler che rappresenta il servizio del bot
my_bot = sh.ServiceHandler('Bot','MyBot.service')

# Controlla lo stato del bot
my_bot.state()
<ServiceState.STOPPED: 2>

# Avvia un bot
my_bot.start()
Bot changed state to ServiceState.STOPPED
<Response.OK: 1>
    
# Ferma il bot
my_bot.stop()
Bot changed state to ServiceState.RUNNING
<Response.OK: 1>

Prossimamente

Alcune cose da implementare in futuro:

Come gli altri progetti di cui parlo in questo blog, anche servicehandler è completamente open-source e consultabile su GitHub: servicehandler.

A presto, al prossimo articolo!


  1. So che una qualsiasi macchina virtuale della fascia gratuita sarebbe bastata. Tuttavia cerco di massimizzare il “fai-da-te” nei miei progetti. Inoltre ho scelto di riesumare il povero RPi Zero da un paio di anni vede solamente l’interno di un cassetto. Si sarà annoiato, povero 

  2. Sempre 

  3. È ovviamente possibile configurare port-forwarding od utilizzare VNC, sono entrambe soluzioni valide 

  4. Chi controllerà i controllori? Ovviamente LordOfTheBot deve essere controllato manualmente (per esempio tramite SSH). Deve avere un design robusto, che lo renda il più possibile affidabile e stabile 

  5. xkcd: Python 

  6. Mi rendo conto di aver perso l’occasione di chiamare la libreria systemd-onering o qualcosa di simile, ma un barlume di serietà mi è rimasto (risate di sottofondo

  7. Sono disponibili metodi per avviare, fermare, abilitare, disabilitare, killare, ottenere lo stato