ファイルサーバを新しくしました。 SNMP(bsnmpd)経由でHDDの温度取得編
Posted on 2015/09/01(Tue) 01:05 in technical
今日のお話
つい最近、ファイルサーバを新しくした のですけど、
当然HDDの温度をSNMPで取得できるようにしたいと思うわけで、FreeBSDに標準搭載されているbsnmpdを使ってそれを実現しようと思います。
smartmontoolsのインストール
何にしても、まずはS.M.A.R.Tを取得できるようにしないといけないので、smartctl(が入ってるsmartmontools)をインストールします。:
# pkg install smartmontools
S.M.A.R.Tが有効になっていない場合は、有効にしつつ情報が取得できることを確認しておきます。:
# smartctl -s on /dev/ada0 # smartctl -i /dev/ada0 smartctl 6.4 2015-06-04 r4109 [FreeBSD 10.2-RELEASE amd64] (local build) Copyright (C) 2002-15, Bruce Allen, Christian Franke, www.smartmontools.org === START OF INFORMATION SECTION === Model Family: JMicron based SSDs Device Model: ADATA SP600 Serial Number: 7E1920004364 LU WWN Device Id: 5 707c18 00004cff0 Firmware Version: 3.04 User Capacity: 64,023,257,088 bytes [64.0 GB] Sector Size: 512 bytes logical/physical Rotation Rate: Solid State Device Form Factor: < 1.8 inches Device is: In smartctl database [for details use: -P show] ATA Version is: ACS-2 (minor revision not indicated) SATA Version is: SATA 3.1, 6.0 Gb/s (current: 6.0 Gb/s) Local Time is: Sun Aug 23 22:14:59 2015 JST SMART support is: Available - device has SMART capability. SMART support is: Enabled
bsnmpdのインストール
最初から入っているので不要です。
bsnmp-ucdのインストール
net-snmpdで言うところのexecを実行するには、bsnmp-ucdが必要になるので、それを入れます。:
# pkg install bsnmp-ucd
S.M.A.R.T.値の自動取得スクリプトと独自OIDの生成
次に、ユーザ独自に定義したOIDでS.M.A.R.T.情報が取得できるように適当なスクリプトを書きます。
#!/bin/sh
TMP_DIR="/tmp/snmp_smart"
mkdir -p ${TMP_DIR}
BSNMPD_CONFIG="/etc/snmp_smartctl.config"
echo "# Auto generate: smartctl -A" > ${BSNMPD_CONFIG}
echo "# ------------------------------------------" >> ${BSNMPD_CONFIG}
echo "# extTable OIDs:" >> ${BSNMPD_CONFIG}
echo "# 1.3.6.1.4.1.2021.8.1.1 : extIndex" >> ${BSNMPD_CONFIG}
echo "# 1.3.6.1.4.1.2021.8.1.2 : extNames" >> ${BSNMPD_CONFIG}
echo "# 1.3.6.1.4.1.2021.8.1.3 : extCommand" >> ${BSNMPD_CONFIG}
echo "# 1.3.6.1.4.1.2021.8.1.100 : extResult" >> ${BSNMPD_CONFIG}
echo "# 1.3.6.1.4.1.2021.8.1.101 : extOutput" >> ${BSNMPD_CONFIG}
echo "# 1.3.6.1.4.1.2021.8.1.102 : extErrFix" >> ${BSNMPD_CONFIG}
echo "# 1.3.6.1.4.1.2021.8.1.103 : extErrFixCmd" >> ${BSNMPD_CONFIG}
echo "# ------------------------------------------" >> ${BSNMPD_CONFIG}
count=1
for dev in `ls /dev/ | grep -E -e "^ada[0-9]+\>" -e "^da[0-9]+\>"`; do
DEV_VALUE_FILE="${TMP_DIR}/${dev}_smart.txt"
echo "# Auto generate: smartctl -A /dev/$dev" > ${DEV_VALUE_FILE}
data=`/usr/local/sbin/smartctl -A /dev/$dev | awk '/0x00/ {print $1,$2,$10}'`
IFS_OLD=${IFS}
IFS=$'\n'
for line in $data; do
echo ${line} >> ${DEV_VALUE_FILE}
OID=`echo $line | cut -d " " -f 1`
NAME=`echo $line | cut -d " " -f 2`
VALUE=`echo $line | cut -d " " -f 3`
echo "extNames.${count} = \"SMART_${OID}_${NAME}_${dev}\"" >> ${BSNMPD_CONFIG}
echo "extCommand.${count} = \"grep ${NAME} ${DEV_VALUE_FILE} | cut -d ' ' -f 3\"" >> ${BSNMPD_CONFIG}
count=$((count+1))
done
IFS=${IFS_OLD}
done
bsnmpdに読み込ませて動かす
さっき書いたスクリプトをこんな感じで置いて、とりあえず一度実行しておくと、スーパー力技コマンド群が生成されます。:
# chmod 700 /usr/local/etc/snmp_smartctl.sh # /usr/local/etc/snmp_smartctl.sh # head -40 /etc/snmp_smartctl.config # Auto generate: smartctl -A # ------------------------------------------ # extTable OIDs: # 1.3.6.1.4.1.2021.8.1.1 : extIndex # 1.3.6.1.4.1.2021.8.1.2 : extNames # 1.3.6.1.4.1.2021.8.1.3 : extCommand # 1.3.6.1.4.1.2021.8.1.100 : extResult # 1.3.6.1.4.1.2021.8.1.101 : extOutput # 1.3.6.1.4.1.2021.8.1.102 : extErrFix # 1.3.6.1.4.1.2021.8.1.103 : extErrFixCmd # ------------------------------------------ extNames.1 = "SMART_1_Raw_Read_Error_Rate_ada0" extCommand.1 = "grep Raw_Read_Error_Rate /tmp/snmp_smart/ada0_smart.txt | cut -d ' ' -f 3" extNames.2 = "SMART_2_Throughput_Performance_ada0" extCommand.2 = "grep Throughput_Performance /tmp/snmp_smart/ada0_smart.txt | cut -d ' ' -f 3" extNames.3 = "SMART_3_Unknown_JMF_Attribute_ada0" extCommand.3 = "grep Unknown_JMF_Attribute /tmp/snmp_smart/ada0_smart.txt | cut -d ' ' -f 3" extNames.4 = "SMART_5_Reallocated_Sector_Ct_ada0" extCommand.4 = "grep Reallocated_Sector_Ct /tmp/snmp_smart/ada0_smart.txt | cut -d ' ' -f 3" extNames.5 = "SMART_7_Unknown_JMF_Attribute_ada0" extCommand.5 = "grep Unknown_JMF_Attribute /tmp/snmp_smart/ada0_smart.txt | cut -d ' ' -f 3" extNames.6 = "SMART_8_Unknown_JMF_Attribute_ada0" extCommand.6 = "grep Unknown_JMF_Attribute /tmp/snmp_smart/ada0_smart.txt | cut -d ' ' -f 3" extNames.7 = "SMART_9_Power_On_Hours_ada0" extCommand.7 = "grep Power_On_Hours /tmp/snmp_smart/ada0_smart.txt | cut -d ' ' -f 3" extNames.8 = "SMART_10_Unknown_JMF_Attribute_ada0" extCommand.8 = "grep Unknown_JMF_Attribute /tmp/snmp_smart/ada0_smart.txt | cut -d ' ' -f 3" extNames.9 = "SMART_12_Power_Cycle_Count_ada0" extCommand.9 = "grep Power_Cycle_Count /tmp/snmp_smart/ada0_smart.txt | cut -d ' ' -f 3" extNames.10 = "SMART_167_Unknown_JMF_Attribute_ada0" extCommand.10 = "grep Unknown_JMF_Attribute /tmp/snmp_smart/ada0_smart.txt | cut -d ' ' -f 3" extNames.11 = "SMART_168_SATA_Phy_Error_Count_ada0" extCommand.11 = "grep SATA_Phy_Error_Count /tmp/snmp_smart/ada0_smart.txt | cut -d ' ' -f 3" extNames.12 = "SMART_169_Unknown_JMF_Attribute_ada0" extCommand.12 = "grep Unknown_JMF_Attribute /tmp/snmp_smart/ada0_smart.txt | cut -d ' ' -f 3" extNames.13 = "SMART_170_Bad_Block_Count_ada0" extCommand.13 = "grep Bad_Block_Count /tmp/snmp_smart/ada0_smart.txt | cut -d ' ' -f 3" extNames.14 = "SMART_173_Erase_Count_ada0" extCommand.14 = "grep Erase_Count /tmp/snmp_smart/ada0_smart.txt | cut -d ' ' -f 3"
通報
記述の方法は extNames.XXX となるが、子要素は作れないようだ。つまり extNames.X.YYY とは書けない。
しかし、連番である必要はないので、例えば S.M.A.R.T. に関するOIDは1000番台(extNames.1XXX)、ZFSに関するOIDは2000番台(extNames.2XXX)などのように使い分けることは出来る。
デフォルトのconfigに少し手を入れて起動します。:
# echo 'begemotSnmpdModulePath."ucd" = "/usr/local/lib/snmp_ucd.so"' >> /etc/snmpd.config # echo '%ucd' >> /etc/snmpd.config # echo '.include "/etc/snmp_smartctl.config"' >> /etc/snmpd.config # sysrc bsnmpd_enable="YES" # service bsnmpd start
ちゃんと起動してきたら、ひとまず先へ進もう。
bsnmpdから値を取得できるようになるまで
さて、すぐにSNMP Getして値を確認。したいのは山々だが、少し待つ必要がある。
net-snmpdのexecやextendで設定したコマンドは「SNMPで取得しようとした時に実行される」のだが、bsnmpdはどうやらポーリング実行のようだ。
実行間隔については bsnmp-ucd(8) に記載されている:
updateInterval Statistics update interval, in ticks. The default is 500 ticks (5 seconds). extCheckInterval External commands check interval, in ticks. The default is 100 ticks (1 second). extUpdateInterval External commands update interval (used e.g. by fix commands executor), in ticks. The default is 3000 ticks (30 secondd). extTimeout External commands start timeout. The default is 60 seconds.
と言うことらしいので、多少の振れ幅はあるものの30秒前後で更新されると考えればいいだろう。
これはbsnmpdを再起動した場合もそうなので、タイミングには少し気を付けた方が良いかもしれない。
実際に取得してみる
まぁそんなわけで、少し待てば値がずらずら並ぶようになるので一息ついてから確認に入ろう。
皆さんも既にご存知の通り、SNMP Getのクライアントには bsnmpwalk または bsnmpget を使用します。
例えばda2の温度を取得する場合はこんな感じ:
# smartctl -A /dev/da2 | grep ^194 194 Temperature_Celsius 0x0022 108 101 000 Old_age Always - 44 # bsnmpwalk 1.3.6.1.4.1.2021.8.1.2.65 1.3.6.1.4.1.2021.8.1.2.65 = SMART_194_Temperature_Celsius_da2 # bsnmpwalk 1.3.6.1.4.1.2021.8.1.101.65 1.3.6.1.4.1.2021.8.1.101.65 = 44
おー、ちゃんと取れているね。
動かし続けよう
とりあえず、さっきのスクリプトをcronに仕込んで動かし続けてみようと思います。まる。
ちゃんとグラフも描いてみないとね!