约定: 所有的脚本放在 / usr/local/sbin / 下
一, 告警系统主脚本 main.sh
- # cd /usr/local/sbin/
- # mkdir mon
- # cd mon
- # mkdir bin conf shares log mail
- # cd bin
- # vim main.sh
- #!/bin/bash
- #Written by aming.
- # 告警是否发送邮件的开关
- export send=1 #// 意味着这个变量会有应用到所有的子脚本里面.
- # 过滤 ip 地址, 网卡名根据自己的定义. 这里的 addr, 是每一台服务器的 IP 地址, 也可以定义 hostname.
- export addr=`/sbin/ifconfig |grep -A1 "ens33:"|awk '/inet/ {print $2}'`
- dir=`pwd`
- # 只需要最后一级目录名, 等于上面 pwd 出来的最后一个目录.
- last_dir=`echo $dir|awk -F'/' '{print $NF}'`
- # 下面一句的判断目的是, 保证执行脚本的时候, 我们在 bin 目录里, 不然监控脚本, 邮件和日志很有可能找不到
- if [ $last_dir == "bin" ] || [ $last_dir == "bin/" ]; then
- conf_file="../conf/mon.conf"
- else #如果没有在 bin 目录, 输出: 你应 cd 到 bin 目录
- echo "you shoud cd bin dir"
- exit
- fi
- exec 1>>../log/mon.log 2>>../log/err.log
- echo "`date +"%F %T"` load average" #打标记, 是要求出系统负载
- /bin/bash ../shares/load.sh #直接执行主脚本
- # 先检查配置文件中是否需要监控 502
- if grep -q 'to_mon_502=1' $conf_file; then
- export log=`grep 'logfile=' $conf_file |awk -F '=' '{print $2}' |sed 's///g'`
- /bin/bash ../shares/502.sh
- fi
二, 告警系统配置文件 mon.conf
mon.conf 内容 路径:/usr/local/sbin/mon/conf/mon.conf
- ## to config the options if to monitor
- ## 定义 mysql 的服务器地址, 端口以及 user,password
- to_mon_cdb=0 ##0 or 1, default 0,0 not monitor, 1 monitor,cdb 是数据库名
- db_ip=10.20.3.13
- db_port=3315
- db_user=username
- db_pass=passwd
- ## 监控 httpd 如果是 1 则监控, 为 0 不监控
- to_mon_httpd=0
- ## 监控 php 如果是 1 则监控, 为 0 不监控
- to_mon_php_socket=0
- ## 监控 502 http_code_502 需要定义访问日志的路径, 因为 502 在访问日志里, 要在这个日志里去过滤出来
- to_mon_502=1
- logfile=/data/log/xxx.xxx.com/access.log
- ## request_count 定义日志路径以及域名, 监控请求数, 监控为 1, 反之 0.
- to_mon_request_count=0
- req_log=/data/log/www.discuz.net/access.log ## 这里是同理, 在这个日志过滤, 还要定义所涉及到的域名如 www.discuz.net.
- domainname=www.discuz.net
可以把域名和日志全写到子脚本里面去, 前提是没有太多机器的情况下是可以的.
如果想把 shell 系统写得非常规范化, 标准化, 让脚本通用, 就把各个日志什么的都写到配置文件里, 这样改起来就很方便. 省得各个子脚本挨个去改.
三, 告警系统监控项目 load.sh
load.sh 内容 路径:/usr/local/sbin/mon/shares/load.sh
- #! /bin/bash
- ##Writen by aming##
- load=`uptime |awk -F 'average:' '{print $2}'|cut -d',' -f1|sed 's///g' |cut -d. -f1`
- # 求出 load 数值
- if [ $load -gt 10 ] && [ $send -eq "1" ]
- # 当 load 值大于 10 并且 send 开关等于 1 时.
- then
- echo "$addr `date +%T` load is $load">../log/load.tmp
- # 输出一条日志, 这条日志是为了发送邮件用的, 输出到的后面的文件是用来发邮件用的一个文件
- /bin/bash ../mail/mail.sh aming_test@163.com "$addr\_load:$load" `cat ../log/load.tmp`
- #mail.sh(发邮件的脚本)
- fi
- echo "`date +%T` load is $load"
整体: 负载大于 10 并且 send 等于 1 时, 就发邮件记录, 反之, 则只记录一条日志.
502.sh 内容 路径:/usr/local/sbin/mon/shares/502.sh
502.sh 的内容和 load.sh 的思路一样.
因为主脚本是一分钟执行一次, 所以, 监控的是一分钟前的日志, 所以截取一分钟前的时间.
- #! /bin/bash
- d=`date -d "-1 min" +%H:%M` #截取一分钟前的时间
- c_502=`grep :$d: $log |grep '502'|wc -l`
- if [ $c_502 -gt 10 ] && [ $send == 1 ]; then
- echo "$addr $d 502 count is $c_502">../log/502.tmp
- /bin/bash ../mail/mail.sh $addr\_502 $c_502 ../log/502.tmp
- fi
- echo "`date +%T` 502 $c_502"
disk.sh 内容 (磁盘使用率) 路径:/usr/local/sbin/mon/shares/disk.sh
思路: 把所有的分区挨个看一下
- #! /bin/bash
- ##Writen by aming##
- rm -f ../log/disk.tmp
- for r in `df -h |awk -F '[ %] ' '{print $5}'|grep -v Use` #把磁盘已用的过滤出来, 去掉百分号. 这里 awk 的分隔符比较特殊, 以空格和百分号两个作为分隔符,+ 号代表一个或多个空格只作为一个符号来作用, 比如多个空格或多个百分号. 在一个字符串里可以用多个作为分隔符. grep -v Use 就是把已用两个字也过滤掉, 英文下可过滤, 中文不行.
- do
- if [ $r -gt 90 ] && [ $send -eq "1" ] #判断, 阈值大于 90 就发邮件
- then
- echo "$addr `date +%T` disk useage is $r">>../log/disk.tmp
- fi
- if [ -f ../log/disk.tmp ] #判断这个文件是否存在, 存在就直接发邮件, 不存在就写日志.
- then
- df -h>> ../log/disk.tmp
- /bin/bash ../mail/mail.sh $addr\_disk $r ../log/disk.tmp
- echo "`date +%T` disk useage is nook"
- else
- echo "`date +%T` disk useage is ok"
- fi
- # 两个条件同时满足就写 disk.tmp 文件, 不满足就写日志就行了.
来源: http://www.bubuko.com/infodetail-2708761.html