Información blog

Linux, tutoriales, noticias, sistemas, redes y seguridad informática, entre otras cosas.

domingo, 12 de julio de 2015

Controlando la salud del equipo con bash

Siguiendo con la línea del último post, en el día de hoy vengo a explicaros cómo podemos tener controlados los diferentes aspectos relacionados con la salud y el rendimiento del equipo mediante bash. Un servidor que tenga que soportar muchas peticiones o una raspberry a la que queramos exprimir el máximo partido posible, pueden verse sobrecargados si no vigilamos bien todos los aspectos relacionados con el rendimiento; tales como el consumo de ram, carga a la que están sometidos los procesadores, espacio en el disco, etc... La cuestión está que cada uno de estos puntos está reflejado en sitios distintos, y además en algunos casos es necesario interpretarlos, por ello el post de hoy tiene dos objetivos:
  1. Explicar los distintos aspectos relacionados con el rendimiento y como consultarlos.
  2. Agrupar todos los conceptos en un solo script escrito en bash para interpretar los resultados con fácil y rápidamente.
I love bash

Para ello comenzaré con uno de los aspecto más importantes dentro de un ordenador; un aspecto que no conviene subestimar, especialmente si hablamos de servidores. Se trata del procesador. Un procesador no es ni más ni menos que el encargado de gestionar todos los procesos del sistema; La velocidad con la que se resuelven estos procesos dependen de muchos aspectos, pero existen dos de ellos que son fundamentales:
  1. Calidad del procesador.
  2. Número de procesadores/núcleos.
La calidad del procesador es un punto bastante subjetivo, pues aquí influyen bastante los gustos, aún así por lo general habría que fijarse en la velocidad en la que trabaja y el consumo...

Por otro lado estarían los procesadores y núcleos. Esto es un aspecto bastante más objetivo. Imaginemos que nuestro procesador es un carretera, y que los procesos son coches... Imaginemos también que dicha carretera es lo suficientemente grande como para soportar 5 coches circulando por dicha carretera... En caso de tener 6 coches queriendo pasar por dicha carretera, uno de ellos tendría que esperarse a que uno de los coches de la carretera termine el trayecto, ya que no hay espacio para que entren más... Obviamente esa espera por parte de dicho coche se traduce, en términos informáticos, en un mayor tiempo de espera para que se finalice un proceso. 

Representación coloquial de procesos y procesador
Representación coloquial de procesos y procesador

Con el cada vez mayor número de procesos con los que los equipos de hoy en día tienen que lidiar, un solo procesador no tiene la capacidad suficiente para gestionar con agilidad todas las tareas que le mandan, es por ello que hoy en día se venden algunos equipos con doble procesador; Aún así, dos procesadores siguen siendo incapaces de recibir todo el tráfico, es por ello que se han desarrollado los núcleos, que simplemente se trata del mismo concepto dentro de un solo procesador; es decir que por ejemplo un procesador con dos núcleos sería prácticamente lo mismo que dos procesadores que uno solo, con la diferencia de que la primera opción es más económica. Aún así, en Linux ambos son tratados de la misma forma y son reconocidos de la misma forma; es por ello que cuando haces una búsqueda sobre la información de la cpu, veréis que el sistema puede estar reconociendo 4 procesadores, aún cuando en realidad simplemente se tiene uno con 4 núcleos. Para conocer el número de procesadores que tiene nuestro equipo, simplemente habría que ejecutar el comando:

  1. cat /proc/cpuinfo |grep processor |wc -l

Esto, aunque resulta interesante, puede parecerle poco importante a uno que le preocupe el rendimiento de su equipo; pero más adelante veréis que está estrechamente relacionado con éste. Ahora que conocemos la cantidad de procesadores que tiene el sistema, procederíamos observar qué carga poseen nuestros "procesadores". Para ello se recurriría al comando:

  1. cat /proc/loadavg
Aquí obtendríamos una serie de valores que pude que a uno le parezcan inconexos y sinsentido, aunque en realidad sí que tienen significado. Por ejemplo imaginemos que hemos tenido este resultado:

Loadvg_text

