38

案例五、监控磁盘使用率-CLAY

 4 years ago
source link: https://blog.51cto.com/13576245/2422097
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

案例五、监控磁盘使用率

对于磁盘的监控属于最基础的监控,但是很多时候往往因为运维的疏忽而忽略监控磁盘,最终导致事故发生。希望读到这篇文章的朋友,一定要把监控磁盘这件事重视起来。

本案例需求如下:

1)每分钟检测一次磁盘状况

2)当磁盘空间使用率或者iNode使用率高于90%,需要发邮件告警,假设收件邮箱为[email protected]

3)统计使用率超过90%的分区所有子目录的大小,并把排名前三的子目录写到邮件内容中发给上面的邮箱

4)第一次告警后,如果我们没有及时处理,则需要每隔30分钟告警一次

5)每分钟脚本执行时,需检测该脚本是否已执行完,如果没有完成则本次不执行

知识点一:查看磁盘使用

命令:df

df查看已挂载磁盘的总容量、使用容量、剩余容量等,可以不加任何参数,默认是以k为单位显示的,常用选项有-i,-h,-k,-m。-i选项查看iNode使用状况,-h选项会使用合适的单位显示,例如G或M,-k、-m选项分别以K、M为单位显示。

# df -h
文件系统        容量  已用  可用 已用% 挂载点
/dev/sda3        16G  8.0G  7.9G   51% /
devtmpfs        903M     0  903M    0% /dev
tmpfs           912M     0  912M    0% /dev/shm
tmpfs           912M  8.7M  903M    1% /run
tmpfs           912M     0  912M    0% /sys/fs/cgroup
/dev/sda1       197M  113M   85M   58% /boot
tmpfs           183M     0  183M    0% /run/user/0

第一列是分区名字,第二列为该分区总共的容量,第三列为已经使用了多少,第四列为还剩下多少,第五列为已经使用的百分比,最后一列为挂载点。

知识点二:查看目录或文件大小

命令:du

du命令用来查看某个目录或文件所占空间的大小。

语法:du [-abckmsh] [文件名或目录名]

常用参数:

-a:表示全部文件和目录的大小都列出来。若后面不加任何选项和参数。则只会列出目录(包含子目录)的大小。若du命令不指定单位的话,默认显示单位为KB。

示例命令:

# du /tmp/test
0	/tmp/test
# du -a /tmp/test
0	/tmp/test/1.txt
0	/tmp/test

-b:表示列出的值以B为单位输出。

-k:表示以KB为单位输出,这和默认不加任何选项的输出值是一样的。

-m:表示以MB为单位输出。

-h:表示系统自动调节单位。

-c:表示最后加总。不常用,示例命令:

# du -c /tmp/test
0	/tmp/test
0	总用量

-s:表示只列出总和。常用选项,示例命令:

# du -s /tmp/test
0	/tmp/test

常用的用法:du -sh filename

结合find查找某个目录下所有子目录,并统计大小,命令为:

# find /dir/ -type d |sed '1d' |xargs du -sm

说明:用sed '1d'删除第一行,原因是第一行是目录本身,而我们要统计的是子目录。

知识点三:查看进程

在Windows下可以进入任务管理器查看进程,在Linux下有一些命令也可以查看进程。

1)top

这个命令用于动态监控进程所占系统资源,每隔3秒变一次。该命令的特点是把占用系统资源(CPU、内存、磁盘IO等)最高的进程放到最前面。

top命令打印出了很多信息,包括系统负载(load average)、进程数(Tasks)、CPU使用情况、内存使用情况以及交换分区使用情况。

top重点查看的还是下面的进程使用系统资源详细情况。这部分东西反映的还是比较多,不过需要关注的也就几项:RES,%CPU,%MEN,COMMAND。RES为进程所占内存大小,%CPU为进程使用CPU百分比。COMMAND为具体进程名字。

在top状态下,按M可按内存使用大小排序,按P切回CPU排序,按数字1可列出每颗CPU的使用状态。常用的一个命令为:top -bn1,表示静态打印系统资源使用情况,适合用在shell脚本中。top还有一个-c选项,可以显示具体的命令,也就是说在COMMAND这一列出更加详细。

ps命令用来汇报当前系统进程的状况,常见用法有ps aux和ps -elf。

在本例中,我们检查某个进程是否存在,可以用:

# ps aux |grep '进程名'

假如,本脚本的名字为mon_disk.sh,则需要这样统计:

# ps aux |grep 'mon_disk.sh' |grep -vE "$$|grep"

说明:这里的$$为本进程PID ,之所以要排除掉它,是因为我们需要检查之前的旧进程而不是本次的进程,并且需要把grep这个进程也排除掉。

知识点四:告警收敛思路分析

