监控系统负载记录系统状态

描述

【需求】

写一个监控脚本,监控系统负载,如果系统负载超过10,需要记录系统状态信息。

提示:

1)系统负载命令使用uptime看,过去1分钟的平均负载

2)系统状态使用如下工具标记:top、 vmstat、   ss

3)要求每隔20s监控一次

4)系统状态信息需要保存到/opt/logs/下面,保留一个月,文件名建议带有`date +%s`后缀或者前缀

【解析】

这是一个监控脚本,对于监控脚本,通常有两种思路

一个是做一个死循环,让它一直跑着,每检测一次,中间间隔一段时间,比如本题要求的20s

另外一种是一分钟执行一次,利用系统的任务计划,每分钟执行

本案例要求每20s监控一次,所以只能使用第一种,死循环

死循环,使用while :; do  ...; done 

这里的 : 你可以理解成条件为真

再来看脚本要求,监控系统负载,超过10就记录系统状态信息

问题的关键点在于,如何获取到系统负载的值

系统负载,在Linux里面可以使用w或者uptime或者top命令都可以获取到

脚本

脚本

脚本

这里的load average 后面的三个数字就是系统负载,它们分别表示过去1分钟、5分钟、15分钟内系统的平均负载

为了更加精准,我们需要选择1分钟的平均负载

那这个负载到底代表着什么含义呢?

就拿这个1分钟负载来说,这个数字表示,过去1分钟,平均有多少个进程在使用CPU资源

使用CPU资源的进程越多,那就意味着CPU越忙

那,这个数字为多少是合适呢?

这取决于你的系统里有多少颗CPU,这个数字不是物理CPU,指的是逻辑CPU个数,那如何查看?

使用lscpu命令看

脚本

比如,你系统有8颗CPU,那么系统负载为8时,表示1颗CPU处理一个进程,这样CPU没有空闲也不忙,是最合适的

好了,说完系统负载,再回头看脚本

如何拿到这个1分钟的负载数值呢?

这就需要借助sed awk 以及 cut等各种处理字符串的工具了

uptime |awk -F 'average:' '{print $2}'

脚本

首先将三个数字打出来,然后想办法截取第一个数字

此时,可以使用cut来截取

脚本

这时候出现的结果还不是最终的数字,还需要将最前面的空格去掉,而且我们不需要小数点以及后面的数字

使用sed将空格去掉

脚本

再使用cut将小数点前面的数字截取

脚本

其实,写脚本就需要大家一步一步地去尝试

拿到负载值之后,再去和10做比较

可以先将负载值赋值到变量里,然后用变量去做比较

if [ $load -gt 10 ]; then ...; fi 

如果负载值高于10,就需要记录系统状态信息

题目也提示我们了,获取系统负载的状态,有top  vmstat 和 ss 三个命令

如果大家不会使用这几个命令,那么脚本就无法写出来了

所以,写shell脚本的前提是,你必须要具备一定的认知

top -bn1 可以一次性展示top的结果,但是没必要将所有都记录下来,只需要前100行就足够了,因为我们关注的是排在最前面的几个进程

vmstat 命令可以记录包括cpu、内存、io等信息,用法是 vmstat  n1  n2 , 其中n1和n2是两个数字,前面的数字,表示几秒钟打印一次信息,后面的数字是打印几次,建议是1秒1次,打印10次

所以最终用法啊是

 

vmstat 1 10

 

ss是用来查看网络链接状态的命令,这里需要使用

 

ss -an

 

有了记录系统状态信息的命令后,接下来就是要规划,将这些信息记录到哪个日志里

两种思路,一个是一股脑全部记录到一个文件里,每次记录都是追加

另外一个思路是,针对top、vmstat、ss分别记录日志

这里我选择第二个,这样方便查看,题目中要求给这个日志加一个date +%s的时间戳作为后缀前缀或者后缀,那么就用后缀吧,比如:

 

top.`date +%s`, vmstat.`date+%s`, ss.`date +%s`

 

删除掉一个月以前的,使用find查看即可,还需要注意,/opt/logs/下面有可能有其它日志,所以我们只需要针对本脚本产生的日志进行搜索

find可以这样做

 

find  /opt/logs  -name "top*" -o -name "vmstat*" -o -name "ss*" 

 

说明一下,这里的-o表示或者的意思,如果不加-o,那么就是并且

find 还支持将一堆条件搞到一起,作为一个整体,需要使用(),例如

 

find  /opt/logs ( -name "top*" -o -name "vmstat*" -o -name "ss*" ) -mtime +30

 

需要注意,小括号使用脱义符号脱义了,并且前后有空格

【参考答案】

脚本最终结果是这样的:

 

#!/bin/bash
[ -d /opt/logs ] || mkdir -p /opt/logs
while :
do
    load=`uptime |awk -F 'average:' '{print $2}'|cut -d',' -f1|sed 's/ //g' |cut -d. -f1`
    if [ $load -gt 10 ]
    then
        top -bn1 |head -n 100 > /opt/logs/top.`date +%s` 
        vmstat 1 10 > /opt/logs/vmstat.`date +%s`
        ss -an > /opt/logs/ss.`date +%s`
    fi
    sleep 20
    find  /opt/logs ( -name "top*" -o -name "vmstat*" -o -name "ss*" ) -mtime +30 |xargs rm  -f
done

 

脚本运行时,丢入后台去

着重提醒一下,有的同学将最后面这个load赋值或者find命令放到了while循环外面,

这是不对的,放到while循环前面它只会执行一次,而放到while循环后面永远也不会执行

  审核编辑:汤梓红

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分