Hardware Monitoring

Aus wiki.frank-wulf.de
Zur Navigation springen Zur Suche springen

Shell script /usr/bin/fwsysmon

#!/bin/bash
#
# Author:  Frank Wulf
# Version: 1.5 (2024-10-17)
#
# This program detects the following system values and writes
# them into a database:
# - Temperatures of room, mainboard, CPU and hard disks
# - Status of hard disks (active or sleeping)
# - Fan speeds
# - System load
# - Power consumption
#
# Version history:
# 1.0   2017-10-04   Initial release
# 1.1   2018-09-07   Replaced pcsensor program with newer version
# 1.2   2019-04-20   Changed logic to build the SQL command
# 1.3   2020-04-20   Changed logic for process list and building comment
# 1.4   2020-10-17   Replaced USB temperature sensor with smart plug sensor
# 1.5   2024-10-17   Add power consumption of server

## Offset for room temperature sensor (value will be subtracted from Celsius)
#calib=2

# Minimum percentage of CPU usage for processes shown in comment field
tmin=10

# Determine load average for last 1, 5 and 15 minutes
i=0
for loadavg in `cat /proc/loadavg`; do
  let i+=1
  if [ $i -le 3 ]; then load[$i]=$loadavg; fi
done

# Build comment field with processes reaching minimum percentage
i=0
while read process; do
  let i+=1
  tpcnt[$i]=`echo "$process"|awk '{printf $9}'`
  tproc[$i]=`echo "$process"|awk '{printf $12}'`
  if (( $(echo "${tpcnt[$i]} >= $tmin" | bc -l) )); then
    if [ $i -eq 1 ]; then
      comment="${tpcnt[$i]}%=${tproc[$i]}"
    else
      comment="${comment}; ${tpcnt[$i]}%=${tproc[$i]}"
    fi
  else
    break
  fi
done <<<`top -b -n 1|grep -v "top$"|sed '1,7d'|sed '5,$d'`

# Get status and temperatures of hard disks
i=0
while read temp; do
  let i+=1
  if `echo $temp|grep -qv "sleeping"`; then
    status_hdd[$i]="Active"
    temp_hdd[$i]=`echo $temp|cut -c1-2`
  else
    status_hdd[$i]="Sleeping"
    temp_hdd[$i]=0
  fi
done <<<`hddtemp /dev/sd? 2>&1|grep "^/dev"|grep -v "sda"|sort|cut -d: -f3|cut -c2-`

while [ $i -lt 5 ]; do
    let i+=1
    status_hdd[$i]="Not available"
    temp_hdd[$i]=0
done

# Get system temperatures and fan speeds
while read line; do
  case `echo $line|cut -d: -f1` in
    "SYSTIN") temp_sys=`echo "$line"|cut -c26-29`;;
    "CPUTIN") temp_cpu_ext=`echo "$line"|cut -c26-29`;;
    "Package id 0") temp_cpu_int=`echo "$line"|cut -c17-20`;;
    "Core 0") temp_core0=`echo "$line"|cut -c17-20`;;
    "Core 1") temp_core1=`echo "$line"|cut -c17-20`;;
    "Core 2") temp_core2=`echo "$line"|cut -c17-20`;;
    "Core 3") temp_core3=`echo "$line"|cut -c17-20`;;
    # The sequence of the fans provided by "sensors" is different
    # to the sequence in the database.
    "fan1") speed_fan4=`echo "$line"|cut -c24-28`;;
    "fan2") speed_fan1=`echo "$line"|cut -c24-28`;;
    "fan3") speed_fan2=`echo "$line"|cut -c24-28`;;
    "fan4") speed_fan3=`echo "$line"|cut -c24-28`;;
    "fan5") speed_fan5=`echo "$line"|cut -c24-28`;;
  esac
done <<<`sensors -A nct6791-isa-0290 coretemp-isa-0000`

# Get actual power consumption from smart plug
power=`iobroker state getvalue fritzdect.0.DECT_116300171650.power`

# Get room temperature (up to 5 attempts)
temp_room='0'
#for i in {1..5}
#do
#  temp_room=`pcsensor -s$calib`
#  if [ "$temp_room" == "" ]; then
#    # Wait five seconds and try again
#    sleep 5
#  else
#    break
#  fi
#done
temp_room=`iobroker state getvalue fritzdect.0.DECT_116300171650.celsius`

# Fill timestamp field
timestamp=`date +'%Y-%m-%d %H:%M:%S'`

# Insert data into database
sql="INSERT INTO fw_values (timestamp,temp_room,temp_sys,temp_cpu_ext,"
sql+="temp_cpu_int,temp_core0,temp_core1,temp_core2,temp_core3,"
sql+="status_hdd1,status_hdd2,status_hdd3,status_hdd4,status_hdd5,"
sql+="temp_hdd1,temp_hdd2,temp_hdd3,temp_hdd4,temp_hdd5,"
sql+="speed_fan1,speed_fan2,speed_fan3,speed_fan4,speed_fan5,"
sql+="load01,load05,load15,power,comment) VALUES ("
sql+="\"$timestamp\", \"$temp_room\", \"$temp_sys\", \"$temp_cpu_ext\", "
sql+="\"$temp_cpu_int\", \"$temp_core0\", \"$temp_core1\", \"$temp_core2\", "
sql+="\"$temp_core3\", \"${status_hdd[1]}\", \"${status_hdd[2]}\", "
sql+="\"${status_hdd[3]}\", \"${status_hdd[4]}\", \"${status_hdd[5]}\", "
sql+="\"${temp_hdd[1]}\", \"${temp_hdd[2]}\", \"${temp_hdd[3]}\", "
sql+="\"${temp_hdd[4]}\", \"${temp_hdd[5]}\", "
sql+="\"$speed_fan1\", \"$speed_fan2\", \"$speed_fan3\", "
sql+="\"$speed_fan4\", \"$speed_fan5\", "
sql+="\"${load[1]}\", \"${load[2]}\", \"${load[3]}\", "
sql+="\"$power\", \"$comment\")"

mysql --login-path=fwsysmon -D fwsysmon -e "$sql"

Notes

By default the Linux kernel claims the TEMPer device as a keyboard (HID device). When that happens, the program pcsensor is not able to set the configuration and communicate with it.

An error occurs and is shown in logfile /var/log/kern.log:

usbfs: USBDEVFS_CONTROL failed cmd pcsensor rqt 128 rq 6 len 255 ret -71

To prevent this we have to add a kernel parameter in /etc/default/grub:

#>>>2019-04-19 Frank Wulf
#GRUB_CMDLINE_LINUX_DEFAULT=""
GRUB_CMDLINE_LINUX_DEFAULT="usbhid.quirks=0x0c45:0x7401:0x4"
#<<<2019-04-19 Frank Wulf