【需求】
写一个监控脚本,监控系统负载,如果系统负载超过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循环后面永远也不会执行
审核编辑:汤梓红
全部0条评论
快来发表一下你的评论吧 !