Monitorar status de computadores

O script a seguir permite monitorar uma lista de computadores (identificados por hostname e número de IP) através de algumas variáveis, como a conectividade, temperatura, tempo de funcionamento e uso de disco. Existem vários programas bem completos para monitoramento de máquinas, mas o objetivo desse é comprimir as principais informações de vários computadores em um arquivo com as informações obtidas no instante de consulta.

A rotina executa remotamente os comandos, e portanto precisa de acesso sem senha nos computadores. Isso pode ser feito gravando uma chave de segurança (recomendado) ou usando o comando “sshpass” (opção utilizada), que pode ser instalado pelo comando “sudo apt-get install sshpass”. Também deve ser instalado o programa “sensors”, para acessar as informações de temperatura, através do comando “sudo apt-get install lm-sensors”. Para saber a temperatura de uma Raspberry pi, o comando é “vcgencmd measure_temp”.

Feito em shell script, é feito um loop para todos os computadores para executar os seguintes comandos:

  • sensors ou vcgencmd measure_temp – obter temperatura (em °C) com o maior valor dentre todos os sensores (de núcleo e de gabinete); um “if” exclui as máquinas virtuais dessa análise
  • uptime – exibe o tempo de funcionamento do computador (em dias)
  • df – exibe a ocupação dos discos (no caso, em porcentagem e somente é selecionado o disco com maior ocupação)

A saída dos comandos é editada pelo comando “grep” para restringir linhas, “awk” para selecionar colunas, “sort” para ordenar os valores numericamente e “tail” para selecionar o maior valor. Os valores são salvos em uma variável e impressas (junto com o hostname) no arquivo de saída “status.txt” em formato CSV (colunas separadas por vírgula).

#!/bin/bash
# Script to monitor machine status

usr="USUARIO"
psw="SENHA"
hostnames=( "host1" "host2" "host3")
ips=( "192.168.0.1" "192.168.0.2" "192.168.0.3" )

i=0
echo "host,temp,uptime,hd,hd_health" > status.txt
for host in ${hostnames[@]}; do
	# Skip VM
	if [ "$host" == "host3" ]; then
		temperatura=$(sshpass -p $psw ssh [email protected]${ips[$i]} "sensors | grep °C | grep '^[^ ;]' | awk -F'°C' '{print \$1}' | awk -F'+' '{print \$NF}' | sort -n | tail -1")
		health_hd=$(sshpass -p $psw ssh [email protected]${ips[$i]} "tail -1 /home/locator/status_hd_smart.txt")
		# copy script (temporary)
		sshpass -p $psw scp check_hd.sh [email protected]${ips[$i]}:/home/$usr
	else
		temperatura=$(sshpass -p $psw ssh [email protected]${ips[$i]} "vcgencmd measure_temp | awk -F'=' '{print \$2}' | sed \"s/'C//\"")
		health_hd='NA'
	fi
	# Uptime
	up=$(sshpass -p $psw ssh [email protected]${ips[$i]} "uptime | awk -F',' '{print \$1}' | awk -F'up ' '{print \$2}'")
	# Less disponible disk
	df=$(sshpass -p $psw ssh [email protected]${ips[$i]} "df -h | awk -F'%' '{print \$1}' | awk -F' ' '{print \$NF}' | sort -n | tail -1")
	# Print info
	echo $host","$temperatura","$up","$df","$hd_health >> status.txt
	i=$((i+1))
done

Para verificar a saúde física dos HDs, é usado o comando “smartctl” – para instalá-lo e configurá-lo, visite o post Verificando a saúde do HD. Como ele só pode ser executado como super usuário, foi criado um script, a ser copiado para cada máquina (check_hd.sh) que deverá executar o smartctl com o parâmetro “–scan” para identificar todos os dispositivos, e então imprimir uma tabela de monitoramento (parâmetro “-A”) para cada um.

Essa tabela é filtrada para ler somente a coluna com a última data de falha – em especial os IDs “Reallocated_Sector_Ct” e “Seek_Error_Rate”, mas você pode ser menos restritivo. Se essa coluna não estiver só com traços, significa que houve alguma falha em algum momento. Nesse caso, em vez de simplesmente imprimir um 0 no final do relatório, vai imprimir 1 e também a tabela completa, assim como o histórico de auto-testes realizados.

No final, o script principal (status.sh) lê remotamente o arquivo gerado (status_hd_smart.txt) pelo script secundário (check_hd.sh) e pega somente a última linha, dizendo o stauts de “sem falhas” (0) ou “com alguma falha em algum dispositivo” (1). Veja o script secundário a seguir – ele deve constar do crontab do usuário root, conforme exemplo no comentário do início do próprio código:

#!/bin/bash
# Script to test HD health
#(crontab do root)
# 0 2 * * * /home/$user/check_hd.sh > /home/$user/status_hd_smart.txt 2>&1

hostname=$(cat /etc/hostname)
echo $hostname
check=0
for device in $(/usr/sbin/smartctl --scan | awk '{print $1}'); do
	echo $device
	if [ "$hostname" == "storage" ] && [ "$device" == "/dev/sda" ]; then
		for N in {1..12}; do
			string=$(/usr/sbin/smartctl -A -d megaraid,$N $device | awk '/Reallocated_Sector_Ct/ || /Seek_Error_Rate/ { print $9 }' | sed 's/-//g')
			if [ ${#string} -eq 0 ]; then
				echo $N "- OK"
			else
				echo $N "- not OK"
				/usr/sbin/smartctl -A -d megaraid,$N $device
				/usr/sbin/smartctl -l selftest -d megaraid,$N $device
				check=1
			fi
		done
	else
		string=$(/usr/sbin/smartctl -A $device | awk '/Reallocated_Sector_Ct/ || /Seek_Error_Rate/ { print $9 }' | sed 's/-//g')
		if [ ${#string} -eq 0 ]; then
			echo "OK"
		else
			echo "not OK"
			/usr/sbin/smartctl -A $device
			/usr/sbin/smartctl -l selftest $device
			check=1
		fi
	fi
done
echo $check

Atualização: foi incluído um “if” para considerar o caso de uma “storage” cujo dispositivo “/dev/sda” seja formado por um RAID (no caso, RAID10 com 12 HDs).

Em vez de gravar sobrescrevendo um único arquivo, é possível editar o script para criar um arquivo por dia e ir incluindo novas informações no fim do arquivo – e fazer um gráfico da evolução das variáveis analisadas. Em ambos os casos, é interessante incluir a execução desse script no crontab, para atualização de status após um intervalo de tempo. Para ficar mais completo, pode-se configurar para mandar um e-mail caso alguma variável atinja um valor crítico – veja mais no post Como enviar e-mails para vários destinatários.