本案例中有要求,如果发生告警后,下次再告警应该是30分钟后。脚本本应该是一分钟执行一次,告警邮件也会一分钟发一次,告警邮件也会一分钟发一次,如果我们不能在短时间内修复完问题,则会造成邮件骚扰。

这里的思路是引入一个计数器,而且需要考虑以下几个场景:

1)脚本从来没有告警过,第一次告警

这种情况,不用考虑太多东西,直接发邮件,但需要做两件事,第一需要记录此时的时间戳到一个临时文件中,第二需要建立一个临时文件记录告警次数,告警发生但不一定发邮件,要区分差异。

2)脚本之前告警过,距离上一次告警超过30分钟

判断距离上一次告警多久需要借助记录时间戳的临时文件,求本次告警时间戳和上一次告警时间戳的差值,是否大于1800秒。根据需求,只要大于30分钟就可以立即发邮件,同时记录时间戳和告警次数到两个不同的临时文件中。

3)脚本之前告警过,距离上一次告警不超过30分钟

不超过30分钟则需要查看记录告警次数的临时文件,只有次数大于等于30才会再一次发邮件。

本案例参考脚本

#!/bin/bash
##监控磁盘使用情况,并做告警收敛(30分钟发一次邮件)
##作者:
##日期:
##版本:v0.1

#把脚本名字存入变量s_name
s_name=`echo $0 |awk -F '/' '{print $NF}'`
#定义收件人邮箱
[email protected]

#定义检查磁盘空间使用率函数
chk_sp()
{
  df -m |sed '1d' |awk -F '%| +' '$5>90 {print $7,$5}'>/tmp/chk_sp.log
  n=`wc -l /tmp/chk_sp.log|awk '{print $1}'`
  if [ $n -gt 0 ]
  then
      tag=1
      for d in `awk '{print $1}' /tmp/chk_sp.log`
      do
        find $d -type d |sed '1d' |xargs du -sm |sort -nr|head -3
      done > /tmp/most_sp.txt
  fi
}

#定义检查iNode使用率的函数
chk_in()
{
  df -i |sed '1d'|awk -F '%| +' '$5>90 {print $7,$5}'>/tmp/chk_in.log
  n=`wc -l /tmp/chk_in.log|awk '{print $1}'`
  if [ $n -gt 0 ]
  then
      tag=2
  fi
}

#定义告警函数(这里的mail.py是案例二中的那个脚本)
m_mail(){
   log=$1  #此处的$1表示第一个函数chk_sp
   t_s=`date +%s`
   t_s2=`date -d "1 hours ago" +%s`
   if [ ! -f /tmp/$log ]
   then
       #创建$log文件
       touch /tmp/$log
       #增加a权限,只允许追加内容,不允许更改或删除
       chattr +a /tmp/$log
       #第一次告警,可以直接写入1小时以前的时间戳
       echo $t_s2 >> /tmp/$log
   fi
   #无论$log文件是否是刚刚创建,都需要查看最后一行的时间戳
   t_s2=`tail -1 /tmp/$log|awk '{print $1}'`
   #取出最后一行即上次告警的时间戳后,立即写入当前的时间戳
   echo $t_s>>/tmp/$log
   #取两次时间戳差值
   v=$[$t_s-$t_s2]
   #如果差值超过1800,立即发邮件
   if [ $v -gt 1800 ]
   then
      #发邮件,其中$2为mail函数的第二个参数,这里为一个文件
      python mail.py $mail_user "磁盘使用率超过90%" "`cat $2`" 2>/dev/null
      #定义计数器临时文件,并写入0
      echo "0" > /tmp/$log.count
   else
      #如果计数器临时文件不存在,需要创建并写入0
      if [ ! -f /tmp/$log.count ]
      then
          echo "0" > /tmp/$log.count
      fi
      nu=`cat /tmp/$log.count`
      #30分钟内每发生一次告警,计数器加1
      nu2=$[$nu+1]
      echo $nu2>/tmp/$log.count
      #当告警次数超过30次,需要再次发邮件
      if [ $nu2 -gt 30 ]
      then
          python mail.py $mail_user "磁盘使用率超过90%持续30分钟了" "`cat $2`" 2>/dev/null
          #第二次告警后,将计数器再次从0开始
          echo "0" > /tmp/$log.count
      fi
    fi
}

#把进程情况存入临时文件,如果加管道求行数会有问题
ps aux |grep "$s_name" |grep -vE "$$|grep">/tmp/ps.tmp
p_n=`wc -l /tmp/ps.tmp|awk '{print $1}'`

#当进程数大于0,则说明上次的脚本还未执行完
if [ $p_n -gt 0 ]
then
    exit
fi

chk_sp
chk_in

if [ $tag == 1 ]
then
   m_mail chk_sp /tmp/most_sp.txt
elif [ $tag == 2 ]
then
   m_mail chk_in /tmp/chk_in.log
fi

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK