Shell脚本进阶案例


目录:

job-监控磁盘使用率

案例需求

打印磁盘使用率脚本,对本机的磁盘使用率统计并打印结果 使用率小于80,绿色输出 使用率小于90,大于80,黄色输出 使用率小于95,大于90,红色输出

脚本应用场景:

磁盘使用率监控一般周期为小时、天,不会太频繁。

监控平台+监控脚本

计划任务+监控脚本

手动监控

解决问题

及时掌握磁盘容量,防止100%造成磁盘无法读取。

脚本思路

  1. 检索本机磁盘
  2. 判断磁盘使用率
  3. 输出结果

实现代码

#!/bin/bash
# 
#Author: www.zuolaoshi.cn
#Created Time: 
#Release: 
#Description: 

#指定for条件的分割符为回车,一行一个条件
IFS=$'\n'

#1、遍历符合条件的每一行磁盘数据
for i in `df -Th|egrep -v "(tmpfs|sr0)"|tail -n +2|tr -s " "`;do
size=`echo $i|cut -d " " -f6|tr -d "%"`
name=`echo $i|cut -d " " -f1`

#2、判断每行中的磁盘使用率并输出结果
 if [ $size -ge 95 ];then
    #3、输出日志并关机,不许在写入数据
    logger "ERROR:$name use is $size.halt"
    halt -p
 elif [ $size -ge 90 ];then

    echo -e "\033[31m $name use is ${size}%\033[0m"
 elif [ $size -ge 80 ];then
    echo -e "\033[33m $name use is ${size}%\033[0m"
 else
    echo -e "\033[32m$name use is ${size}%\033[0m"
 fi
done

案例思考

思考磁盘IO队列、吞吐率、IOPS的监控方法

监控接口

案例需求

URL监控脚本,对某个URL进行监控,返回值为200则代表成功访问。

脚本应用场景:

WEB站点监控

解决问题

URL监控

页面监控

脚本思路

1、使用curl访问一次URL,并将输出保存

2、访问输出文件,获取返回值

3、判断返回值是否和初始预设的返回值相等,并对应输出

实现代码

#!/bin/bash
# 
#Author: www.zuolaoshi.cn
#Created Time: 
#Release: 
#Description: URL监控脚本
#监控阈值可以是: 状态码、页面字符串、页面所有内容
#本例以状态码为例

#variables
init_url_status=200
temp_file=`mktemp /tmp/check_url.XXX`

#help
if [ -z "$1" ]||[ "$1" == "--help" ];then
   echo "$0 url"
   echo "--help: 打印该帮助"
fi

