martes, octubre 08, 2013

Controlar el tamaño de las particiones y sus ficheros con Bash Script

Cuando trabajamos con servidores Linux generalmente estamos bastante confiados de su estabilidad y la mayor parte del tiempo así es. Si los servicios están bien configurados, tenemos una política de seguridad adecuada y además realizamos backups periódicamente nada tiene por qué fallar. O quizás no.


En ocasiones algún bug en un servicio, un fallo de configuración
o un ataque al sistema de repente comienza a generar mensajes de error que van llenando la partición donde tenemos el directorio /var/log hasta que se colapsa el sistema. O por ejemplo nuestras bases de datos alcanzan un tamaño crítico y no podemos realizar operaciones de escritura porque la partición de ha llenado.

Si además es la misma partición de root y la compartes con otros servicios tienes un buen problema. Con toda probabilidad esta falta de espacio provocará que otros servicios vayan cayendo al interrumpirse los procesos de escritura y quedarse también sin espacio: motores de bases de datos, servidores web y de correo, compartición de ficheros… Todos estos procesos empezarán a dar problemas hasta que el propio sistema quede inoperativo y en muchos casos tardarás un buen rato en darte cuenta que el problema es un error en algún servicio.

¿Qué hacer cuando tenemos una partición llena?
En primer lugar no entres en pánico y no reinicies la máquina por que sí cuando veas que tu servidor se ha vuelto inestable. Si tenías operaciones pendientes en bases de datos por ejemplo las perderás. Lo mismo en otros servicios, como transacciones de ficheros, conexiones web, emails, etc. Averigua qué sucede primero y actúa en consecuencia.

Un fallo frecuente es que se haya llenado la partición donde se almacenen los ficheros de /var/log. Entonces mueve los archivos de logs de mayor tamaño a otra ubicación para revisarlos más tarde y detén o deshabilita el servicio problemático. Ahora el resto de servicios tendrán espacio para operar con normalidad. Si aún así crees que es necesario reinicia los servicios críticos o reinicia el servidor, pero asegurate antes de que todo está operando normalmente y has deshabilitado los servicios problemáticos.

Es un problema más frecuente del que parece, un servicio falla y comienza a dar mensajes de error. Si la partición donde está /var/log es pequeña el colapso se dará pronto. En caso de que sea muy grande puede suceder que tardes varios días en darte cuenta y quizás descubras que el servicio da problemas antes de que el sistema caiga. En cualquier caso ningún fallo es deseable.

Medidas preventivas
Independientemente qué cause que una partición se colapse por completo deberemos de vigilar el tamaño y ocupación de las particiones del sistema; así como el tamaño de los ficheros que contenien. Para ello he desarrollado este sencillo script que realiza esta misión de vigilancia pasando un cron cada 15 minutos.

En mi caso el gestor de correo Cyrus ha sido el responsable de más de un quebradero de cabeza por fallos en el indexado o de acceso a carpetas, lo cual ha comenzado a saturar de mensajes de error/var/log/mail.err hasta que ha colapsado el sistema. A partir de ahora espero que eso no suceda.

El script
Podes comprobar que el script es plenamente configurable y reutilizable, preparado para controlar la ocupación de varios puntos de montaje, así como el tamaño de los ficheros que contienen.

#!/bin/bash

# Functions
sendMailStatus() {
 mail -s "$1" \
 -a "MIME-Version: 1.0" \
 -a "Content-Type: text/html" \
 root@$domain < $2
 return $?
}

# Vars
domain=$(dnsdomainname)
localHost=$(hostname)
dirsToWatch=("/var/log" "/var/mail")
maxPercentageOfUsage=5
maxFileSize='100M' # In MB
logWatcherFile='logwatch.log'

# Resetting log
cat /dev/null > $logWatcherFile

# Retrieving the partition usage and parsing the string 
for currentDir in ${dirsToWatch[@]}; do
        # Extracting and parsing the usage of partition
 ocupationPercentage=$(df -P $currentDir | awk '/[0-9]+%/ {gsub("%",""); print $5}')

 # Checking the percentage of usage
 if [ $maxPercentageOfUsage -le $ocupationPercentage ]; then

         # Including the error message
         echo "<p>The used space of partition where <b>$currentDir</b> is mounted is greater than limit of <b>$maxPercentageOfUsage%</b><br />Now is at <b>$ocupationPercentage%</b> of usage.</p" >> $logWatcherFile

 fi

 # Retrieving the filenames of files greater than limit
 filesGreaterThanLimit=$(find $currentDir -mount -type f -size +$maxFileSize)

 # Checking the maximum filesize limit
 if [ -n "$filesGreaterThanLimit" ]; then

  # Including the error message
 echo "<p>The following file/s from <b>$currentDir</b> is/are greater than <b>$maxFileSize limit</b></p>
  <pre>$filesGreaterThanLimit</pre>" >> $logWatcherFile

 fi
done


# Sending the warning email if logfile has content
if [ -s $logWatcherFile ]; then
 sendMailStatus "WARNING: Partition or file size limits exceeded" $logWatcherFile
fi

Ahora ya solo queda asignar dicho script a una tarea cron cada cierto tiempo y el script nos avisará cuando se alcancen los límites especificados. Espero que os sea de utilidad y por supuesto aportes otras alternativas que conozcáis o utilicéis.


Escrito por: Oscar Gascón