Monday, July 14, 2014

在Ganglia中監測主機溫度

雖然Ganglia 3.4.x之後支援直接用python寫module, 但是小弟的python功力還未夠班XD
所以用比較土法煉鋼的方法.
直接看code.

#!/usr/bin/python
import subprocess
import time

def gmetric():
        s = 0.0
        length = 0.0
        average = 0.0

        subprocess.call("/usr/local/bin/sensors |grep Core |awk '{print $3}'|cut -c 2-5 > /tmp/cpu.log",shell=True)
        subprocess.call("ipmitool sdr type temperature|grep Ambient|awk '{print $10}' > /tmp/ambient.log",shell=True)
        data = open('/tmp/cpu.log','r').read().split()
        s = sum([float(i) for i in data])
        average = s/len(data)
        data2 = open('/tmp/ambient.log','r').readline()
        a = int(data2)

        subprocess.call(['gmetric','-uCelsius','-gTemperature','-ncputemp','-tfloat','-TCPU Average Temperature','-v', str(average)])
        subprocess.call(['gmetric','-uCelsius','-gTemperature','-nambient','-tfloat','-TAmbient Temperature','-v', str(a)])

gmetric()

重點在中間的兩個shell command.
第一個subprocess call 會呼叫lm_sensors, 擷取帶有Core的字眼, 用awk切第三欄出來 (溫度), 然後用cut把單位跟正負號砍掉, 只留下數字. 最後核心的溫度被倒進/tmp/cpu.log裡面.
第二個call則是呼叫ipmitool, 去擷取溫度相關的部分, 然後找Ambient (環境)溫度, 一樣擷取數字出來, 倒進/tmp/ambient.log.

要注意的是, 不同的機器這個過濾條件會不一樣.
例如lm_sensors抓到的CPU溫度監控模組名稱 Intel現在大多用coretemp, AMD的有些無法用lm_sensors抓到正確的溫度, 要從ipmitool去抓.
因此你可以多加測試正確有效的command, 確定ok之後再改進這個python code裡面.

範例中的機器是IBM x3550 M3.
另一個測試成功的機器是Dell R815, 中間的部分變成:

        subprocess.call("ipmitool sdr type temperature | head -n 11 > /tmp/ipmi.log",shell=True)
        subprocess.call("grep CPU /tmp/ipmi.log|awk '{print $11}' > /tmp/cpu.log",shell=True)
        subprocess.call("grep Ambient /tmp/ipmi.log|awk '{print $10}' > /tmp/ambient.log",shell=True)

這就是因為lm_sensors抓不到CPU溫度, 所以都用ipmitool讀取溫度後倒進/tmp/ipmi.log, 然後再去ipmi.log中分別找CPU / Ambient溫度.

只要最後溫度的數字寫在/tmp/cpu.log, 環境溫度寫在/tmp/ambient.log, 後面的code就可以處理.

後面的code讀取cpu.log, 對所有數字做平均, 得到CPU的平均溫度, 另外讀出ambient溫度.

最後再次呼叫gmetric指令, 把CPU平均溫度以cputemp metric傳給gmond, ambient溫度以ambient metric傳給gmond, 這樣就可以了.

原先的寫法是把這個python code寫成無限迴圈, 利用sleep指令固定一段時間做一次擷取, 但這樣的壞處是如果code因故中斷, 整個監測就停下來了, 要手動再執行一次迴圈.
現在這樣的寫法, code只會執行一次, 然後用cron去每分鐘執行一次這個code, 這樣就不怕迴圈中斷的問題.

No comments: