"Después del juego es antes del juego"
Sepp Herberger

jueves, 25 de abril de 2019

Monitorizando los puestos del aula con monit (II)

Seguimos desde aquí. Vamos a ampliar añadiendo controles basándonos en esta entrada de mi compañero Esteban:
  • Temperatura de la CPU
  • Temperatura de la placa base
  • Temperatura del disco duro
  • Temperatura de la GPU (tarjeta gráfica)
  • Velocidad ventiladores
  • Estado de las fuentes de alimentación redundantes en el servidor del centro
Todo esto lo haremos usando los comandos sensors, nvidia-smi, hddtemp y hplog.

El comando sensors es el que mas información da, pero el problema es que es muy dependiente del hardware y con él no obtenemos una salida homogénea con los números bien colocaditos, sino distintos formatos de presentación a partir de los cuales extraemos los datos. A eso hay que añadir que no siempre tenemos accesibles todos los valores de temperaturas y/o ventiladores debido a que a veces los comandos sensors y hddtemp no son compatibles con el hardware subyacente.

Con esto así he adaptado los scripts para que sean los mas completos posibles, pero no es descartable irlos ampliando conforme vayamos recibiendo nuevos equipos o actualizaciones que hagan que sensorsse comunique mejor con el hardware.

El fichero de monitorización para todas la máquinas sería (esto se añadiría a la tarea puppet vista en el post anterior):
# cat /etc/monit/conf.d/monitrc.temperatura
check program mbtemperatura with path "/usr/local/bin/mbtemp.sh"
   if status > 60 for 3 cycles then alert
   group temperature

check program cputemperature  with path "/usr/local/bin/cputemp.sh"
   if status > 65 for 3 cycles then alert
   group temperature

check program hddtemperature with path "/usr/local/bin/hddtemp.sh"
   if status > 50 for 3 cycles then alert
   group temperature

check program vgatemperature with path "/usr/local/bin/vgatemp.sh"
   if status > 98 for 3 cycles then alert
   group temperature

check program fanspeed with path "/usr/local/bin/fanspeed.sh"
   if status = 1 for 3 cycles then alert
   group temperature
El script que comprueba la velocidad de los ventiladores (solo funciona en las placas Asus de los servidores LTSP que nos envió Telefónica) sería:
# cat /usr/local/bin/fanspeed.sh
#!/bin/bash
hardware=$(facter hardware)
FANSPEED=0 #
case $hardware in
   "telefonica")
         FANSPEED1=$(sensors |grep "^CPU FAN Speed" | awk '{print $4}')
         FANSPEED2=$(sensors |grep "^CHASSIS2 FAN Speed" | awk '{print $4}')
         test $FANSPEED1 -lt 600 -o $FANSPEED2 -lt 600 && FANSPEED=1       #Si alguno de los ventiladores gira por debajo de los 600RPM se avisa de ello
         ;;
esac
#echo $FANSPEED # for debug only
exit $FANSPEED
Para estos PC, que tienen una placa Asus P5Q DELUXE, la salida de sensors es muy completa:
# sensors
coretemp-isa-0000
Adapter: ISA adapter
Core 0:       +43.0°C  (high = +82.0°C, crit = +100.0°C)
Core 1:       +43.0°C  (high = +82.0°C, crit = +100.0°C)
Core 2:       +43.0°C  (high = +82.0°C, crit = +100.0°C)
Core 3:       +40.0°C  (high = +82.0°C, crit = +100.0°C)

radeon-pci-0100
Adapter: PCI adapter
temp1:        +56.0°C  

atk0110-acpi-0
Adapter: ACPI interface
Vcore Voltage:       +1.13 V  (min =  +0.80 V, max =  +1.60 V)
 +3.3 Voltage:       +3.28 V  (min =  +2.97 V, max =  +3.63 V)
 +5 Voltage:         +5.14 V  (min =  +4.50 V, max =  +5.50 V)
 +12 Voltage:       +12.21 V  (min = +10.20 V, max = +13.80 V)