El primer valor representaría la carga de promedio que han tenido los procesadores durante el último minuto; el segundo valor representaría lo mismo pero para los 5 último minutos, mientras que el tercero para los 10. Además estaría el 4 valor, que representaría el número de proceso del que el procesador se estaría encargando en este momento, aparte del número de procesador que estaría haciéndose cargo de dicho proceso. El último valor haría referencia al número total de procesos que está gestionando el procesador.

Ahora bien, ¿como sabemos si dichos promedios mostrados por loadavg son altos o bajos? Gracias al número de procesadores que hay en el sistema. Estos valores representan el número de procesadores "ocupados" en este momento, con lo que por ejemplo un valor de 4 puede ser bueno en un equipo con 8 procesadores, mientras que un valor de 2 puede ser un valor catastrófico en un entorno con un solo procesador, ya que habrían muchísimos procesos en cola esperando. Teniendo esto en cuenta, podríamos calcular el % de carga que están soportando nuestros procesadores de promedio. Dicho % podría hacerse en base a los tres promedios o al del último minuto. Si por ejemplo quisiésemos hacer el cálculo en base al último minuto, un pequeño script que lograría esto sería:

  1. #!/bin/bash
  2. NUCLEOS=$(cat /proc/cpuinfo |grep processor |wc -l)
  3. CARGA1MIN=$(cat /proc/loadavg |awk {'print $1'} |bc -l)
  4. echo "scale=2;100 * ${CARGA1MIN} / ${NUCLEOS}" |bc > /tmp/resultado.txt
  5. PERCENTCARGA=$(cat /tmp/resultado.txt)
  6. rm /tmp/resultado.txt
  7. echo "Porcentaje carga:${PERCENTCARGA}%"

Obviamente siempre habrán nucleos que trabajen más que otros, pero este es un recurso muy útil para tener una noción general de la carga que está soportando el procesador.

Teniendo esta parte clara, llegaría el turno de tener controlada la ram... La ram(Random Access Memory) es la memoria de trabajo del equipo, y es bastante importante tener controlada la cantidad de memoria usada, pues aunque el tener gran parte de la memoria en uso no es perjudicial, es importante controlar que nunca se acerque al límite de memoria ramdisponible, pues en dicho caso el ordenador empezaría a usar swap o incluso podría bloquearse. El comando para mantener controlada la memoria ram total y la memoria ram usada se denomina free. Aún así, el resultado que muestra el comando por defecto (es decir sin parámetro alguno) es mostrado en kilobytes, algo poco práctico teniendo en cuenta las cantidades de memoria que se controlan hoy en día; por ello, mediante el uso del parámetro -m o -g, podemos mostrar el resultado en megabytes o gigabytes respectivamente. A nivel práctico, lo más útil es visualizar la memoria en megabytes, con lo que usaremos el comando:

  1. free -m

El comando en cuestión os mostrará algo como esto:

ram_megabytes

Aquí podríamos ver la ram total, la ram usada, la ram libre y la cantidad de memoria cacheada... Aunque esto que aparece aquí mostrado es muy informativo, yo soy más partidario de los porcentajes, con el fin de poder saber con mayor exactitud si nos queda poca RAM libre o no. Para ello habría que coger el valor de la ram usada, multiplicarla por 100 y luego dividirla entre la ram total (la típica regla de tres); obteniendo así el porcentaje usado. Esto se plasmaría en un script de bash tal que así:

  1. #!/bin/bash
  2. RAMTOTAL=$(free |grep Mem |awk '{print $2}' |bc -l)
  3. RAMUSADA=$(free |grep Mem |awk '{print $3}' |bc -l)
  4. echo "scale=2;${RAMUSADA} * 100 / ${RAMTOTAL}" |bc > /tmp/resultadoram.txt
  5. PORCENTAJERAM=$(cat /tmp/resultadoram.txt)
  6. rm /tmp/resultadoram.txt
  7. echo "Porcentaje ram usada:${PORCENTAJERAM}%"

