第二十章、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"
 
改進:一、判斷是不是系統的網卡
          二、判斷網卡是否有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 languoxin_test@163.com "$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腳本
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"
 
改進:一、判斷是不是系統的網卡
          二、判斷網卡是否有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 languoxin_test@163.com "$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腳本
相關文章
相關標籤/搜索