Home.

Blog

Kmoser's Tech-Blog

Samstag
09
Dezember 2017

Temperaturüberwachung mit hddtemp und FHEM

Nachdem sich bei mir neulich eine Platte in meinem Server verabschiedet hatte und sie mir bei der Datenrettung doch etwas sehr heiß vorkam habe ich beschlossen die Festplattentemeraturen zukünftig besser im Auge zu behalten.

In den meißten Festplatten ist inzwischen ein Temperatursensor verbaut den man über geeignete Tools auslesen kann. Die verscheidenen Hausautomationslösungen, in meinem Fall FHEM, bieten sich an um hier die Überwachung durchzuführen und ggf. Maßnahmen zu ergreifen.

En geeingetes Tool um an die Temeraturen der Festplatten zu kommen ist hddtemp. Eine gute Anleitung gibt es wie immer im Wiki von ubuntuusers.de.

Auf dem Desktop verwende ich das Tool schon sein längerer Zeit um die Festplattentemperaturen mittels dem Plugin xfce4-sensors-plugin auf dem Desktop in der Statusleiste anzeigen zu lassen.

Man kann das Tool aber auch direkt als Serverdienst laufen lassen der auf Port 7634 die aktuellen Festplattentemperaturen ausgeben kann.

Installation

Die Installation erfolgt mit

Bash
sudo apt-get install hddtemp

Das Programm hddtemp als Benutzer ausführen

Soll hddtemp von einem normalen Benutzer ausgeführt werden können dann führt man

Bash
sudo dpkg-reconfigure hddtemp 

aus und wählt "Nein" bei der Frage "Soll hddtemp mit root-Rechten arbeiten?".

Temperatur abfragen

Die Temperatur einer Festplatte fragt man ab mit:

Bash
sudo hddtemp /dev/sda

Wenn die Festplatte erkannt wurde und einen Temperatursensor hat erfolgt eine Ausgabe wie die folgende:

/dev/sdb: ST4000DM005-2DP166: 33°C

Will man nur den numerischen Wert der Temperatur, z.B. um damit zu Rechnen oder in ein Integerfeld in einer Datenbank zu speichern kann man folgendes verwenden:

Bash
sudo hddtemp /dev/sdb -n

Jetzt sollte die Temperatur als Zahl ausgegeben werden

33

Als Dienst starten

Muss man wie ich die Festplatten von einem anderen Rechner aus überwachen besteht die Möglichkeit hddtemp als Serverdiest laufen zu lassen der dann Anfragen auf Port 7634 entgegen nimmt.

Um den Dienst einzurichten führt man wieder

Bash
sudo dpkg-reconfigure hddtemp 

aus und wählt bei "hddtemp als Dienst starten" als Antwort "Ja" aus. Unter "Port-Nummer" kann man ggf. noch den Port ändern falls man den Standard-Port nicht verwenden möchte.

Dienst testen

Um die Ausgabe zu testen kann man entweder telnet oder netcat verwenden.

Bash
# telnet
telnet localhost 7634

# netcat
nc localhost 7634

Es sollte eine Ausgabe wie die folgende erscheinen:

|/dev/sda|INTEL SSDSC2BB120G4|33|C||/dev/sdb|WDC WD30EFRX-68EUZN0|32|C|

Im Wiki von Archlinux habe ich eine Zeile gefunden welche eine etwas übersichtlichere Darstellung erzeugt:

Bash
nc localhost 7634 |sed 's/|//m' | sed 's/||/ \n/g' | awk -F'|' '{print $1 " " $3 " " $4}'

Die Ausgabe sieht dann so aus:

/dev/sda 33 C
/dev/sdb 32 C

Werte in FHEM loggen

Das Ausgeben der Werte bringt uns natürlich nichts wenn wir diese Werte nirgends auswerten.

Da bei mir FHEM läuft bietet es sich an die Auswertung und ggf. Reaktionen darüber laufen zu lassen.

Dummy anlegen

Als erstes benötigen wir einen Dummy in dem wir die Werte als Readings speichern können:

Fhem
define HddTempServer dummy

99_myUtils.pm erweitern

Im zweiten Schritt erstellen wir ein Perl Script in der 99_myUtils.pm, welches sich zum Hddtemp Dienst verbindet, die Daten abruft, aufbereitet und die Werte als Reading in dem Dummy speichert:

Perl
use IO::Socket::INET;
use List::Util qw( min max );

