Smart-Monitoring Alternative
Da war dann noch offen, wie mal mehrere Platten über eine Grafikanzeige überwachen kann. Ich hab das ohne tps und dafür mit Google-Charts realisiert. Voraussetzung bleibt weiterhin der Einsatz von
smartctl.
(1) Ein Datensammler-Skript
/usr/sbin/diskstatsd für die CronTab:
Rich (BBCode):
[ "$1" == "" ] || exit 1
NOW=$(/usr/sbin/smartctl -d marvell -A /dev/hda | awk '/^194/{t1=$10}/^ 9/{t2=$10}/^ 4/{t3=$10}/^ 12/{t4=$10}/^ 5/{t5=$10}END{printf("%d %d %d %d %d\n",t1,t2,t3,t4,t5)}')
date "+%m %d %H %M $NOW" >>/var/log/hdastats
NOW=$(/usr/sbin/smartctl -d marvell -A /dev/hdb | awk '/^194/{t1=$10}/^ 9/{t2=$10}/^ 4/{t3=$10}/^ 12/{t4=$10}/^ 5/{t5=$10}END{printf("%d %d %d %d %d\n",t1,t2,t3,t4,t5)}')
date "+%m %d %H %M $NOW" >>/var/log/hdbstats
Die beiden Zeilen für die beiden Platten lassen sich für weitere Platten erweitern. Der
awk sucht die folgenden Zeilen:
Rich (BBCode):
ID# ATTRIBUTE_NAME FLAG VALUE WORST THRESH TYPE UPDATED WHEN_FAILED RAW_VALUE
4 Start_Stop_Count 0x0032 100 100 020 Old_age Always - 273
5 Reallocated_Sector_Ct 0x0033 100 100 036 Pre-fail Always - 1
9 Power_On_Hours 0x0032 100 100 000 Old_age Always - 330
12 Power_Cycle_Count 0x0032 100 100 020 Old_age Always - 47
194 Temperature_Celsius 0x0022 034 040 000 Old_age Always - 34 (0 21 0 0)
Wenn die Zeilen andere Nummern haben, dann einfach im Skript abändern.
(2) In der
/etc/crontab wirds aufgerufen:
Rich (BBCode):
0,15,30,45,59 7-23 * * * root /bin/sh /usr/sbin/diskstatsd
Die Ergebnisse werden pro Platte gesammelt im Verzeichnis
/var/log/hd?stats (? steht für a, b, usw). Wenn die Logfiles anders heissen sollen, dann einfach im Skript (1) oben abändern.
(3) Ein Auswertungs-Skript namens
/usr/sbin/diskstats:
Rich (BBCode):
f=${1:-hda}
</var/log/${f}stats awk "/^$GET/{v1+=\$5;c++;v2=\$6;v5=\$9;
if(v1min==0) v1min=\$5; else if(v1min>\$5) v1min=\$5;
if(v1max==0) v1max=\$5; else if(v1max<\$5) v1max=\$5;
if(v3==0||\$7<v3)v3=\$7;else v3delta+=\$7-v3;
if(v4==0||\$8<v4)v4=\$8;else v4delta+=\$8-v4;
}
{v3=\$7;v4=\$8;}
END{if(v1>0)printf(\"%03.1f°C %03.1f°C %03.1f°C %5d h %5d cycles %5d cycles %4d sectors\n\",
v1/c,v1min,v1max,v2,v3delta-v4delta,v4delta,v5);else printf(\"\n\")}"
(4) Eine 3rd-party-Apps namens
/usr/syno/synoman/phpsrc/diskhealth/diskhealth.cgi (falls jemand die andere Lösung schon eingesetzt hatte, diese vorher umbenennen):
Rich (BBCode):
#!/bin/ash
export GET
cat <<EOT
Content-type: text/html
<html><head><title>System-Info</title></head><body style="width:750px">
<style>body{font:11px Arial;background-color:#ddf;}</style>
$(/usr/sbin/diskstatsd)
<div style="font:11px monospace;position:absolute;top:11px;left:27px;z-index:5">
<span style="color:#333333">?
</span>/dev/hda actual Temperature $(</var/log/hdastats tail -1|awk '{print $5}')°C
<span style="color:#666666">?</span>
/dev/hdb actual Temperature $(</var/log/hdbstats tail -1|awk '{print $5}')°C</div>
<div style="padding-top:142px;padding-left:1px;line-height:10px"><pre>
Aver. Mini Maxi Lifetime Hibernate Power on/off Reallocated
hda $(/usr/sbin/diskstats hda|awk '{printf("%s",$1)}';/usr/sbin/smartctl -d marvell -A /dev/hda | awk '/^194/{t1=$10}/^190/{t6=substr($13,1,2),t7=substr($13,4,2)}
/^ 9/{t2=$10}/^ 4/{t3=$10}/^ 12/{t4=$10}/^ 5/{t5=$10}
END{printf(" %2d.0°C %2d.0°C %7d h %5d cycles %6d cycles %4d sectors\n",t6,t7,t2,t3-t4,t4,t5)}')
hdb $(/usr/sbin/diskstats hdb|awk '{printf("%s",$1)}';/usr/sbin/smartctl -d marvell -A /dev/hdb | awk '/^194/{t1=$10}/^190/{t6=substr($13,1,2),t7=substr($13,4,2)}
/^ 9/{t2=$10}/^ 4/{t3=$10}/^ 12/{t4=$10}/^ 5/{t5=$10}
END{printf(" %2d.0°C %2d.0°C %7d h %5d cycles %6d cycles %4d sectors\n",t6,t7,t2,t3-t4,t4,t5)}')
EOT
year=$(date "+%Y")
month=$(date "+%m")
day=$(date "+%d"); day1=`expr $day - 1`;
hour=$(date "+%H"); hour1=`expr $hour + 1`;
T1="";T2="";L="";
G=`date -d"$month${day1}0000$year" "+%m %d "`;for t in $(seq $hour1 23);do
t=$(printf %02d $t);GET=$G$t;if [ "$L" == "" ] ;then L=$t; else L=$L'|'$t; fi
T=$(/usr/sbin/diskstats hda); if [ "$T" == "" ] ;then S=0; else S=`echo $T|sed 's/\(..\).\(.\).*/\1\2/'`; fi
if [ "$T1" == "" ] ;then T1=$S; else T1=$T1,$S; fi
if [ "$T" != "" ] ;then echo "$t: $T"; fi
T=$(/usr/sbin/diskstats hdb); if [ "$T" == "" ] ;then S=0; else S=`echo $T|sed 's/\(..\).\(.\).*/\1\2/'`; fi
if [ "$T2" == "" ] ;then T2=$S; else T2=$T2,$S; fi
if [ "$T" != "" ] ;then echo " $T"; fi
done
G=`date "+%m %d "`;for t in $(seq 00 $hour);do
t=$(printf %02d $t);GET=$G$t;if [ "$L" == "" ] ;then L=$t; else L=$L'|'$t; fi
T=$(/usr/sbin/diskstats hda); if [ "$T" == "" ] ;then S=0; else S=`echo $T|sed 's/\(..\).\(.\).*/\1\2/'`; fi
if [ "$T1" == "" ] ;then T1=$S; else T1=$T1,$S; fi
if [ "$T" != "" ] ;then echo "$t: $T"; fi
T=$(/usr/sbin/diskstats hdb); if [ "$T" == "" ] ;then S=0; else S=`echo $T|sed 's/\(..\).\(.\).*/\1\2/'`; fi
if [ "$T2" == "" ] ;then T2=$S; else T2=$T2,$S; fi
if [ "$T" != "" ] ;then echo " $T"; fi
done
cat <<EOT
</pre>
</div>
<img style="position:absolute;top:2px;margin-left:-2px"
src="http://chart.apis.google.com/chart?cht=bvg&chds=200,500&&chbh=11,0,0
&chf=c,lg,90,dd0000,1,ffff77,0|bg,s,efefef00&chg=8.33,33.33&chco=333333,666666&chs=680x150
&chxt=x,r&chxl=0:|$L|1:|20|30|40|50
&chd=t:$T1|$T2">
EOT
for d in $(ls /dev/hd?); do
cat <<EOT
<hr><h3>$d</h3>
<pre>$(/opt/sbin/smartctl -d marvell -iAH $d|sed '1,3d')</pre>
EOT
done
cat <<EOT
</body></html>
EOT
Auch hier sieht man zwei Platteneinträge, die problemlos erweitert werden könnten. Die beiden roten Zahlen beeinflussen die Breite der Grafik bzw. die Breite der Balken, da kann man mit spielen.
Die beiden schwarzen Blöcken sind eigentlich folgenden Zeichen (bitte ersetzen): & #9606; (ich hab mal eine Leestelle dazwischen gesetzt, damit der Code auch angezeigt wird. Die Leerstelle muss natürlich dann entfernt werden.
Daran denken, die Datei mit
chmod 755 ausführbar zu machen.
(5) Wenn man die Smarttool-Geschichte schon hatte, läuft es jetzt. Wenn nicht, dann noch im Verzeichnis
/usr/syno/synoman/webman/3rdparty ein Verzeichnis namens
diskhealth erstellen. In dieses Verzeichnis eine Datei namens
application.cfg erfassen:
Rich (BBCode):
text = diskhealth
description = diskhealth
type = embedded
path = /phpsrc/diskhealth/diskhealth.cgi
Anmerkungen:
Die Hibernate-Cycles sind die Start/Stop-Counts minus Power-on/off-Counts, was so ungefähr mit der Hibernate-Anzahl übereinstimmen würde. Wir alle wissen, dass es nicht wirklich Hibernates sind, sondern nur das Plattenruhen
.
In jedem Fall sind die Start/Stop-Zyklen ein wichtiger Parameter für die Platten-Haltbarkeit (<50.000 meist). Daneben ist auch der Reallocate-Zähler ein Indiz für die Güte der Platte. Wenn dieser Wert ansteigt, dann verliert die Platte ihre Selbstheilungskraft - sind ja so etwas wie Ersatz-Sektoren.
Die Balken in der Grafik repräsentieren gemittelte Stunden-Werte, der Text in der Grafik liest den aktuellen Wert aus (höchsten 10 Sekunden alt). Die Legende der x-Achse sind Uhrzeiten, der y-Achse °C. Die beiden Zeilen unterhalb der Grafik sind die Total-Werte der Platten, danach kommen gemittelte, minimalen und maximalen Stundenwerte bei den Temperaturen bzw. die Differenzwerte bei den cycles zwischen zwei Stunden-Intervallen. Die Werte werden für die letzten 24 Stunden berechnet - liegen keine Messergebnisse vor, wird nicht angezeigt (z.B. Ruhezeiten in der Nacht). Da jeder SMART-Auslesevorgang auch den spin-down der Platte unterbricht, macht es Sinn, in der Nacht nicht zu messen. Ich habe die Intervalle auf ca 15 Minuten für die Messung gesetzt (siehe /etc/crontab (2)) und meine Ruhezustands-Eintragung ist 15 Minuten (da 10 Minuten bei einigen Modellen wohl zu Problemen führt, macht das so Sinn).
Wie immer der Hinweis, dass alles auf eigene Kappe geht.