Matteo Vignoli
Sviluppatore Web Full-Stack, autodidatta, curioso per natura,
attualmente impiegato a Milano in ContactLab
Telegram, con i suoi bot e canali, è uno strumento estremamente versatile che si presta molto bene ad essere utilizzato come endpoint per ricevere warning e notifiche di diverso tipo, ad esempio quando un servizio importante come mysql smette di funzionare (per qualsiasi ragione, sono cose che purtroppo capitano e quando capitano sono dolori!).
In un'azienda, normalmente, il monitoraggio è affidato a strumenti appositi e sistemisti dedicati, che sanno come configurare al meglio le macchine e come mettere in piedi un sistema di alert come si deve.
Ma se stiamo parlando di un progetto amatoriale (o di una piccolissima realtà) e non abbiamo troppo tempo e risorse da dedicare al monitoraggio possiamo mettere facilmente in piedi - in poco tempo - qualcosa che funziona, fa il suo dovere ed è abbastanza affidabile da dormire un po' più tranquilli la notte 😉
Su Google o StackOverflow si possono trovare diversi metodi per verificare che mysql sia up, dal vedere se la porta di default (3306) è utilizzata, a fare una grep
sulla lista di processi per cercare un mysql
o mysqld
oppure usando mysqladmin
(che però richiede un'autenticazione). Il metodo che ho usato io, invece, è un po' meno affidabile ma decisamente più spiccio: eseguire un semplice mysql status
e leggerne l'output [^1]
Il codice seguente è molto semplice: utilizzando la libreria nativa subprocess
controlla lo status: se il servizio è down prova ad effettuare un restart (e manda un avvisio via Telegram), se il restart non funziona ci riprova X volte prima di mandare un ultimo avviso e poi attendere l'intervento "umano".
Tutto è dentro un loop continuo per mantenere il processo attivo (il controllo viene fatto ogni 30 secondi ma tutto è configurabile)
#!/usr/bin/env python3
import subprocess, time, requests
""" configuro i comandi da eseguire e i dati per connettermi
a Telegram
"""
cmd_check = ["sudo", "service","mysql","status"]
cmd_restart = ["sudo", "service", "mysql", "restart"]
TELEGRAM_TOKEN = 'TOKEN-ID'
TELEGRAM_CHAT_ID = 'CHAT-ID'
default_sleep = 10;
iter_check = 0
first_warning = False
send = True
messaggi = {
'terzo_tentativo' : 'Terzo tentativo, mysql è ancora down.',
'invio_notifica' : 'Invio notifica...',
'restart': 'Attenzione, mysql sembra down! Provo a fare il restart',
'mysql_ok' : 'Mysql è ok',
'restart_fatto': 'Restart tentato'
}
def get_payload(messaggio):
payload = { 'chat_id': TELEGRAM_CHAT_ID,'text': messaggio,'parse_mode': 'HTML'}
return payload
def warn_telegram(messaggio):
payload = get_payload(messaggio)
return requests.post("https://api.telegram.org/bot{token}/sendMessage".format(token=TELEGRAM_TOKEN), data=payload)
while True:
proc = subprocess.run(cmd_check, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
if "(running)" not in str(proc.stdout):
if iter_check >= 3:
print(messaggi['terzo_tentativo'])
if send:
#Notifica "definitiva" la faccio solo una volta
warn_telegram(messaggi['terzo_tentativo'])
print(messaggi['invio_notifica'])
send = Fals
else:
print(messaggi['restart'])
if not first_warning:
# anche in questo caso, mando un solo avviso al restart
warn_telegram(messaggi['restart'])
first_warning = True
subprocess.run(cmd_restart, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
warn_telegram(messaggi['restart_fatto'])
iter_check += 1
else:
print(messaggi['mysql_ok'])
# azzero il counter
iter_check = 0
send = True
# durata del ciclo
time.sleep(default_sleep)
(Ho usato la libreria requests
perchè era già installata sul server, ma anche le native urlib
vanno benissimo, alla fine si tratta solo di fare una chiamata POST verso le API Telegram)
Questo sistema non è certamente dei migliori ma fa il suo dovere, e può essere esteso al monitoraggio di altri servizi (ad esempio sendmail, redis, ecc.) Ah, per quanto riguarda la creazione di un bot e di un canale di Telegram... ci sono decine di guide là fuori, in inglese ma anche in italiano, è al di fuori dello scope di questo articolo 👽
[^1] Questo comando, così come l'output, variano a seconda dell'OS e della versione di MySQL: può essere service mysql status
per un Ubuntu 14.x oppure systemctl mysql status
per Ubuntu > 16, ecc. Anche l'output della versione di MySQL sembra diverso, tra la 5.6 e la 5.7.* ho notato una differenza abissale.
Matteo Vignoli
Sviluppatore Web Full-Stack, autodidatta, curioso per natura,
attualmente impiegato a Milano in ContactLab