sub
GetHddTempServer($$)
{
	my ($dummy,$host) = @_;

	my $socket = new IO::Socket::INET (
		PeerAddr => $host,
		PeerPort => '7634',
		Proto => 'tcp',
		#Blocking => 0,
		Timeout => 2
	);

	if (! $socket) {
		Log 1,"HddTemp: ERROR in socket creation : $! \n";
		return;
	}

	#Log 1,"HddTemp: TCP connection successfully established.\n";

	# Get data from socket
	$socket->recv(my $rawData, 1024);

	# Exit if no data
	if ($rawData eq "") {
		Log 1,"HddTemp: Error: Got no data. Data: $rawData. Error: $!";
		return;
	}

	# Split string
	my @diskStrings = split(/\|\|/, $rawData);
	my $diskString;
	my @temperatures = ();

	foreach $diskString (@diskStrings) {

		# Trim lines
		$diskString =~ s/^\|+|\|+$//g;

		# Split values
		my @values = split(/\|/, $diskString);

		# Split device name values
		my @dev = split(/\//, @values[0]);

		fhem("setreading $dummy hdd_@dev[2]_device $values[0]");
		fhem("setreading $dummy hdd_@dev[2]_temperature $values[2]");
		fhem("setreading $dummy hdd_@dev[2]_model $values[1]");
		fhem("setreading $dummy hdd_@dev[2]_unit $values[3]");

		push(@temperatures, $values[2]);
	}

	my $maxValue = max @temperatures;
	fhem("setreading $dummy max_value $maxValue");

	# Debug
	#Log 1, "HddTemp: Data received from server : $rawData\n";
}

Cronjob anlegen

Dieses Script wird jetzt per at cron Job alle 10 Minuten aufgerufen.

Fhem
define HddTempServerCron at +*00:10:00 { GetHddTempServer("HddTempServer", "192.168.0.123") }
attr HddTempServerCron alignTime 00:10

Jetzt sollte man nach der Ausführung des Scripts im Dummy HddTempServer die entsprechenden Readings finden.

Man kann jetzt noch den State des Dummies setzen damit man in der Übersicht alle relevanten Temeraturen angezeigt bekommt ohne den Dummy öffnen zu müssen:

Fhem
attr HddTempServer stateFormat sda: hdd_sda_temperature °C, sdb: hdd_sdb_temperature °C, sdc: hdd_sdc_temperature °C

In der Übersicht sieht der Dummy dann so aus:

FileLog einrichten

Um Werte über Zeit zu bekommen, richten wir noch ein FileLog ein damit wir später einen schönen SVG Graphen zeichnen können:

Fhem
define FileLog_HddTemp_Server FileLog /opt/fhem/log/HddTemp_Server-%Y.log HddTempServer
attr FileLog_HddTemp_Server icon time_note
attr FileLog_HddTemp_Server logtype text
attr FileLog_HddTemp_Server room 9.9 Logs

Den Graphen richtet man dann innerhalb des FileLog Eintrags ein. Das sieht dann nach einer Weile (wenn genügend Log-Einträge da sind) so aus:

Alarm

Damit wir im Falle eines Falles rechtzeitig reagieren können brauchen wir noch eine Benachrichtigung falls eine der Platten zu heiß wird. Dazu könne man sich eine E-Mail schicken eine Warnleuchte einschalten oder sich eine Push-Nachricht auf das Handy schicken.

Ich werde letzteres machen. Um sich eine Nachricht auf das Handy schicken zu können benötigt man einen Service der dieses zur Verfügung stellt. Für diese Zwecke verwende ich Pushbullet. Habe bisher noch keine Probleme mit dem Service gehabt und er ist auch noch kostenlos. Die Einrichtung des Services in Fhem ist im Fhem Wiki gut erklärt.

Für den Alarm benötigen wir einen Dummy und einen Notify. Der Dummy zeigt und speichert den Alarm-Status sowie den Schwellenwert ab dem ein Alarm ausgelöst werden soll.

Zuerst legen wir den Dummy an:

Fhem
define HddTempServerAlarm dummy
attr HddTempServerAlarm webCmd on:off
attr HddTempServerAlarm room 1.3 Buero

Nun setzen wir den Schwellenwert als Reading und schalten das Alarmsignal aus:

Fhem
setreading HddTempServerAlarm threshold 45
set HddTempServerAlarm off

Als nächstes wird der Notify erzeugt der jedes Mal wenn sich ein Wert in dem Dummy HddTempServer ändert prüfen soll ob der Wert über dem eingestellten Schwellenwert liegt und sofern nicht schon Alarm ausgelöst wurde, eine Push-Nachricht absenden soll.

Fhem
define HddTempServer_notify notify HddTempServer:.*temperature:.* {

	my $threshold = ReadingsVal("HddTempServerAlarm", "threshold", "50");

	if ($EVTPART1 > $threshold) {
		if (ReadingsVal("HddTempServerAlarm", "state", "") == 'off') {
			fhem('set HddTempServerAlarm on');
			fhem("set Pushbullet message Festplattentemperatur im Server kritisch: $threshold °C | FHEM");
		}
	} else {
		fhem('set HddTempServerAlarm off');
	}
}

Anstatt der Meldung über Pushbullet kann man natürlich jede beliebige andere Aktion ausführen. Wie man z.B. eine E-Mail schickt ist im FHEM Wiki erklärt.

Ich hoffe dass ich jetzt beim nächsten anstehenden Hitzetod einer meiner Festplatten im Server vorher Bescheid bekomme.