1. 程式人生 > >32 shell(2)

32 shell(2)

20.16 shell中的函式(上)

函式就是把一段程式碼整理到了一個小單元中,並給這個小單元起一個名字,當用到這段程式碼時直接呼叫這個小單元的名字即可。
函式必須要放在最前面

格式: function f_name() {
                      command
             }

1.[[email protected] ~]# vi fun1.sh   # 新增內容:

#!/bin/bash
function inp(){
   echo "The first par is $1"
   echo "The second par is $2"
   echo "The third par is $3"
   echo "the scritp name is $0"
   echo "the number of par is $#"
}
inp $1 $2 $3

2. 執行fun1.sh指令碼,後面跟函式

[[email protected] test]# sh fun1.sh 1 2   後面跟引數
The first par is 1
The second par is 2
The third par is 
the scritp name is fun1.sh
the number of par is 2

20.17 shell中的函式(下)

1. 加法函式:[[email protected] ~]# vi fun2.sh   #新增內容:

#!/bin/bash
sum() {
   s=$[$1+$2]
   echo $s
}
sum 1 10
echo $s

2. 執行fun2.sh指令碼:[[email protected] ~]# sh -x fun2.sh  # -x看到執行過程

1. 輸入網絡卡名字,顯示網絡卡ip:[[email protected] ~]# vi fun3.sh    #新增內容:

#!/bin/bash
ip()
{
   ifconfig |grep -A1 "$1: "|awk '/inet/ {print $2}'
}                                                                            #  以上為函式體
read -p "please input the eth name: " ech
ip $eth
#ifconfig 查詢IP地址
#grep -A1 "$1" 查詢第一段
#awk '/inet/ '{print $2}' 查詢inet字元列出後列印第二列(即IP地址)

2. 執行fun3.sh指令碼:

[[email protected] ~]# sh fun3.sh
please input the eth name: ens33

20.18 shell中的陣列

1. 定義陣列:[[email protected] ~]# a=(1 2 3 4 5)

2. 檢視a陣列的元素:[[email protected] ~]# echo ${a[*]}  #  1 2 3 4 5

3. 檢視陣列某個元素的值(陣列從0開始值為1):[[email protected] ~]# echo ${a[1]}  #1 2 3 4 5

4. 獲取陣列的元素 個數:[[email protected] ~]# echo ${#a[*]}   # 5

5. 如果下標不存在則會自動新增一個元素:
[[email protected] ~]# a[5]=b
[[email protected] ~]# echo ${a[*]}       #  1 2 6 4 5 a

陣列元素賦值(更改替換):
[[email protected] ~]# a[5]=bbb
[[email protected] ~]# echo ${a[*]}

6. 刪除陣列元素:#刪除數組裡的一個值只需 unset a[下標] ---unset a[0]
[[email protected] shell]# unset a[0]
[[email protected] shell]# echo ${a[*]}
2 6 4 5 bbb

7. 刪除(清空)陣列值:
[[email protected] ~]# unset a
[[email protected] ~]# echo ${a[*]}

8. 設定陣列:
[[email protected] ~]# a=(`seq 1 10`)
[[email protected] ~]# echo ${a[*]}

9. 從第1個元素開始,截取出5個數值:[[email protected] ~]# echo ${a[*]:0:5}

從第2個元素開始,截取出5個數值:[[email protected] ~]# echo ${a[*]:1:5}

10. 從倒數第3個元素開始,截取出2個數值:[[email protected] ~]# echo ${a[*]:0-3:2}

11. 擷取替換,8元素列印成cc66:[[email protected] ~]# echo ${a[@]/8/cc66}

12. 替換元素值,8元素替換成cc66:[[email protected] ~]# a=(${a[*]/8/cc66})

替換元素值,cc66元素替換成888:[[email protected] ~]# a=(${a[*]/cc66/888})

[[email protected] ~]# echo ${a[*]}

20.19 告警系統需求分析

1. 需求:使用shell定製各種個性化告警工具,但需要統一化管理、規範化管理。
2. 思路:指定一個指令碼包,包含主程式、子程式、配置檔案、郵件引擎、輸出日誌等。
3. 主程式:作為整個指令碼的入口,是整個系統的命脈。
4. 配置檔案:是一個控制中心,用它來開關各個子程式,指定各個相關聯的日誌檔案。
5. 子程式:這個才是真正的監控指令碼,用來監控各個指標。
6. 郵件引擎:是由一個python程式來實現,它可以定義發郵件的伺服器、發郵件人以及發件人密碼
7. 輸出日誌:整個監控系統要有日誌輸出。

