有台主机的CPU负荷监控脚本,原先是这么写的
import psutil
sample_seconds = 1
print psutil.cpu_percent(sampel_seconds)
就是跑的时候采样1秒钟的系统负荷,如果超过阈值会引发告警。
最近发现告警频繁, 但是通过uptime看又占用不高, 看来是因为采用的1s随机性太大,如果这1s刚好和一些定时任务的执行时间重叠,就会造成负荷偏高,而实际上主机负荷并不高。把sample_seconds拉长的话,这个取监控的脚本又会阻塞监控agent。
如果用vmstat的话,要另外安装,而且这个的原理也是指定采样时长统计负荷,跟之前的做法换汤不换药,有没有更简单直接的办法呢?
当然是有的:
我们知道系统自带的uptime命令,会统计最近的1,5,15 min的系统负荷,单位是占用的core数,而系统的总core数,可以通过/proc/cpuinfo文件得到,于是,改为用下面的脚本来得到过去的1,5,15 min的系统平均负荷,这样能够有效的解决上面随机采样的问题。
于是撸一个脚本如下:
#!/usr/bin/python
#coding: utf-8
import os
import re
def cmd(CMD):
'''执行命令行获取输出'''
return os.popen(CMD).read().strip()
#正则表达式,从uptime输出抽取出3个时段的平均负荷
r = re.compile(r'.*load average:(.*)$')
def get_avg_loads():
#uptime命令可以得到最近1min, 5min, 15min的系统负荷
#单位是占用了几个core
#22:55:40 up 646 days, 11:18, 9 users, load average: 0.21, 0.29, 0.32
m = r.match(cmd('uptime'))
if m is not None:
return map(lambda x:float(x), m.groups()[0].split(','))
def get_cores():
# 这个命令,直接获取主机的core总数
CMD="grep processor /proc/cpuinfo|wc -l"
return float(cmd(CMD))
if __name__=='__main__':
core_num = get_cores()
load_percent = map(lambda x: "%.3f%%"%(x/core_num*100), get_avg_loads())
print load_percent
执行结果得到# ./cpu_load.py
['7.125%', '7.187%', '7.875%']
实际上,如果再深挖一下uptime的那3个负荷统计的来源的话,可以找到/proc/loadavg内核文件,这个文件的说明可以在 man proc里面找到说明# uptime
15:41:23 up 521 days, 56 min, 3 users, load average: 2.04, 1.93, 1.28
# cat /proc/loadavg
2.04 1.93 1.28 3/2512 5451
所以,上面的实现,可以改为从/proc/loadavg文件读,这样就更直接了。