CPU FAN Speed:      2556 RPM  (min =  600 RPM, max = 7200 RPM)
CHASSIS1 FAN Speed:    0 RPM  (min =  600 RPM, max = 7200 RPM)
CHASSIS2 FAN Speed: 3515 RPM  (min =  600 RPM, max = 7200 RPM)
CHASSIS3 FAN Speed:    0 RPM  (min =  600 RPM, max = 7200 RPM)
POWER FAN Speed:       0 RPM  (min =  600 RPM, max = 7200 RPM)
CPU Temperature:     +27.0°C  (high = +60.0°C, crit = +95.0°C)
MB Temperature:      +45.0°C  (high = +45.0°C, crit = +95.0°C)
Por desgracia, en el resto de máquinas que tengo la información es mucho mas limitada.

El script que comprueba la temperatura de la VGA utiliza varios filtros y comandos para extraer a los datos. Su código es:
# cat /usr/local/bin/vgatemp.sh
#!/bin/bash

#ati radeon y nouveau se comprueban con "sensors"
#nvidia se comprueba con nvidia-smi
#intel no se puede monitorizar, no he encontrado herramienta
 
VGATEMP=0
if sensors | grep -q radeon-pci
then
  VGATEMP=$(sensors | sed -n '/radeon-pci/,/^$/p' | grep "^temp" | tr -d '+°C' | awk '{printf("%d\n",$2 + 0.5)}' | sort -nr | head -1)
else
   if sensors | grep -q nouveau-pci
   then
     VGATEMP=$(sensors | sed -n '/nouveau-pci/,/^$/p' | grep "^temp" | tr -d '+°C' | awk '{printf("%d\n",$2 + 0.5)}' | sort -nr | head -1)
   else
      if test -f /usr/bin/nvidia-smi
      then
        VGATEMP=$(nvidia-smi -q | grep "GPU Current Temp" | awk '{printf("%d\n",$5)}')
      fi
   fi

fi

#echo $VGATEMP # for debug only
exit $VGATEMP
El script que comprueba la temperatura de la placa base, según el hardware que usemos, sería:
# cat /usr/local/bin/mbtemp.sh
#!/bin/bash
hardware=$(facter hardware)
MBTEMP=0
case $hardware in
   "telefonica") MBTEMP=$(sensors |grep "^MB Temperature:"| awk '{printf $3}'  | tr -d '+°C'  | awk '{printf("%d\n",$1 + 0.5)}')
           ;;
   "siatic") MBTEMP=$(sensors | sed -n '/acpitz-virtual-0/,/^$/p' | grep "^temp" | tr -d '+°C' | awk '{printf("%d\n",$2 + 0.5)}' | sort -nr | head -1)
           ;;
   "infolab" ) MBTEMP=$(sensors | sed -n '/pch_skylake-virtual-0/,/^$/p' | grep "^temp" | tr -d '+°C' | awk '{printf("%d\n",$2 + 0.5)}' | sort -nr | head -1)
           ;;

   * ) MBTEMP=$(sensors | sed -n '/acpitz-virtual-0/,/^$/p' | grep "^temp" | tr -d '+°C' | awk '{printf("%d\n",$2 + 0.5)}' | sort -nr | head -1)

        ;;
esac
#echo $MBTEMP # for debug only
exit $MBTEMP
El script que obtiene la temperatura de todos los discos duros y devuelve la mayor entre ellas es:
# cat /usr/local/bin/hddtemp.sh
#!/bin/bash

HDDTEMP=0
DISCOS=$(lsblk  -l | grep disk | cut -f1 -d" ")
for i in $DISCOS
do
  TEMP=$(hddtemp  /dev/$i 2> /dev/null | tr -d "°C " | cut -d":" -f3)
  test -z "$TEMP" && TEMP="0"
  test "$TEMP" -gt "$HDDTEMP" && HDDTEMP="$TEMP"
done

#echo $HDDTEMP # for debug only
exit $HDDTEMP
El script que comprueba la temperatura de la CPU o sus cores y devuelve la mayor:
# cat /usr/local/bin/cputemp.sh
#!/bin/bash
hardware=$(facter hardware)
CPUTEMP=0
case $hardware in
   "telefonica") CPUTEMP=$(sensors |grep "^CPU Temperature"| awk '{printf $3}'  | tr -d '+°C'  | awk '{printf("%d\n",$1 + 0.5)}')
           ;;
   "siatic" | "infolab" ) CPUTEMP=$(sensors |grep "^Package id"| awk '{printf $4}'  | tr -d '+°C' | awk '{printf("%d\n",$1 + 0.5)}')
           ;;
   * )  CPUTEMP=$(sensors |grep "^Core "| tr -d '+°C' |  awk '{printf("%d\n",$3 + 0.5)}'  | sort -nr | head -1) #El mayor de los cores
        ;;
esac
#echo $CPUTEMP # for debug only
exit $CPUTEMP
En el caso del servidor del centro tenemos un HP Proliant que gracias al paquete hp-health nos permite acceder a más valores interesantes, como el estado de las dos fuentes de alimentación redundantes que tiene.
# cat /etc/monit/conf.d/monitrc.temperatura
check program mbtemperatura with path "/usr/local/bin/mbtemp.sh"
   if status > 60 then alert
   group temperature

check program cputemperature  with path "/usr/local/bin/cputemp.sh"
   if status > 60 then alert
   group temperature

check program hddtemperature with path "/usr/local/bin/hddtemp.sh"
   if status > 50 then alert
   group temperature

check program fanspeed with path "/usr/local/bin/fanspeed.sh"
   if status = 1 then alert
   group temperature

check program powersupply with path "/usr/local/bin/powersupply.sh"
   if status = 1 then alert
   group temperature
El script de chequeo de ambas fuentes de alimentación sería:
# cat /usr/local/bin/powersupply.sh
#!/bin/bash
fans=$(hplog -p | grep Normal | wc -l)
if [ $fans -ne 2 ] #Verificamos que ambas fuentes estén en estado "normal"
then
   salida=1
else
   salida=0
fi
#echo $salida # for debug only
exit $salida
El script de chequeo de los ventiladores (para el HP Proliant se usa hplog en lugar de sensors) sería:
# cat /usr/local/bin/fanspeed.sh
#!/bin/bash
fans=$(hplog -f | grep Normal | wc -l)
if [ $fans -ne 2 ] #Verificamos que ambos ventiladores estén en estado "normal"
then
   salida=1
else
   salida=0
fi
#echo $salida # for debug only
exit $salida
Nota: los valores de temperatura en monitrc.temperatura los he ido afinando con diversas pruebas a lo largo de 10 días, ya que no es raro que haya máximos puntuales sobre todo cuando se reproducen vídeos. Cada uno debe ir probando y cambiando valores hasta dar con el equilibrio óptimo que no te fría a mensajes y a la vez te alerte cuando algo empiece a ir mal.

Bueno, pues hasta aquí hemos llegado. Si nos salen nuevas cosas que comprobar haremos una tercera parte.

domingo, 14 de abril de 2019

Monitorizando los puestos del aula con monit (I)


Mi compañero Esteban ha publicado en su blog varios artículos muy interesantes sobre monit. Resumidamente: monit es un servicio que se encarga de monitorizar el sistema y asegurarse de que otros servicios funcionan y/o informarnos ante determinados eventos.

Aparte de usarlo en los servidores del centro también viene bien tenerlo en funcionamiento en los ordenadores de los profesores dentro del aula, ya que se ocupan de varias tareas críticas dentro del contexto de sus funciones y es recomendable tener asegurada y controlada su disponibilidad.

1. Configuración de alertas mediante correo.

Para que monit nos notifique cosas la opción más sencilla es que nos envíe correos electrónicos a través de una cuenta de Gmail. En mi caso ya tengo en el centro un servidor de correo postfix que redirige sus correos a través de la cuenta de Gmail, tal como conté en al apartado 2 de la entrada sobre la Gestión de Avisos del SAI usando nut, por lo que lo mas correcto es que los distintos servicios monit que hay por los pc del centro envíen sus alertas al servidor postfix y este a su vez lo reenvíe a través Gmail.

Para que el servidor postfix admita correos de cualquier PC de nuestra red hay que editar su fichero /etc/postfix/main.cf y añadir:
..
mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128 172.19.196.0/24
..
smtpd_client_restrictions = permit_mynetworks, reject
Siendo 172.19.196.0 mi red local y no olvidando reiniciar el servicio postfix después.

A continuación, en cada /etc/monit/monitrc añadimos:
.....
set mailserver 172.19.196.X port 25

set alert mi.correo@gmail.com not on {instance}