1. 要求:我們的機器角色多種多樣,但是所有機器上都要部署同樣的監控系統,也就說所有機器不管什麼角色,整個程式框架都是一致的,不同的地方在於根據不同的角色,定製不同的配置檔案。

2. 程式架構:

bin下是:主程式
conf下是:配置檔案
shares下是:各個監控指令碼
mail下是:郵件引擎
log下是:日誌

20.20 告警系統主指令碼

約定:所有指令碼都放在 /usr/local/bin目錄下!
shell專案-告警系統main.sh

1. 在/usr/local/bin/目錄下,建立一個mon目錄 :[[email protected]~]# mkdir /usr/local/bin/mon

2. 進入.../mon目錄下 :[[email protected]~]# cd /usr/local/bin/mon

3. 在 /usr/local/bin/mon目錄下,建立以下目錄 :[[email protected] mon]# mkdir bin conf shares log mail

4. 在/usr/local/bin/mon/bin下,建立main.sh主指令碼 :[[email protected] mon]# vim /usr/local/bin/mon/bin/main.sh  #新增內容:

#!/bin/bash
#Written by panyu.
# 是否傳送郵件的開關
export send=1
# 過濾ip地址,第二段是ip
export addr=ifconfig |grep -A1 "ens33:  "|awk '/inet/ {print $2}'                      
dir=`pwd`
# 只需要最後一級目錄名
last_dir=`echo $dir|awk -F'/' '{print $NF}'`
# 下面的判斷目的是,保證執行指令碼的時候,我們在/usr/local/bin/mon/bin目錄裡,不然監控指令碼、郵件和日誌很有可能找不到
if [ $last_dir == "bin" ] || [ $last_dir == "bin/" ]; then
   conf_file="../conf/mon.conf"    # bin的父級目錄/usr/local/bin/mon下配置檔案mon.conf
else
   echo "you shoud cd bin dir"
   exit

fi
# 記錄正確日誌和錯誤日誌  exec建立一個子程序
exec 1>>../log/mon.log 2>>../log/err.log
# 顯示執行時間
echo "`date +"%F %T"` load average"
/bin/bash ../shares/load.sh  #監控指令碼
#先檢查配置檔案中是否需要監控502  #執行監控指令碼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 告警系統配置檔案

shell專案-告警系統mon.conf 

1. 在/usr/local/bin/mon/conf下,建立mon.conf配置檔案 :[[email protected] mon]# vim /usr/local/bin/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
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  需要定義訪問日誌的路徑 (0關閉,1開啟)
to_mon_502=1
logfile=/data/log/xxx.xxx.com/access.log
## request_count   定義日誌路徑以及域名 
to_mon_request_count=0
req_log=/data/log/www.discuz.net/access.log
domainname=www.discuz.net

20.22 告警系統監控專案

shell專案-告警系統load.sh

在/usr/local/bin/mon/shares下,建立load.sh子指令碼 :[[email protected] ~]# vim /usr/local/bin/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` ##求出負載值
if [ $load -gt 10 ] && [ $send -eq "1" ] #判斷當負載大於10並且傳送郵件開關等於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" #顯示執行時間

shell專案-告警系統502.sh

 在/usr/local/bin/mon/shares下,建立502.sh子指令碼 :[[email protected] ~]# vim /usr/local/bin/mon/shares/502.sh   #新增內容:

#! /bin/bash
d=`date -d "-1 min" +%H:%M` #定義前一分鐘時間
c_502=`grep :$d:  $log  |grep ' 502 '|wc -l`  #定義c_502變數:查詢日誌
if [ $c_502 -gt 10 ] && [ $send == 1 ]; then #如果發現502大於10並且郵件關開等於1
     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"

shell專案-告警系統disk.sh

在/usr/local/bin/mon/shares下,建立disk.sh子指令碼 :[[email protected] ~]# vim /usr/local/bin/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`  #定義r變數為檢視磁碟使用率,下面的[ %]表示空格和百分號都當分隔符
do
    if [ $r -gt 90 ] && [ $send -eq "1" ]  #如果使用率大於90並且郵件開關等於1
then
    echo "$addr `date +%T` disk useage is $r" >>../log/disk.tmp  #記錄日誌
fi 
if [ -f ../log/disk.tmp ]  #查詢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 告警系統郵件引擎(上中下)

shell專案-告警系統mail.sh

1. 建立mail.py指令碼 :[[email protected] ~]# vim /usr/local/bin/mon/mail/mail.py

#####指令碼使用說明######
#1. 首先定義好指令碼中的郵箱賬號和密碼
#2. 指令碼執行命令為:python mail.py 目標郵箱 "郵件主題" "郵件內容"    # 新增內容 :

