shell 监控cpu,memory,load average,记录到log,当负载压力时,发电邮通知管理员。
平均负载是指系统的运行队列的平均利用率,也可以认为是可运行进程的平均数。
一般的进程需要消耗CPU、内存、磁盘I/O、网络I/O等资源,在这种情况下,平均负载就不是单独指的CPU使用情况。即内存、磁盘、网络等因素也可以影响系统的平均负载值。
在单核处理器中,平均负载值为1或者小于1的时候,系统处理进程会非常轻松,即负载很低。当达到3的时候,就会显得很忙,达到5或者8的时候就不能很好的处理进程了(其中5和8目前还是个争议的阈值,为了保守起见,建议选择低的)。
举例说明:
比如我的服务器是两颗CPU,每颗CPU有6个核,相当于12核的处理器。如果负载小于12,说明服务器利用率较低。如果负载大于12小于36,说明服务器利用率比较高,这个时候就应该考虑优化业务或者更换更快的CPU。如果负载大于36小于60,甚至超过60,则说明该服务器很危险,随时可能发生问题。经过上面的分析,我们用以下命令获取系统的平均负载值。
# top
# uptime
# w
平均负载值部分如:load average: 0.08, 0.03, 0.00.这些数值是指系统在最后1/5/15分钟的平均负载.那么我们判断负载过高,要以哪个值为准呢?根据经验:我们应该把重点放在5/15分钟的平均负载,因为1分钟的平均负载太频繁,一瞬间的高并发就会导致该值的大幅度改变。其中top的第一行与uptime的结果相同
uptime
top
[linuxidc@linuxidc ~]# uptime
20:15:58 up 7 min, 1 user, load average: 0.00, 0.10, 0.08
其中
20:15:58 up 系统启动时间
7 min 系统在线运行时间
load average 分别记录一分钟、五分钟、十五分钟的系统平均负载
主要是判断CPU的使用情况,现在的CPU都是多核心、多线程的模式。所以最终取决于总线程数。比如我们公司的CPU,是2个单元,每个单元是4核8线程。那么负载因子16的时候才算100%。
查看CPU信息使用
cat /proc/cpuinfo
如果只想得到线程数,则
grep 'model name' /proc/cpuinfo | wc -l
原理:
1.获取cpu,memory,load average的数值
2.判断数值是否超过自定义的范围,例如(CPU>90%,Memory<10%,load average>2)
3.如数值超过范围,发送电邮通知管理员。发送有时间间隔,每小时只会发送一次。
4.将数值写入log。
5.设置crontab 每30秒运行一次。
ServerMonitor.sh
[plain] view plain
copy
#!/bin/bash
1.
1.
# 系统监控,记录cpu、memory、load average,当超过规定数值时发电邮通知管理员
1.
1.
# *** config start ***
1.
1.
# 当前目录路径
1.
ROOT=$(cd "$(dirname "$0")"; pwd)
1.
1.
# 当前服务器名
1.
HOST=$(hostname)
1.
1.
# log 文件路径
1.
CPU_LOG="${ROOT}/logs/cpu.log"
1.
MEM_LOG="${ROOT}/logs/mem.log"
1.
LOAD_LOG="${ROOT}/logs/load.log"
1.
1.
# 通知电邮列表
1.
NOTICE_EMAIL='admin@admin.com'
1.
1.
# cpu,memory,load average 记录上一次发送通知电邮时间
1.
CPU_REMARK='/tmp/servermonitor_cpu.remark'
1.
MEM_REMARK='/tmp/servermonitor_mem.remark'
1.
LOAD_REMARK='/tmp/servermonitor_loadaverage.remark'
1.
1.
# 发通知电邮间隔时间
1.
REMARK_EXPIRE=3600
1.
NOW=$(date +%s)
1.
1.
# *** config end ***
1.
1.
1.
# *** function start ***
1.
1.
# 获取CPU占用
1.
function GetCpu() {
1.
cpufree=$(vmstat 1 5 |sed -n '3,$p' |awk '{x = x + $15} END {print x/5}' |awk -F. '{print $1}')
1.
cpuused=$((100 – $cpufree))
1.
echo $cpuused
1.
1.
local remark
1.
remark=$(GetRemark ${CPU_REMARK})
1.
1.
# 检查CPU占用是否超过90%
1.
if [ "$remark" = "" ] && [ "$cpuused" -gt 90 ]; then
1.
echo "Subject: ${HOST} CPU uses more than 90% $(date +%Y-%m-%d' '%H:%M:%S)" | sendmail ${NOTICE_EMAIL}
1.
echo "$(date +%s)" > "$CPU_REMARK"
1.
fi
1.
}
1.
1.
# 获取内存使用情况
1.
function GetMem() {
1.
mem=$(free -m | sed -n '3,3p')
1.
used=$(echo $mem | awk -F ' ' '{print $3}')
1.
free=$(echo $mem | awk -F ' ' '{print $4}')
1.
total=$(($used + $free))
1.
limit=$(($total/10))
1.
echo "${total} ${used} ${free}"
1.
1.
local remark
1.
remark=$(GetRemark ${MEM_REMARK})
1.
1.
# 检查内存占用是否超过90%
1.
if [ "$remark" = "" ] && [ "$limit" -gt "$free" ]; then
1.
echo "Subject: ${HOST} Memory uses more than 90% $(date +%Y-%m-%d' '%H:%M:%S)" | sendmail ${NOTICE_EMAIL}
1.
echo "$(date +%s)" > "$MEM_REMARK"
1.
fi
1.
}
1.
1.
# 获取load average
1.
function GetLoad() {
1.
load=$(uptime | awk -F 'load average: ' '{print $2}')
1.
m1=$(echo $load | awk -F ', ' '{print $1}')
1.
m5=$(echo $load | awk -F ', ' '{print $2}')
1.
m15=$(echo $load | awk -F ', ' '{print $3}')
1.
echo "${m1} ${m5} ${m15}"
1.
1.
m1u=$(echo $m1 | awk -F '.' '{print $1}')
1.
1.
local remark
1.
remark=$(GetRemark ${LOAD_REMARK})
1.
1.
# 检查是否负载是否有压力
1.
if [ "$remark" = "" ] && [ "$m1u" -gt "2" ]; then
1.
echo "Subject: ${HOST} Load Average more than 2 $(date +%Y-%m-%d' '%H:%M:%S)" | sendmail ${NOTICE_EMAIL}
1.
echo "$(date +%s)" > "$LOAD_REMARK"
1.
fi
1.
}
1.
1.
# 获取上一次发送电邮时间
1.
function GetRemark() {
1.
local remark
1.
1.
if [ -f "$1" ] && [ -s "$1" ]; then
1.
remark=$(cat $1)
1.
1.
if [ $(( $NOW – $remark )) -gt "$REMARK_EXPIRE" ]; then
1.
rm -f $1
1.
remark=""
1.
fi
1.
else
1.
remark=""
1.
fi
1.
1.
echo $remark
1.
}
1.
1.
1.
# *** function end ***
1.
1.
cpuinfo=$(GetCpu)
1.
meminfo=$(GetMem)
1.
loadinfo=$(GetLoad)
1.
1.
echo "cpu: ${cpuinfo}" >> "${CPU_LOG}"
1.
echo "mem: ${meminfo}" >> "${MEM_LOG}"
1.
echo "load: ${loadinfo}" >> "${LOAD_LOG}"
1.
1.
exit 0
crontab
[plain] view plain
copy
* * * * * /home/xxxx/ServerMonitor.sh
1.
* * * * * sleep 30; /home/xxxx/ServerMonitor.sh