Casi tan importante como controlar la memoria ram, es controlar el espacio en el disco duro que llevamos usada, pues aunque los discos duros de hoy en día tienen cada vez mayor capacidad (Hoy en día tenemos discos de 2 TB muy asequibles). Para controlar tanto el espacio ocupado en el disco duro como el espacio total se usaría el comando df; el cual por defecto muestra los resultados en gigabytes... Aunque los resultados son muy acertados, yo recomiendo plasmar éstos en megabytes, pues después querremos obtener un % y el calculo y preferimos trabajar con números enteros para hacer el calculo (aún cuando el resultado final casi siempre tendrá decimales). Para mostrar los resultado en megabytes se usaría el parámetro -B m; lo cual haría que el comando final fuese este:

  1. df -B m
df_megabytes

Gracias a dicho comando obtendríamos una lista de resultados referentes a cada una de las particiones montadas en el sistema, aún cuando solo nos puede interesar una de ellas (en nuestro caso sólo nos interesaría la partición /), eso implica que querríamos distinguir esta partición del resto y que además queremos obtener únicamente el tamaño total de la partición y la cantidad de megabytes usados... Todo esto sumado a que dependiendo del sistema de la versión del sistema operativo se obtienen estos datos de una forma u otra, haría que creasemos dos métodos distintos para extraer dichos datos... Con dichos datos extraídos, obtendríamos el % de disco duro usado mediante la misma regla de tres que hemos usado para la memoria ram. Todo esto se plasmaría en un script de bash de la siguiente forma:

  1. #!/bin/bash
  2. #DEPENDIENDO DEL SISTEMA OPERATIVO O SU VERSION, SE PUEDE OBTENEN OBTENER LOS TAMAÑOS DE UNA FORMA U OTRA
  3. if [[ $(df -B m |grep $(cat /etc/fstab |grep "/ " |awk '{print $1}' |cut -d "=" -f 2 |grep -v "#")) == '' ]];
  4. then
  5.         TOTALDISCO=$(df -B m |grep "/$" |awk '{print $2}' |cut -d "M" -f 1)
  6.         OCUPDISCO=$(df  -B m |grep "/$" |awk '{print $3}' |cut -d "M" -f 1)
  7. else
  8.         TOTALDISCO=$(df  -B m |grep $(cat /etc/fstab |grep "/ " |awk '{print $1}' |cut -d "=" -f 2 |grep -v "#") |awk '{print $2}'  |cut -d"M" -f 1)
  9.         OCUPDISCO=$(df  -B m |grep $(cat /etc/fstab |grep "/ " |awk '{print $1}' |cut -d "=" -f 2 |grep -v "#") |awk '{print $3}' |cut -d "M"-f 1)
  10. fi
  11. echo "scale=2;${OCUPDISCO} * 100 / ${TOTALDISCO}" |bc > /tmp/resultadodisco.txt
  12. PORCENTAJEDISCO=$(cat /tmp/resultadodisco.txt)
  13. rm /tmp/resultadodisco.txt
  14. echo  "Porcentaje Disco ocupado:{PORCENTAJEDISCO}%"

Por último pero no menos importante estaría la cuenta de procesos en el sistema. Cuando existen problemas de rendimiento (lentitud, mucha memoria ram consumida, etc...) la mayoría de las veces se debe a un gran número de procesos existentes. Para tener todos los procesos contabilizados se usaría la combinación de ps -e para obtener éstos, en conjunto con el parámetro |wc -l para realizar el recuento de dichos procesos. Así pues, el comando final sería:

  1. ps -e |wc -l

Así pues, con todo lo que hemos visto hasta ahora podríamos hacer un solo script que combinase todas estas revisiones para que nos mostrasen todo de forma agrupada. Dicha agrupación se puede mostrar ordenada e incluso coloreada para darle vistosidad... El resultado final sería éste:

  1. #!/bin/bash
  2. #COLOR
  3. red='\e[0;31m'
  4. green='\e[0;32m'
  5. NC='\e[0m' # No Color
  6. #CARGA CPU
  7. NUCLEOS=$(cat /proc/cpuinfo |grep processor |wc -l)
  8. CARGA1MIN=$(cat /proc/loadavg |awk {'print $1'} |bc -l)
  9. echo "scale=2;100 * ${CARGA1MIN} / ${NUCLEOS}" |bc > /tmp/resultado.txt
  10. PERCENTCARGA=$(cat /tmp/resultado.txt)
  11. rm /tmp/resultado.txt
  12. #RAM
  13. RAMTOTAL=$(free |grep Mem |awk '{print $2}' |bc -l)
  14. RAMUSADA=$(free |grep Mem |awk '{print $3}' |bc -l)
  15. echo "scale=2;${RAMUSADA} * 100 / ${RAMTOTAL}" |bc > /tmp/resultadoram.txt
  16. PORCENTAJERAM=$(cat /tmp/resultadoram.txt)
  17. rm /tmp/resultadoram.txt
  18. #ESPACIO DISCO
  19. #DEPENDIENDO DEL SISTEMA OPERATIVO O SU VERSION, SE PUEDE OBTENEN OBTENER LOS TAMAÑOS DE UNA FORMA U OTRA
  20. if [[ $(df -B m |grep $(cat /etc/fstab |grep "/ " |awk '{print $1}' |cut -d "=" -f 2 |grep -v "#")) == '' ]];
  21. then
  22.         TOTALDISCO=$(df -B m |grep "/$" |awk '{print $2}' |cut -d "M" -f 1)
  23.         OCUPDISCO=$(df  -B m |grep "/$" |awk '{print $3}' |cut -d "M" -f 1)
  24. else
  25.         TOTALDISCO=$(df  -B m |grep $(cat /etc/fstab |grep "/ " |awk '{print $1}' |cut -d "=" -f 2 |grep -v "#") |awk '{print $2}'  |cut -d"M" -f 1)
  26.         OCUPDISCO=$(df  -B m |grep $(cat /etc/fstab |grep "/ " |awk '{print $1}' |cut -d "=" -f 2 |grep -v "#") |awk '{print $3}' |cut -d "M"-f 1)
  27. fi
  28. echo "scale=2;${OCUPDISCO} * 100 / ${TOTALDISCO}" |bc > /tmp/resultadodisco.txt
  29. PORCENTAJEDISCO=$(cat /tmp/resultadodisco.txt)
  30. rm /tmp/resultadodisco.txt
  31. #PROCESOS
  32. PROCESOS=$(ps -e |wc -l)
  33. #RESULTADOS
  34. clear
  35. echo -e "${red}RESULTADO REVISION${NC}"
  36. echo -e "Porcentaje carga:${green}${PERCENTCARGA}%${NC}" #CARGA
  37. echo -e "Porcentaje ram usada:${green}${PORCENTAJERAM}%${NC}" #RAM
  38. echo -e "Porcentaje Disco ocupado:${green}${PORCENTAJEDISCO}%${NC}" #OCUPADO
  39. echo -e "Numero de procesos:${green}$PROCESOS${NC}" #NUMERO PROCESOS

Tan solo quedaría darle a dicho script permisos de ejecución y ya podríamos disfrutar de esta sencilla herramienta escrita en bash. El resultado que daría dicha herramienta sería algo parecido a este:

Resultado_final

Espero que os resulte útil.

Saludos.

5 comentarios :

  1. con su permiso lo inserto en mi .basrc...gracias.

    ResponderEliminar
    Respuestas
    1. Para eso está dicho script. Me alegro de que te haya gustado.

      Saludos.

      Eliminar
    2. muy bueno amigo. una pregunta y paa calcular las conexiones simultaneas de un servidor apache como hago y tambien las conexiones maximas en cualquier mmento cual seria el script atte dennis

      Eliminar
  2. , lo q pasa es q nose cuanto aguantaria mi apahe

    ResponderEliminar
    Respuestas
    1. Buenas tardes DENISS.

      Ante todo gracias por tus comentarios; con respecto al cálculo de las conexiones simultáneas en apache, existe un comando llamado netstat (muy útil por cierto) que nos permite controlar el número de conexiones simultáneas en apache. Dicho comando es:

      netstat -putan |grep apache

      Con respecto al número máximo de conexiones. Por defecto son 150, si bien dicho valor se puede modificar. Casualmente realicé un post sobre dicho tema en un blog llamado desde linux; post cuyo enlace te dejo a continuación y que creo que te puede ser de gran ayuda:

      http://blog.desdelinux.net/como-aumentar-conexiones-simultaneas-apache/

      Espero que te resulte útil.

      Saludos

      Eliminar