內容參考https://coding.net/u/aminglinux/p/aminglinux-book/git/blob/master/D22Z/mail.py

#!/usr/bin/env python
#-*- coding: UTF-8 -*-
import os,sys
reload(sys)
sys.setdefaultencoding('utf8')
import getopt
import smtplib
from email.MIMEText import MIMEText
from email.MIMEMultipart import MIMEMultipart
from  subprocess import *
 def sendqqmail(username,password,mailfrom,mailto,subject,content):
    gserver = 'smtp.qq.com'
    gport = 25
 

   try:
        msg = MIMEText(unicode(content).encode('utf-8'))
        msg['from'] = mailfrom
        msg['to'] = mailto
        msg['Reply-To'] = mailfrom
        msg['Subject'] = subject
 
        smtp = smtplib.SMTP(gserver, gport)
        smtp.set_debuglevel(0)
        smtp.ehlo()
        smtp.login(username,password)
 
        smtp.sendmail(mailfrom, mailto, msg.as_string())
        smtp.close()
    except Exception,err:
        print "Send mail failed. Error: %s" % err
 def main():
    to=sys.argv[1]
    subject=sys.argv[2]
    content=sys.argv[3]
##定義QQ郵箱的賬號和密碼,你需要修改成你自己的賬號和密碼(請不要把真實的使用者名稱和密碼放到網上公開,否則你會死的很慘)
    sendqqmail('[email protected]','aaaaaaaaaa','[email protected]',to,subject,content)
 if __name__ == "__main__":
    main()
#####指令碼使用說明######
#1. 首先定義好指令碼中的郵箱賬號和密碼
#2. 指令碼執行命令為:python mail.py 目標郵箱 "郵件主題" "郵件內容"

2. 設定mail.py指令碼許可權為755 :[[email protected] ~]# chmod 755 /usr/local/bin/mon/mail/mail.py

3. 建立mail.sh指令碼 :[[email protected] ~]# vim /usr/local/bin/mon/mail/mail.sh  #新增內容 :

mail.sh內容 //其中mail.py內容到這裡下載https://coding.net/u/aminglinux/p/aminglinux-book/git/blob/master/D22Z/mail.py

#定義mail.sh 的第一個引數,為了區分
log=$1
#定義時間戳
t_s=`date +%s`
#定義2個小時前的時間戳
t_s2=`date -d "2 hours ago" +%s`
#如果tmp下沒有log日誌
if [ ! -f /tmp/$log ]
then
#建立日誌並把2小時前的時間戳寫入進去
    echo $t_s2 > /tmp/$log
fi
#覆蓋上面的t_s2的值並擷取日誌最後一行時間戳作為變數
t_s2=`tail -1 /tmp/$log|awk '{print $1}'`
#寫入當前時間戳
echo $t_s>>/tmp/$log
#定義V變數。計算2個比值的時間差 當前時間-2小時前的時間
v=$[$t_s-$t_s2]
#顯示算出的時間
echo $v
#如果時間大於3600秒
if [ $v -gt 3600 ]
then
#呼叫mail.py告警 $1.2.3是主題,傳送人、....
    ./mail.py  $1  $2  $3
#生成一個新日誌log.txt(目的是為了計數)
    echo "0" > /tmp/$log.txt
#如果小於3600執行如下
else
#如果log.txt計數器檔案不存在
    if [ ! -f /tmp/$log.txt ]
    then
#則建立並寫入0
        echo "0" > /tmp/$log.txt
    fi
#檢視計數器數值
    nu=`cat /tmp/$log.txt`
#nu變數基礎上+1
    nu2=$[$nu+1]
#nu2+完1的數值寫入到log.txt
    echo $nu2>/tmp/$log.txt
#如果數值大於10
    if [ $nu2 -gt 10 ]
    then
#告警
         ./mail.py  $1 "trouble continue 10 min $2" "$3"
#並清空計數器,重新計數
         echo "0" > /tmp/$log.txt
    fi
fi  

20.26 執行告警系統

1. 暫時關閉掉502:[[email protected] ~]# vim /usr/local/bin/mon/conf/mon.conf

clipboard.png

2. 暫時註釋掉main.sh指令碼中日誌行:[[email protected] ~]# vim /usr/local/bin/mon/bin/main.sh

clipboard.png

3. 執行main.sh[[email protected] ~]# sh -x /usr/local/bin/mon/bin/main.sh

4. 執行load.sh[[email protected] ~]# bash /usr/local/bin/mon/shares/load.sh

clipboard.png