set mail-format { from: mi.correos@gmail.com
subject: $HOST - $SERVICE $EVENT a $DATE
message: Monit $ACTION $SERVICE a $DATE en $HOST, Descripcion: $DESCRIPTION.
}
Siendo 172.19.196.X el servidor donde está ejecutándose el servicio postfix en mi red y mi.correo@gmail.com la cuenta de correo Gmail usada para notificar las alertas. El "not on {instance}" es un filtro para que no nos envien correos de alerta cada vez que el servicio monit se enciende o se apaga, ya que son bastante molestos.

2. Monitorizando servicios básicos.

En los puestos de los profesores tengo como mínimo 2 servicios críticos: dhcp (para dar IP a los portátiles, thinclients o worskstations de alumnos) y tftp (para la imagen de arranque de thinclients).
# cat /etc/monit/conf.d/monit.dhcp
check process dhcpd matching "dhcpd"
  start program "/etc/init.d/isc-dhcp-server start"
  stop  program "/etc/init.d/isc-dhcp-server stop"
Y:
# cat /etc/monit/conf.d/monit.tftp
check process tftp matching "/usr/sbin/in.tftpd"
  start program "/etc/init.d/tftpd-hpa restart"  # El restart funciona mejor, porque a veces si no se hace stop luego no arranca.
  stop  program "/etc/init.d/tftpd-hpa stop"
De igual manera podemos ir añadiendo ficheros para monitorizar cualquier servicio que juzguemos imprescindible.

3. Monitorizando los puntos wifi.

Otro recurso crítico en las aulas son los puntos wifi para permitir la conexión de portátiles y dispositivos móviles. Por regla general están en la IP 192.168.0.1 de la red interna del aula:
# cat /etc/monit/conf.d/monit.puntowifi
check host punto-wifi  with address 192.168.0.1
      if failed icmp type echo count 5 with timeout 30 seconds then alert
De esta manera si hay algún problema con el punto wifi (bloqueo o desconexión de cables) nos llegará una alerta por correo.

4. Monitorizando la conexión de las pizarras digitales.

Esta es más divertida: las pizarras digitales se conectan por USB y a veces por accidente o por diabluras de los alumnos se desconecta el cable que las une al PC.
# cat /etc/monit/conf.d/monit.pizarra
check program pizarra with path /usr/local/bin/check_pizarra
    if status != 0 then alert
Evidentemente, para este caso no hay orden específica de monit, lo que tenemos es un script que busca la pizarra entre los dispositivos USB y devuelve 1 si no la encuentra.
# cat /usr/local/bin/check_pizarra
#!/bin/bash
# Devuelve 1 para avisar de desconexión, 0 si esá conectada o bien ya se avisó.

pizarra=$(lsusb -d 0b8c: ; lsusb -d 13ff:) # 0b8c:0069  0b8c:0001  13ff:0008 - Pizarras SmartBoard 480/640 y Galneo
if test -z "$pizarra"
then
     if ! test -f /var/cache/no-pizarra
     then
         retorno=1
         touch /var/cache/no-pizarra
     else
         retorno=0 # Ya se avisó, no necesario volver a hacerlo
     fi
else
      retorno=0
      rm -f /var/cache/no-pizarra  # Reconectada, se borra el testigo de aviso.
fi
exit $retorno
De esta manera se avisa de forma inmediata de cualquier desconexión, quedando registrado en el correo el momento en que sucedió por si necesitamos hacer indagaciones posteriores.

5. Monitorizando teclados y ratones.

Al igual que las pizarras digitales, los teclados y ratones en los puestos del profesor son causa de algún que otro problema. Ya traté este tema en otro artículo, pero ahora lo enfocaré para que la detección se haga desde monit:
# cat /etc/monit/conf.d/monit.kbmouse
check program teclado_raton with path /usr/local/bin/check_kb_mouse
    if status != 0 then alert
Siendo el script:
# cat /usr/local/bin/check_kb_mouse
#!/bin/bash

FICHERO=/var/cache/kbvigila

#En teclados Sweex USB, aparece mouse en devices, aun cuando no haya ratón 
#conectado. Con el filtro grep -v kbd eliminamos esas lineas, para que solo
#coja las corresponden a un ratón real.
raton=$(cat /proc/bus/input/devices  | grep -i mouse | grep -v kbd | grep Handlers| wc -l)

#En teclados RML, la cadena es "keykoard" en lugar de "keyboard"
teclado=$(cat /proc/bus/input/devices  | grep -i key[bk]oard | wc -l)