#如果用户没有传参则退出
[ $# -lt 1 ]&&exit 1
#main

#1、使用curl命令访问一次URL
#1.1 判断脚本依赖命令是否存在
[ ! -x /usr/bin/curl ]&&echo "curl: not found command"&&exit 1

#1.2 访问一次URL
curl -I $1 &> $temp_file


#2、从输出中截取状态码
url_status=`grep "HTTP/1.1" $temp_file|cut -d " " -f2`

#2.1如果取值失败直接报错(测试发现当无法访问URL时会在第三步中报比较错误,所以这里取不到值就不往下走了)
[ -z "$url_status" ]&&echo -e "\033[31mstatus:NULL\033[0m"&&exit 1


#3、判断状态码是否和预设的一致
    #3.1 一致  输出绿色字体 "status:200"
    #3.2 不一致 输出红色字体 "status:XXX"

if [ $init_url_status -eq $url_status ];then
    echo -e "\033[32mstatus:$url_status\033[0m"
else
    echo -e "\033[31mstatus:$url_status\033[0m"
fi

#4、删除临时文件
rm -f $temp_file

案例思考

页面监控方法(监控页面字符串或全页内容)

监控内存使用率

案例需求

打印内存使用率脚本,打印内存使用率、swap使用率、buff&cache使用量

实现效果

#实现演示
内存使用率: 2.69%,buff&cache:535 MB
Swap使用率: 0%

脚本应用场景:

监控平台+内存监控脚本

手动监控

解决问题

随时掌握业务对内存的占用,合理使用内存资源

脚本思路

1、获取物理内存、swap的相关数据

1.1通过数据检索获得物理内存总量、Swap的总量

1.2通过数据检索获得物理内存的使用量,Swap的使用量

1.3通过检索获得物理内存buff&cache的量

2、调用相关数据进行运算,并输出结果

实现代码

#!/bin/bash
# 
#Author: www.zuolaoshi.cn
#Created Time: 
#Release: 
#Description:内存使用率计算脚本

#1、通过free命令结合数据处理获得对应数据
#1.1、获得内存总量
memory_totle=`free -m|grep -i "mem"|tr -s " "|cut -d " " -f2`
swap_totle=`free -m|grep -i "swap"|tr -s " "|cut -d " " -f2`
#1.2、获得内存使用的量
memory_use=`free -m|grep -i "mem"|tr -s " "|cut -d " " -f3`
swap_use=`free -m|grep -i "swap"|tr -s " "|cut -d " " -f3`
#1.3、buff/cache
buff_cache=`free -m|grep -i "mem"|tr -s " "|cut -d " " -f6`

#2、计算输出
#运算的时候是否需要小数点 浮点运算,要考虑使用的命令 (难点 重点)
#echo "内存使用率: $((memory_use*100/memory_totle))%"
#难点:浮点运算中,同优先级的情况下,大数除以小数 尽可能保证精确
echo "内存使用率: `echo "scale=2;$memory_use*100/$memory_totle"|bc`%,buff&cache:$buff_cache MB"
echo "Swap使用率: `echo "scale=2;$swap_use*100/$swap_totle"|bc`%"

案例思考

内存获取的方式
内存占用的优先级

job-网卡流量监控

案例需求

网卡发送和就收数据量监控,按秒统计。

思考: 如何获取某块网卡上一秒的流入、流出数据流量 ifconfig中可以获得,你知道吗?

网卡流量.png

脚本应用场景:

动态监控网卡的流量

解决问题

实时掌握网卡的流量,掌握带宽使用情况

脚本思路

1、获得网卡当前流入流出总量

2、休息一秒

3、获得网卡当前流入流出总量

4、运算得出上一秒网卡流量

5、输出结果

实现代码

#!/bin/bash
# 
#Author: www.zuolaoshi.cn
#Created Time: 
#Release: 
#Description: 网卡流量监控


#脚本用法
#判断用户是否传参
if [ -z "$1"] || [ "$1" == "--help" ];then
  cat << EOF
$0 网卡名称
--help 打印帮助菜单
EOF
fi



#如果用户没有传参,则退出脚本
[ $# -lt 1 ]&&exit 1

#第一次取值
#1、获得当前网卡流量 初始化值
NIC_RX=`ifconfig $1|grep "RX packets"|tr -s " "|cut -d " " -f6`
NIC_TX=`ifconfig $1|grep "TX packets"|tr -s " "|cut -d " " -f6`

#休息一秒开始循环
sleep 1


#循环开始监控网卡流量 监控频率 1s
while :
  do
     #2、监控当前网络的流量,第二次取值
     NIC_RX_1=`ifconfig $1|grep "RX packets"|tr -s " "|cut -d " " -f6`
     NIC_TX_1=`ifconfig $1|grep "TX packets"|tr -s " "|cut -d " " -f6`  

     #3、制作输出
     #3.1、清屏输出下文
     clear
     echo -e "\t$1 网卡流量监控"
     echo "----------------------------------------"
     echo -e "网卡: $1\n"
     #3.2、运算得出结论
      echo -e "发送:\t$((NIC_TX_1-NIC_TX))B/s\t接收:\t$((NIC_RX_1-NIC_RX))B/s"

     #重新赋值网卡初始化流入流出变量
     NIC_RX=$NIC_RX_1
     NIC_TX=$NIC_TX_1

     #休眠1秒,进入下一次循环
     sleep 1
done

案例思考

如何采用图表的方式输出网卡信息

判断目录

案例需求

判断/tmp/run目录是否存在,如果不存在就建立,如果存在就删除目录里所有文件

脚本应用场景:

脚本中对文件和文件夹类型的及权限的判断

解决问题

避免文件或者文件夹的重复建立问题

脚本思路

  1. 判断文件夹/tmp/run目录是否存在
  2. 存在 删除目录下内容
  3. 不存在 退出脚本

实现代码

#!/bin/bash
# 
#Author: www.zuolaoshi.cn
#Created Time: 
#Release: 
#Description: 判断/tmp/run目录是否存在

#1、判断文件夹/tmp/run目录是否存在
if [ -d /tmp/run ];then
   #2、存在 删除目录下内容
   rm -rf /tmp/run/*
else
   #3、不存在 退出脚本
   exit 0
fi

判断服务状态

案例需求

判断计算机某个端口是否为OPEN状态,且能正常访问

脚本应用场景:

服务监控脚本+监控平台

手动监控

解决问题

实时掌握服务的运行状态,及时处理问题。

脚本思路

1、使用telnet命令连接远端机器的远端端口

2、接收连接反馈并分析结果

3、分析文件内容

4、打印结果

实现代码

#!/bin/bash
#Description: 
#Author: www.zuolaoshi.cn
#Created Time: 
#监控一个服务端口


#main

temp_file=`mktemp port_status.XXX`

#1、判断依赖命令telnet是否存在
[ ! -x /usr/bin/telnet ]&&echo "telnet: not found command"&& exit 1

#2、测试端口 $1 IP    $2 port
( telnet $1 $2 <<EOF
quit
EOF
) &>$temp_file

#3、分析文件中的内容,判断结果
if egrep "\^]" $temp_file &>/dev/null;then
     #4、打印结果
   echo "$1 $2 is open"
else
   echo "$1 $2 is close"
fi

#5、删除临时文件
rm -f $temp_file

案例思考

#监控方法
#1)通过systemctl  service   服务启动状态  
#2)lsof 查看端口是否存在
#3)查看进程是否存在
   注意  压力过大 无法响应 |  服务down了  上述东西还在  监测不准确

#4)测试端口是否有响应    推荐
    #telnet 协议 

闰年判断

案例需求

闰年判断:判断某年是否问闰年

闰年判断方法:

普通闰年:能被4整除但不能被100整除的年份为普通闰年。(如2004年就是闰年,1900年不是闰年) 世纪闰年:能被400整除的为世纪闰年。(如2000年是世纪闰年,1900年不是世纪闰年)

脚本应用场景:

时间类型脚本总总时间的统计。

解决问题

时间计算中从某一年到某一年天数的统计 ,解决了闰年、平年的天数不同的问题。

脚本思路

1、交互输入year

2、根据公式判断输出

3、输出判断结果

实现代码

#!/bin/bash
# 
#Author: www.zuolaoshi.cn
#Created Time: 
#Release: 
#Description:闰年判断脚本

#variables


#main
#1、交互输入要判断的年
read -p "输入一个年份: " year



#2、判断
if [ -z "$year" ];then
   echo "$0 year"
   exit 1
elif (($year%400==0));then
#3、输出结果
   echo "$year: 闰年"
elif (($year%4==0));then
   echo "$year: 闰年"
else
   echo "$year: 平年"
fi

主机状态监控脚本

案例需求

通过脚本判断远程计算机的存活状态

脚本应用场景

1、通过监控平台调用监控脚本对服务器进行监控

2、机器扫描

解决问题

1、运维人员实时掌控机器的状态,防止宕机或者由于压力过大造成请求处理延时,保障业务的稳定、高效运行

脚本思路

1、通过ICMP协议的ping命令ping目标主机

网络延迟,假报警如何解决?
  3次  

2、分析ping结果

3、给出结论

全部ping结果为假,报宕机
全部ping成功,报正常
否则报警告

实现代码

#!/bin/bash
# 
#Author: www.zuolaoshi.cn
#Created Time: 
#Release: 
#Description: 


#1、ping 目标主机三次,并接收每次的状态值,ping成功返回1,不成功返回0
for ((i=1;i<4;i++));do
#测试代码
   if ping -c1 $1 &>/dev/null;then

    #分析结果
        export ping_count"$i"=1

   else
        export ping_count"$i"=0
   fi

#时间间隔
   sleep 0.3
done

#3、分析结果
#  3次ping失败报警
# 
if [ $ping_count1 -eq $ping_count2 ] && [ $ping_count2 -eq $ping_count3 ]&&[ $ping_count1 -eq 0 ];then
    echo "$1  宕机"
elif [ $ping_count1 -eq $ping_count2 ] && [ $ping_count2 -eq $ping_count3 ]&&[ $ping_count1 -eq 1 ];then
    echo "$1  正常"
else
    echo "warn: $1 网络延迟"
fi 

#4、释放变量
unset ping_count1 
unset ping_count2  
unset ping_count3

案例思考

当你的机器放在IDC机房的时候,你如何判断各个运营商的用户到你服务器的以下数据。

网络延迟如何获得

网络丢包率如何获得

mysql备份脚本

案例需求

写一个mysql binlog备份脚本,要求每天0点0分,计算机自动备份前一天的binlog日志,打包后发送给备份服务器。

脚本应用场景:

文件备份

解决问题

日常文件备份

日常数据备份

脚本思路

1、确定binlog的位置及备份时间间隔 每天

当前要备份的binlog是谁

刷新binlog日志,生成新的binlog用于存储备份节点后的数据

2、打包binlog日志 以年-月-日_binlog.tar.gz格式

3、生成校验码 md5sum

4、将校验码和压缩包存入到文件夹 文件夹命名 年-月-日 再次打包

5、使用scp拷贝到备份机器

6、备份机器解压收到的目录压缩包 通过校验码 教研binlog压缩包是否完整

完整 完成备份 -----发邮件给管理员,明确备份成功

不完整 报错------发邮件给管理员,要求手动备份

实现代码

#!/bin/bash
#Description: 
#Author: www.zuolaoshi.cn
#Created Time: 
#将mysql的binlog日志备份到备份服务器


########variables
db_user='root'
db_password=''
log='/var/log/mysql_backup.log'



###main
#获得信息
binlog_dir='/var/lib/mysql'
current_binlog=`mysql -u $db_user -e "show master status"|egrep "binlog.[[:digit:]]*"|awk '{print $1}'`

date >> $log
#准备备份
#1 刷新binlog    
mysql -u $db_user -e "flush logs"
#2 打包要备份的binlog
tar czf `date +%F`_binlog.tar.gz $binlog_dir/$current_binlog &>>$log
#3 生成校验码
md5sum `date +%F`_binlog.tar.gz > "`date +%F`_md5sum.txt"
#4 存入文件夹
[ ! -d `date +%F` ]&&mkdir `date +%F`
mv  `date +%F`_binlog.tar.gz `date +%F`
mv `date +%F`_md5sum.txt `date +%F`

# 打包目录
tar czf `date +%F`.tar.gz `date +%F` &>>$log

#5 拷贝
#要求提前做证书信任
scp `date +%F`.tar.gz root@192.168.11.241:/opt/backup &>>$log
if [ $? -ne 0 ];then
    echo "ERROR:scp `date +%F`.tar.gz fail" &>>$log
    exit 1
fi

#6 校验
ssh root@192.168.11.241 "tar xf /opt/backup/`date +%F`.tar.gz -C /opt"
#ssh root@192.168.11.241 "cd /opt/backup`date +%F`"
ssh root@192.168.11.241 "cd /opt/`date +%F`;md5sum -c `date +%F`_md5sum.txt" &>>$log
if [ $? -eq 0 ];then
   echo "success" &>>$log
   ssh root@192.168.11.241 "rm -rf /opt/`date +%F`"
else
   echo "fail" &>>$log
fi

案例思考

双机同步实现方式

nginx安装脚本

案例需求

通过shell脚本安装nginx

应用场景

web服务器业务初始化

案例思路

1、软件获得 2、源码安装

案例代码

#!/bin/bash
#Description: nginx install script from zuolaoshi(http://www.zuolaoshi.cn)
#Release: 1.0
#Auther: www.zuolaoshi.cn
#Email: 
#OS: Centos 8.X

cat <<EOF
#Description: nginx install script from zuolaoshi(http://www.zuolaoshi.cn)
#Release: 1.0
#Auther: www.zuolaoshi.cn
#Email: 
#OS: Centos 8.X
EOF


#nginx源码包下载路径
nginx_pkg_url=http://nginx.org/download/nginx-1.17.8.tar.gz

#nginx安装路径,安装路径为$nginx_install_doc/nginx
nginx_install_doc=/usr/local

#nginx服务管理用户
nginx_manage_user=www

#统计本机CPU核数
cpu_count=`grep -c "flags" /proc/cpuinfo`

check ()  {

#安装nginx需要管理员权限 
[ $UID -ne 0 ] && echo "need to be root so that" && exit 1

#安装前的依赖包解决
#wget 命令
#gcc  编译命令
#pcre-devel  URL重写功能
#zlib-devel  压缩支持
#make  编译命令

if ! (yum -y install wget gcc pcre-devel zlib-devel make &>/dev/null);then
    echo "yum install soft package fail"
        exit 1
fi  

if ! (egrep "^www" /etc/passwd &>/dev/null);then
    useradd -s /sbin/nologin -r -M www
fi

}



nginx_install () {
#1、下载软件包
#if wget $nginx_pkg_url &>/dev/null;then
    #2、解压软件包
    echo $nginx_pkg_url|awk -F "/" '{print $5}'|xargs tar xf
    nginx_source_doc=`echo $nginx_pkg_url|awk -F "/" '{print $5}'|cut -d "." -f 1-3`
    #3、进入软件包
    if [ ! -d $nginx_source_doc ];then
      echo "unzip `echo $nginx_pkg_url|awk -F "/" '{print $5}'` fail"
          exit 1
        fi    

    cd $nginx_source_doc

    #4、configure nginx
    ./configure --prefix=$nginx_install_doc/nginx --user=$nginx_manage_user --group=$nginx_manage_user 1>/dev/null
    [ $? -ne 0 ]&&echo "nginx configure fail"&&exit 1

    #5、make nginx
    make -j $cpu_count 1>/dev/null
    [ $? -ne 0 ]&&echo "nginx make fail"&&exit 1

        #6、install nginx
    make install 1>/dev/null
    [ $? -ne 0 ]&&echo "nginx install fail"&&exit 1||echo "`clear`nginx install success..."

    #7、delete nginx soft package
    cd ..
    rm -rf ${nginx_source_doc}*

#else
#   echo "$nginx_pkg_url download fail"
#   exit 1
#fi   


}

#####callable function
check;nginx_install

Python安装脚本

案例需求

使用shell脚本安装Python环境

应用场景

服务器业务初始化

解决问题

避免人工多次安装,节省人工成本 避免人工错误,提高工作效率

脚本思路

1、获得软件包 2、源码安装 3、升级pip命令

案例代码

#!/bin/bash
#Description: python install from zuolaoshi(http://www.zuolaoshi.cn)
#Release: python 3.7.6
#Auther: zuolaoshi
#Email: 
#OS: Centos 8.X


#variables
python_download_url=https://www.python.org/ftp/python/3.7.6/Python-3.7.6.tgz
python_source_pkg=Python-3.7.6.tgz
python_code=Python-3.7.6


#functions
#安装前准备,安装必要依赖包
per_install () {
    if  ( ! yum -y install gcc-* openssl-* libffi-devel sqlite-devel &>/dev/null );then
    #if  ( ! yum -y install gcc-* openssl-* libffi-devel sqlite-devel ) &>/dev/null ;then
    echo -e "\033[31m network connection error,exit... \033[0m"
    exit 130
fi
}

#安装python
install () {
    #下载软件包
    wget $python_download_url
    #解压软件包
    if [ -f $python_source_pkg ];then
        tar xf $python_source_pkg
        [ $? -ne 0 ]&&echo "$python_source_pkg unzip fail"&&exit 1
        cd $python_code
        #配置,开启ssl支持https
        if ./configure --with-openssl=/usr/bin/openssl 1>/dev/null;then
            #mv Modules/Setup Modules/Setup.bak
            cp -f ../Setup Modules/
            if make 1>/dev/null;then
            #if make ;then
                if make install 1>/dev/null;then
                #if make install ;then
                    #if pip3 install --upgrade pip 1>/dev/null;then
                    #安装完成后更新pip
                    if pip3 install --upgrade pip;then
                        echo "python install success"
                    else
                        echo "pip3 install fail"
                        exit 1
                    fi
                else
                    echo "python install fail"
                    exit 1
                fi
            else
                echo "python make fail"
                exit 1
            fi
        else
            echo "python configure fail"
            exit
        fi
    else
        echo "not found $python_source_pkg"
        exit 1
    fi
}



per_install;install
rm -rf $python_code
rm -rf python_source_pkg