第二十章、shell编程(中)

20.16/20.17 shell中的函数

20.18 shell中的数组

20.19 告警系统需求分析

20.20 告警系统主脚本

20.21 告警系统配置文件

20.22 告警系统监控项目

20.23/20.24/20.25 告警系统邮件引擎

20.26 运行告警系统

20.16/20.17 shell中的函数

•函数就是把一段代码整理到了一个小单元中,并给这个小单元起一个名字,当用到这段代码时直接调用这个小单元的名字即可。

格式: (function可以省略掉不写,f_name表示定义函数名)

function f_name() {

                      command

             }

#函数必须要放在最前面

• 示例1

定义系统参数变量

vim fun.sh

#!/bin/bash

input() {

    echo $1 $2 $# $0

}

input 1 a b

#这里input后面跟具体的参数

sh  

•示例2

两个参数相加求和

vim fan2.sh

#!/bin/bash

sum() {

    s=$[$1+$2]

    echo $s

}

sum 1 2

•示例3

输入网卡名字显示ip地址

#!/bin/bash

ip() {

    ifconfig |grep -A1 "$1 " |tail -1 |awk '{print $2}'|awk -F':' '{print $2}'

}

read -p "Please input the eth name: " e

myip=`ip $e`

echo "$e address is $myip"

改进:1、判断是否是系统的网卡

          2、判断网卡是否有ip

20.18 shell中的数组

#应用场景不多

•定义数组 

a=(1 2 3 4 5)

echo ${a[@]}

#将a数组的所有元素显示

echo ${#a[@]} 获取数组的元素个数

echo ${a[2]} 读取第三个元素,数组从0开始算第一个元素

echo ${a[*]} 等同于 ${a[@]}  显示整个数组

• 数组赋值

a[1]=100             #将a数组的第一个元素赋值100

echo ${a[@]}       #显示所有a的元素

a[5]=2; echo ${a[@]}   

#将a的第五个元素赋值2,并信使所有元素

#如果下标(就是第几个元素的标记)不存在则会自动添加一个元素

• 数组的删除

uset a               #删除整个a数组

unset a[1]         #删除a的第一个元素

•数组分片(截取)

a=(`seq 1 5`);echo ${a[*]}      #用seq进行元素赋值并显示

echo ${a[@]:0:3}   #从第一个元素开始,截取3个元素

echo ${a[@]:1:4}  #从第二个元素开始,截取4个元素

echo ${a[@]:0-3:2}  #从倒数第3个元素开始,截取2个元素

• 数组替换

echo ${a[@]/3/100}    #将a的第三个元素替换成100

等同于

a=(${a[@]/3/100})      #将a的第三个元素替换成100

20.19 告警系统需求分析

shell项目-告警系统

• 需求:使用shell定制各种个性化告警工具,但需要统一化管理、规范化管理。 

• 思路:指定一个脚本包,包含主程序、子程序、配置文件、邮件引擎、输出日志等。

  • 主程序:作为整个脚本的入口,是整个系统的命脉。

  • 配置文件:是一个控制中心,用它来开关各个子程序,指定各个相关联的日志文件。

  • 子程序:这个才是真正的监控脚本,用来监控各个指标。

  • 邮件引擎:是由一个python程序来实现,它可以定义发邮件的服务器、发邮件人以及发件人密码

  • 输出日志:整个监控系统要有日志输出。

•要求:我们的机器角色多种多样,但是所有机器上都要部署同样的监控系统,也就说所有机器不管什么角色,整个程序框架都是一致的,不同的地方在于根据不同的角色,定制不同的配置文件。

• 程序架构:   

bin下是主程序

conf下是配置文件

shares下是各个监控脚本

mail下是邮件引擎

log下是日志。

创建相关目录

cd /usr/local/sbin/

mkdir mon

cd mon/

mkdir bin conf shares mail log

20.20 告警系统主脚本

cd /usr/local/sbin/mon/bin/

vim main.sh

• main.sh内容

#!/bin/bash

# 是否发送邮件的开关(如果系统处于维护的状态,应该把发送邮件开关关掉

export send=1

# 过滤ip地址(实验网卡是ens33)

export addr=`/sbin/ifconfig |grep -A1 "ens33: "|awk '/inet/ {print $2}'`

dir=`pwd`

# 找当前主脚本所在的目录,只需要最后一级目录名

last_dir=`echo $dir|awk -F'/' '{print $NF}'`

# 下面的if判断为了保证执行脚本的时候,我们在bin目录里,不然监控脚本、邮件和日志很有可能找不到

if [ $last_dir == "bin" ] || [ $last_dir == "bin/" ]; then

    conf_file="../conf/mon.conf"

#创建配置文件路径

else

    echo "you shoud cd bin dir"

    exit

fi

#定义log日志路径

exec 1>>../log/mon.log 2>>../log/err.log

#打一个日期标记求出系统负载

echo "`date +"%F %T"` load average"

#直接执行子脚本load.sh

/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

20.21 告警系统配置文件

cd /usr/local/sbin/mon/conf/

vim mon.conf

• mon.conf内容

## to config the options if to monitor

## 定义mysql的服务器地址、端口以及user、password

to_mon_cdb=0  

##0 or 1,1监控cdb数据库,0不监控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

## http_code_502  需要定义访问日志的路径

#1是监控502状态码,0是关闭

to_mon_502=0

logfile=/data/log/xxx.xxx.com/access.log

## request_count   定义日志路径以及域名

to_mon_request_count=0

#监控请求数,1监控,0不监控

req_log=/data/log/www.discuz.net/access.log

#定义请求log日志路径

domainname=www.discuz.net

#请求log日志内涉及到的域名

20.22 告警系统监控项目

• load.sh内容(监控系统负载)

cd /usr/local/sbin/mon/shares/

vim load.sh

#! /bin/bash

#查看系统负载的值

load=`uptime |awk -F 'average:' '{print $2}'|cut -d',' -f1|sed 's/ //g' |cut -d. -f1`

#if判断系统负载大于10并且send的开关是打开的,进行操作,然后指定内容放到临时文件,然后再通过邮件发送

if [ $load -gt 10 ] && [ $send -eq "1" ]

then

    echo "$addr `date +%T` load is $load" >../log/load.tmp

    /bin/bash ../mail/mail.sh [email protected] "$addr\_load:$load" `cat ../log/load.tmp`

fi

echo "`date +%T` load is $load"

• 502.sh内容(监控502状态码)

cd /usr/local/sbin/mon/shares/

vim 502.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内容(监控磁盘使用率)

cd /usr/local/sbin/mon/shares/

vim disk.sh

#! /bin/bash

rm -f ../log/disk.tmp

#定义系统语言为英文,目的是为了下面df -h 过滤掉Use,如果是中文的话是已用,没有过滤掉

LANG=en

#'[ %]+'以一个或者多个空格或者%作为分隔符,使用多个分隔符时用中括号 [ ]括起来

for r in `df -h |awk -F '[ %]+' '{print $5}'|grep -v Use`

do

    if [ $r -gt 90 ] && [ $send -eq "1" ]

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

20.23/20.24/20.25 告警系统邮件引擎

cd /usr/local/sbin/mon/mail/

vim mail.sh

•mail.sh内容 (主要做告警收敛)

#告警收敛:就是告完第一次警后,指定间隔多长时间才会再次告警

#其中mail.py内容到这里下载(也放在mail目录)https://coding.net/u/aminglinux/p/aminglinux-book/git/blob/master/D22Z/mail.py

  log=$1

#定义时间戳

t_s=`date +%s`

#定义两个小时前时间戳(为了后面的if判断时间差

t_s2=`date -d "2 hours ago" +%s`

#if判断log日志如果不存在,将t_s2的时间戳放入log日志

if [ ! -f /tmp/$log ]

then

    echo $t_s2 > /tmp/$log

fi

#第一次执行mail,生成log日志,内容是两个小时前时间戳,这次定义变量t_s2,会覆盖上次定义的t_s2

t_s2=`tail -1 /tmp/$log|awk '{print $1}'`

#将当前时间戳写入log日志

echo $t_s>>/tmp/$log

#定义变量值为当前时间戳与两小时前时间戳的时间差

v=$[$t_s-$t_s2]

echo $v

#if判断告警时间差大于一个小时,则发生告警($log.txt相当于计数器)

if [ $v -gt 3600 ]

then

#mail.py的三个参数是发送给谁,邮件主题,邮件内容

    ./mail.py  $1  $2  $3

    echo "0" > /tmp/$log.txt

else

#if判断$log.txt如果不存在,创建并重置

    if [ ! -f /tmp/$log.txt ]

    then

        echo "0" > /tmp/$log.txt

    fi

#定义nu为查看$log.txt里面的数字

    nu=`cat /tmp/$log.txt`

#定义nu2位nu的数字加一

    nu2=$[$nu+1]

    echo $nu2>/tmp/$log.txt

#if判断nu2计数器大于10,则发送邮件,提示计时持续了10分钟

    if [ $nu2 -gt 10 ]

    then

         ./mail.py  $1 "trouble continue 10 min $2" "$3"

#$log.txt计数器被重置

         echo "0" > /tmp/$log.txt

    fi

fi  

#mail.sh是一分钟运行一次的

第一种场景:

某监控一直出现问题,mail.sh运行了11次,发送邮件(mail.sh每次运行一次,计数器加一,11次后满足if判断发送邮件的要求)

第二种场景:

假如502监控前两次运行mial.sh出现问题,在mail.sh第三次运行时正常了,计数器停在2;然而第八次运行时又开始告警(由于502次数大于10),此时计数器是3,再运行mail.sh八次,会发送邮件告警计数器持续十分钟;等过了一个小时后,时间差超过3600,才发送一封邮件告警时间差大于一小时,然后重置计数器

20.26 运行告警系统

一般是写一个任务计划cron

crontab -e

* * * * *   cd /usr/local/sbin/mon/bin;bash main.sh

#本次实验不需要定义log日志,可以先将main.sh定义log的语句注释掉

手动运行main.sh脚本

猜你喜欢

转载自blog.csdn.net/Lucky_LGX/article/details/87978187