pizarra=$(lsusb -d 13ff:0008) # Pizarra Galneo
if test -n "$pizarra"
then
   #Las pizarras Galneo se identifican como ratón, asi que hay que decrementar el contador
   ((raton--))
fi

test $raton -eq 0  && hayraton="1" ||  hayraton="2"
test $teclado -eq 0 &&  hayteclado="1" || hayteclado="2"

#En hayXXX: Valor "1": no detectado. 
#           Valor "2": detectado. 

#Recupera el estado anterior de teclado y ratón.
if [ -f $FICHERO ]
then
   km_anterior=$(cat $FICHERO)
else
   km_anterior=""
fi
#Estado actual
km_actual="${hayteclado}${hayraton}"

#Si el estado teclado/raton ha cambiado respecto al estado anterior, devuelve 1
#para que haya una alerta
if  [ "$km_anterior" != "$km_actual" ]
then
   retorno=1
   #Guarda el estado actual para la siguiente comprobación.
   echo "${hayteclado}${hayraton}" > $FICHERO   
else
   retorno=0
fi
exit $retorno
Simplemente se comprueba el estado de conexión de teclado/ratón y se compara con el resultado de la comprobación anterior. Si ha variado algo se lanza un aviso.

6. Tarea puppet.

Todo esto lo distribuyo mediante una tarea puppet que aplicaría a las distintos pc de profesor que quiero monitorizar, siendo el init.pp de la tarea:
class  xubuntu18_monit {

        package { "monit": ensure =>installed }

        service { 'monit':
                ensure  => 'running',
                enable  => true,
                require => Package['monit'],
        }

        file { "monitrc":
                path => "/etc/monit/monitrc",
                owner => root, group => root, mode => 600,
                source => "puppet:///modules/xubuntu18_monit/monitrc",
                ensure => file,
                notify  => Service['monit'],  # Reinicia el servicio si el fichero cambia
                require => Package['monit'],
        }

        case $ies_isltsp {
                "si","yes","true" : {  #En los pc con thinclients hay serficio tftp
                        file { "monitrc-tftp":
                                path => "/etc/monit/conf.d/monitrc.tftp",
                                owner => root, group => root, mode => 600,
                                source => "puppet:///modules/xubuntu18_monit/monitrc.tftp",
                                ensure => file, notify  => Service['monit'], require => Package['monit'],
                        }
                }
                default: { 
                }
        }


        file { "monitrc-wifiap":
                path => "/etc/monit/conf.d/monitrc.wifiap",
                owner => root, group => root, mode => 600,
                source => "puppet:///modules/xubuntu18_monit/monitrc.wifiap",
                ensure => file, notify  => Service['monit'], require => Package['monit'],
        }

        file { "monitrc-pizarra":
                path => "/etc/monit/conf.d/monitrc.pizarra",
                owner => root, group => root, mode => 600,
                source => "puppet:///modules/xubuntu18_monit/monitrc.pizarra",
                ensure => file, notify  => Service['monit'], require => Package['monit'],
        }

        file { "pizarra":
                path => "/usr/local/bin/check_pizarra",
                owner => root, group => root, mode => 755,
                source => "puppet:///modules/xubuntu18_monit/check_pizarra",
        }

        file { "kb_mouse":
                path => "/usr/local/bin/check_kb_mouse",
                owner => root, group => root, mode => 755,
                source => "puppet:///modules/xubuntu18_monit/check_kb_mouse",
        }

}
7. Continuará...

Una vez montado el sistema lo seguiré ampliando con más scripts de monitorización de temperaturas de CPU, placa y GPU, espacio en disco, uso de CPU, estado de las fuentes de alimentación, etc. Lo iremos viendo en artículos sucesivos.


Llevamos unas semanas frenéticas para los espaciotrastornados. Podría hablar de:
  • Increíbles fotos de agujeros negros.


  • El éxito completo de la Falcon Heavy de Space con los tres cohetes reutilizados aterrizando suavemente en sus plataformas.


    ¡Eres grande, Elon Musk!

  • Próxima C: otro candidato a planeta rocoso a 4 años luz de nosotros.

Pero no, la imagen es un eclipse de sol desde la superficie Marte, al pasar las lunas Fobos/Deimos delante del astro rey. ¿Quién tomó esta maravillosa imagen? Mi admirada Opportunity:


Impresionante.