ここ数日mrtgがおかしかった件

家のサーバでmrtgを使って温度とかCPU使用率とかを監視しているわけですが、一昨日からおそろしい数のエラーメールが来ていることに昨日気づきました。

Subject:Cron  /root/mrtg.sh

うん、cronでmrtg.shを読んでるからそこでエラーが出てるんだなということはわかる。
で、メールの中身は下の一文だけ。超文字化け。

/root/temperature.sh: line 6: echo: write error: e・・、

んー、なんなんだ。ちなみにtemperature.shは、CPUとHDDの温度取得スクリプト(自作)。

で、これを自分で実行してみる。

[root@hmx ~]# ./temperature.sh
45
40
40
 19:43:00 up 2 days, 11:20,  3 users,  load average: 0.13, 0.24, 0.16
Temperature

普通に動く。エラーでない。

[root@hmx ~]# cat temperature.sh
#!/bin/sh

grep RCPU /root/ipmi.dat | sed -e "s/[^|]*[^0-9]*\([0-9]*\)[^0-9]*/\1/g"
/usr/sbin/smartctl -d ata -A /dev/sda | grep Temperature | sed -e "s/[^-]*-[^0-9]*\([0-9]*\)[^-]*/\1/g"
uptime
echo "Temperature"

なんでechoしただけでwrite errorとかでんの…。

で、これの呼び出し元のmrtg.shを見たり、その通りに実行してみたり、cronの設定見たり…してみてもさっぱりわからない。

仕方ないのでそのまま放置して今日は会社に行ったんですが…、さっきわかった。

[root@hmx ~]# ./temperature.sh
45
40
40
 19:43:00 up 2 days, 11:20,  3 users,  load average: 0.13, 0.24, 0.16
Temperature

これ、何も問題ないと思ってたんだけど、実は一行余計じゃん、と。
mrtgって、1行目から順に

  • データ1
  • データ2
  • uptime
  • 説明?

だった気がするので、上の結果だと行が一個余計なんですよね…。それでechoでwrite errorがでてたんだなぁと。うーむ、前はこれできちんとできていたんだが。
というわけで、数値出力部分を実行してみる。

[root@hmx ~]# grep RCPU /root/ipmi.dat
RCPU Diode 1     | 45 degrees C      | ok
[root@hmx ~]# grep RCPU /root/ipmi.dat | sed -e "s/[^|]*[^0-9]*\([0-9]*\)[^0-9]*/\1/g"
45

うん、問題ない。ちなみにipmi.datはmrtg.shの中で、下のコマンドで作ってます。

ipmitool sdr > /root/ipmi.dat

次に2つめ。

[root@hmx ~]# /usr/sbin/smartctl -d ata -A /dev/sda | grep Temperature | sed -e "s/[^-]*-[^0-9]*\([0-9]*\)[^-]*/\1/g"
40
40

こいつかー!

[root@hmx ~]# /usr/sbin/smartctl -d ata -A /dev/sda
smartctl version 5.38 [x86_64-redhat-linux-gnu] Copyright (C) 2002-8 Bruce Allen
Home page is http://smartmontools.sourceforge.net/

=== START OF READ SMART DATA SECTION ===
SMART Attributes Data Structure revision number: 10
Vendor Specific SMART Attributes with Thresholds:
ID# ATTRIBUTE_NAME          FLAG     VALUE WORST THRESH TYPE      UPDATED  WHEN_FAILED RAW_VALUE
  1 Raw_Read_Error_Rate     0x000f   100   253   006    Pre-fail  Always       -       0
  3 Spin_Up_Time            0x0002   097   097   000    Old_age   Always       -       0
  4 Start_Stop_Count        0x0033   100   100   020    Pre-fail  Always       -       61
  5 Reallocated_Sector_Ct   0x0033   100   100   036    Pre-fail  Always       -       0
  7 Seek_Error_Rate         0x000f   081   060   030    Pre-fail  Always       -       135118751
  9 Power_On_Hours          0x0032   083   083   000    Old_age   Always       -       15134
 10 Spin_Retry_Count        0x0013   100   100   097    Pre-fail  Always       -       0
 12 Power_Cycle_Count       0x0033   100   100   020    Pre-fail  Always       -       61
184 Unknown_Attribute       0x0032   100   253   000    Old_age   Always       -       0
187 Reported_Uncorrect      0x003a   100   100   000    Old_age   Always       -       0
189 High_Fly_Writes         0x0022   100   100   000    Old_age   Always       -       0
190 Airflow_Temperature_Cel 0x001a   060   051   000    Old_age   Always       -       40 (Lifetime Min/Max 23/49)
194 Temperature_Celsius     0x0000   040   049   000    Old_age   Offline      -       40 (0 23 0 0)
195 Hardware_ECC_Recovered  0x0032   070   067   000    Old_age   Always       -       93771540
197 Current_Pending_Sector  0x0000   100   100   000    Old_age   Offline      -       0
198 Offline_Uncorrectable   0x0000   100   100   000    Old_age   Offline      -       0
199 UDMA_CRC_Error_Count    0x0000   200   200   000    Old_age   Offline      -       0

Tempertureが2個ありますね。
っつーわけで、どうもsmart関係のアップデートに伴って、このHDDから取得できるデータが増えた、というのが原因のよう。
で、この2個のTemperatureのどっちとりゃいいのかわからんので、grepの時点で1個に制限してみる。

[root@hmx ~]# /usr/sbin/smartctl -d ata -A /dev/sda | grep -m 1 Temperature | sed -e "s/[^-]*-[^0-9]*\([0-9]*\)[^-]*/\1/g"
40

うん、これで問題ないな。
というわけで、temperature.shのgrepのところに-m 1を突っ込んで完了。

[root@hmx ~]# cat temperature.sh
#!/bin/sh

grep -m 1 RCPU /root/ipmi.dat | sed -e "s/[^|]*[^0-9]*\([0-9]*\)[^0-9]*/\1/g"
/usr/sbin/smartctl -d ata -A /dev/sda | grep -m 1 Temperature | sed -e "s/[^-]*-[^0-9]*\([0-9]*\)[^-]*/\1/g"
uptime
/bin/echo "Temperature"

これで無事、CPUとHDDの温度取得が正常になりました…。