Linux: come ricevere una mail quando il disco è quasi pieno

a server rack

Il disco del server aziendale ogni tanto si riempie bloccando tutto: gestionale, database ecc.

Se per voi questo scenario è comune forse avete trovato il modo per risolverlo, ma andiamo con ordine.

Mi è capitato nella mia carriera di aver a che fare con software enterprise che hanno la brutta abitudine di non ripulire mai i file di log che periodicamente producono (es. IBM DB2) con conseguente riempimento periodico dello spazio su disco e blocco di loro stessi in primis e a catena di tutto il resto, magari l’ERP della vostra azienda.

Sicuramente esistono dei software molto belli e molto costosi che potrebbero tener controllato lo stato del server e prevenire questi casi, fortunatamente per voi se il SO del vostro server è Linux non ne avete bisogno.

In questo caso infatti è sufficiente predisporre un piccolo script che periodicamente controlla lo stato di occupazione dei dischi e vi notifica via mail di un eventuale superamento di una soglia di occupazione predefinita.

Per realizzare uno script del genere dobbiamo essere in grado di fare sostanzialmente due cose:

  1. controllare lo stato di occupazione dei dischi
  2. inviare una mail

Il comando Linux per soddisfare il primo requisito è df che, se lanciato con l’opzione -h, ci darà una visione d’insieme umanamente leggibile sullo stato di occupazione delle partizioni.

es.

srv02:~ # df -h
Filesystem Size Used Avail Use% Mounted on
/dev/sda2 98G 7.4G 91G 8% /
udev 1015M 120K 1014M 1% /dev

Per poter trattare però il suo output in maniera automatica ci conviene utilizzarne la versione seguente:

srv02:~ # df -a -P
Filesystem 1024-blocks Used Available Capacity Mounted on
/dev/sda2 102748540 7692172 95056368 8% /
proc 0 0 0 - /proc
sysfs 0 0 0 - /sys
debugfs 0 0 0 - /sys/kernel/debug
udev 1038388 120 1038268 1% /dev
devpts 0 0 0 - /dev/pts
securityfs 0 0 0 - /sys/kernel/security

Il comando Linux per soddisfare il secondo requisito è mail che appunto serve per mandare mail da riga di comando.

Mettendo tutto insieme otteniamo qualcosa di simile

#!/bin/bash

set -x

SIZE_PERC_LIMIT=75
TO="admin@domain.it"
CC="cto@domain.it"
NOREPLY="$(hostname)-noreply@domain.it"
FROM="$(hostname)@domain.it"

df -a -P | grep '^/dev/' | tr -s ' ' | cut -d' ' -f5 | grep '%' | cut -d% -f1 | while read value; do
if [ $value -ge $SIZE_PERC_LIMIT ]; then

echo "*** $(hostname) ha raggiunto la soglia di occupazione del ${value}% di una partizione" > /tmp/check_disco.log
echo "*** di seguito viene riportato l'output del comando: df -h" >> /tmp/check_disco.log
df -h >> /tmp/check_disco.log

SUBJECT="ATTENZIONE $(hostname): stato occupazione partizioni"

mail -c "$CC" -r "$FROM" -R "$NOREPLY" -s "$SUBJECT" "$TO" < /tmp/check_disco.log

break
fi
done

L’unica riga che credo richieda una spiegazione è la 11 la quale ha come scopo quello di ottenere per ogni partizione la percentuale di occupazione e per farlo compie in sequenza le seguenti operazioni:

  1. df -a -P: stampa lo stato di tutte le partizioni utilizzando il formato POSIX. Questo dovrebbe favorire la portabilità di questo script.
  2. grep '^/dev/': seleziona solo le partizioni che ci interessano (ovviamente l’espressione regolare potrebbe essere modificata a seconda della nomenclatura delle vostre partizioni) scartando cioè filesystem virtuali, dispositivi di rete, ecc.
  3. tr -s ' ': rimpiazza le sequenze di spazi con spazi singoli per facilitarne la suddivisione con il comando successivo
  4. cut -d' ' -f5: taglia le righe in campi separati da spazi e ne prende il quinto: quello della percentuale di occupazione
  5. grep '%': tiene solo i valori percentuali scartando eventuali trattini
  6. cut -d% -f1: separa la percentuale dal valore e tiene quest’ultimo
  7. while read value; do: il valore letto lo memorizza nella variabile $value

Il resto dello script non fa altro che confrontare ogni valore letto con la soglia d’allarme che in questo esempio è impostata sul 75% e nel caso in cui sia maggiore spedisce una mail a chi di dovere.

A questo punto non ci resta che schedulare questo script, che chiameremo check_disco.sh e a cui daremo i permessi di esecuzione, con il mitico crontab a seconda delle nostre esigenze.

Se per esempio abbiamo paura che il disco si possa riempire repentinamente, magari a causa di qualche software che in caso di errore produce grossi dump a rate elevati (Java VM anyone?), possiamo pensare di schedularlo in modo che giri ogni ora con la seguente riga di crontab:

0 * * * * /usr/bin/check_disco.sh &> /var/log/check_disco.log

Da notare come la riga 3 dello script (set -x) in combo con la redirezione degli stream di output su check_disco.log ci darà la possibilità di valutare l’ultima esecuzione dello script, nel caso in cui le cose non siano andate come ci aspettavamo.

Come nota finale aggiungo che se non riuscite a mandare le mail attraverso il comando mail, potreste provare a creare un file .mailrc nella directory home dell’utente su cui è stata schedulata l’esecuzione dello script, in cui specificare l’indirizzo del vostro server SMTP nel modo seguente:

set smtp=X.X.X.X