zoukankan      html  css  js  c++  java
  • 30个关于Shell脚本的经典案例(上)

    对于初学者而言,因为没有实战经验,写不出来Shell脚本很正常,如果工作了几年的运维老年还是写不出来,那就是没主动找需求,缺乏练习,缺乏经验。针对以上问题,总结了30个生产环境中经典的Shell脚本,通过这些需求案例,希望能帮助大家提升Shell编写思路,掌握编写技巧。
    先了解下编写Shell过程中注意事项:
    开头加解释器:#!/bin/bash
    语法缩进,使用四个空格;多加注释说明。
    命名建议规则:变量名大写、局部变量小写,函数名小写,名字体现出实际作用。
    默认变量是全局的,在函数中变量local指定为局部变量,避免污染其他作用域。
    有两个命令能帮助我调试脚本:set -e 遇到执行非0时退出脚本,set-x 打印执行过程。
    写脚本一定先测试再到生产上。
    
    1、获取随机字符串或数字
    获取随机8位字符串:
    方法1:
    # echo $RANDOM |md5sum |cut -c 1-8
    471b94f2
    方法2:
    # openssl rand -base64 4
    vg3BEg==
    方法3:
    # cat /proc/sys/kernel/random/uuid |cut -c 1-8
    ed9e032c
    
    获取随机8位数字:
    方法1:
    # echo $RANDOM |cksum |cut -c 1-8
    23648321
    方法2:
    # openssl rand -base64 4 |cksum |cut -c 1-8
    38571131
    方法3:
    # date +%N |cut -c 1-8
    69024815
    
    cksum:打印CRC效验和统计字节
    
    2、定义一个颜色输出字符串函数
    方法1:
    function echo_color() {
        if [ $1 == "green" ]; then
            echo -e "33[32;40m$233[0m"
        elif [ $1 == "red" ]; then
            echo -e "33[31;40m$233[0m"
        fi
    }
    方法2:
    function echo_color() {
        case $1 in
            green)
                echo -e "[32;40m$2[0m"
                ;;
            red)
                echo -e "[31;40m$2[0m" 
                ;;
            *) 
                echo "Example: echo_color red string"
        esac
    }
    
    使用方法:echo_color green "test"
    
    function关键字定义一个函数,可加或不加。
    
    3、批量创建用户
    #!/bin/bash
    DATE=$(date +%F_%T)
    USER_FILE=user.txt
    echo_color(){
        if [ $1 == "green" ]; then
            echo -e "[32;40m$2[0m"
        elif [ $1 == "red" ]; then
            echo -e "[31;40m$2[0m"
        fi
    }
    # 如果用户文件存在并且大小大于0就备份
    if [ -s $USER_FILE ]; then
        mv $USER_FILE ${USER_FILE}-${DATE}.bak
        echo_color green "$USER_FILE exist, rename ${USER_FILE}-${DATE}.bak"
    fi
    echo -e "User	Password" >> $USER_FILE
    echo "----------------" >> $USER_FILE
    for USER in user{1..10}; do
        if ! id $USER &>/dev/null; then
            PASS=$(echo $RANDOM |md5sum |cut -c 1-8)
            useradd $USER
            echo $PASS |passwd --stdin $USER &>/dev/null
            echo -e "$USER	$PASS" >> $USER_FILE
            echo "$USER User create successful."
        else
            echo_color red "$USER User already exists!"
        fi
    done
    
    4、检查软件包是否安装
    #!/bin/bash
    if rpm -q sysstat &>/dev/null; then
        echo "sysstat is already installed."
    else
        echo "sysstat is not installed!"
    fi
    
    5、检查服务状态
    #!/bin/bash
    PORT_C=$(ss -anu |grep -c 123)
    PS_C=$(ps -ef |grep ntpd |grep -vc grep)
    if [ $PORT_C -eq 0 -o $PS_C -eq 0 ]; then
        echo "内容" | mail -s "主题" dst@example.com
    fi
    
    6、检查主机存活状态
    方法1:将错误IP放到数组里面判断是否ping失败三次
    #!/bin/bash  
    IP_LIST="192.168.18.1 192.168.1.1 192.168.18.2"
    for IP in $IP_LIST; do
        NUM=1
        while [ $NUM -le 3 ]; do
            if ping -c 1 $IP > /dev/null; then
                echo "$IP Ping is successful."
                break
            else
                # echo "$IP Ping is failure $NUM"
                FAIL_COUNT[$NUM]=$IP
                let NUM++
            fi
        done
        if [ ${#FAIL_COUNT[*]} -eq 3 ];then
            echo "${FAIL_COUNT[1]} Ping is failure!"
            unset FAIL_COUNT[*]
        fi
    done
    
       方法2:将错误次数放到FAIL_COUNT变量里面判断是否ping失败三次
    #!/bin/bash  
    IP_LIST="192.168.18.1 192.168.1.1 192.168.18.2"
    for IP in $IP_LIST; do
        FAIL_COUNT=0
        for ((i=1;i< =3;i++)); do
            if ping -c 1 $IP >/dev/null; then
                echo "$IP Ping is successful."
                break
            else
                # echo "$IP Ping is failure $i"
                let FAIL_COUNT++
            fi
        done
        if [ $FAIL_COUNT -eq 3 ]; then
            echo "$IP Ping is failure!"
        fi
    done
    
    方法3:利用for循环将ping通就跳出循环继续,如果不跳出就会走到打印ping失败
    #!/bin/bash
    ping_success_status() {
        if ping -c 1 $IP >/dev/null; then
            echo "$IP Ping is successful."
            continue
        fi
    }
    IP_LIST="192.168.18.1 192.168.1.1 192.168.18.2"
    for IP in $IP_LIST; do
        ping_success_status
        ping_success_status
        ping_success_status
        echo "$IP Ping is failure!"
    done
    
    7、监控CPU、内存和硬盘利用率
    1)CPU
    借助vmstat工具来分析CPU统计信息。
    
    #!/bin/bash
    DATE=$(date +%F" "%H:%M)
    IP=$(ifconfig eth0 |awk -F  [ :]+   /inet addr/{print $4} )  # 只支持CentOS6
    MAIL="example@mail.com"
    if ! which vmstat &>/dev/null; then
        echo "vmstat command no found, Please install procps package." 
        exit 1
    fi
    US=$(vmstat |awk  NR==3{print $13} )
    SY=$(vmstat |awk  NR==3{print $14} )
    IDLE=$(vmstat |awk  NR==3{print $15} )
    WAIT=$(vmstat |awk  NR==3{print $16} )
    USE=$(($US+$SY))
    if [ $USE -ge 50 ]; then
        echo "
        Date: $DATE
        Host: $IP
        Problem: CPU utilization $USE
        " | mail -s "CPU Monitor" $MAIL
    fi
    
    2)内存
    #!/bin/bash
    DATE=$(date +%F" "%H:%M)
    IP=$(ifconfig eth0 |awk -F  [ :]+   /inet addr/{print $4} )  
    MAIL="example@mail.com"
    TOTAL=$(free -m |awk  /Mem/{print $2} )
    USE=$(free -m |awk  /Mem/{print $3-$6-$7} )
    FREE=$(($TOTAL-$USE))
    # 内存小于1G发送报警邮件
    if [ $FREE -lt 1024 ]; then
        echo "
        Date: $DATE
        Host: $IP
        Problem: Total=$TOTAL,Use=$USE,Free=$FREE
        " | mail -s "Memory Monitor" $MAIL
    fi
    
    3)硬盘
    #!/bin/bash
    DATE=$(date +%F" "%H:%M)
    IP=$(ifconfig eth0 |awk -F  [ :]+   /inet addr/{print $4} )  
    MAIL="example@mail.com"
    TOTAL=$(fdisk -l |awk -F [: ]+   BEGIN{OFS="="}/^Disk /dev/{printf "%s=%sG,",$2,$3} )
    PART_USE=$(df -h |awk  BEGIN{OFS="="}/^/dev/{print $1,int($5),$6} )
    for i in $PART_USE; do
        PART=$(echo $i |cut -d"=" -f1)
        USE=$(echo $i |cut -d"=" -f2)
        MOUNT=$(echo $i |cut -d"=" -f3)
        if [ $USE -gt 80 ]; then
            echo "
            Date: $DATE
            Host: $IP
            Total: $TOTAL
            Problem: $PART=$USE($MOUNT)
            " | mail -s "Disk Monitor" $MAIL
        fi
    done
    
    8、批量主机磁盘利用率监控
    前提监控端和被监控端SSH免交互登录或者密钥登录。
    
    写一个配置文件保存被监控主机SSH连接信息,文件内容格式:IP User Port
    
    #!/bin/bash
    HOST_INFO=host.info
    for IP in $(awk  /^[^#]/{print $1}  $HOST_INFO); do
        USER=$(awk -v ip=$IP  ip==$1{print $2}  $HOST_INFO)
        PORT=$(awk -v ip=$IP  ip==$1{print $3}  $HOST_INFO)
        TMP_FILE=/tmp/disk.tmp
        ssh -p $PORT $USER@$IP  df -h  > $TMP_FILE
        USE_RATE_LIST=$(awk  BEGIN{OFS="="}/^/dev/{print $1,int($5)}  $TMP_FILE)
        for USE_RATE in $USE_RATE_LIST; do
            PART_NAME=${USE_RATE%=*}
            USE_RATE=${USE_RATE#*=}
            if [ $USE_RATE -ge 80 ]; then
                echo "Warning: $PART_NAME Partition usage $USE_RATE%!"
            fi
        done
    done
    
    9、检查网站可用性
    1)检查URL可用性
    方法1:
    check_url() {
        HTTP_CODE=$(curl -o /dev/null --connect-timeout 3 -s -w "%{http_code}" $1)
        if [ $HTTP_CODE -ne 200 ]; then
            echo "Warning: $1 Access failure!"
        fi
    }
    方法2:
    check_url() {
    if ! wget -T 10 --tries=1 --spider $1 >/dev/null 2>&1; then  
    #-T超时时间,--tries尝试1次,--spider爬虫模式
            echo "Warning: $1 Access failure!"
        fi
    }
    
    使用方法:check_url www.baidu.com
    
    2)判断三次URL可用性
    思路与上面检查主机存活状态一样。
    
    方法1:利用循环技巧,如果成功就跳出当前循环,否则执行到最后一行
    
    #!/bin/bash  
    check_url() {
        HTTP_CODE=$(curl -o /dev/null --connect-timeout 3 -s -w "%{http_code}" $1)
        if [ $HTTP_CODE -eq 200 ]; then
            continue
        fi
    }
    URL_LIST="www.baidu.com www.agasgf.com"
    for URL in $URL_LIST; do
        check_url $URL
        check_url $URL
        check_url $URL
        echo "Warning: $URL Access failure!"
    done
    
       方法2:错误次数保存到变量
    
    #!/bin/bash  
    URL_LIST="www.baidu.com www.agasgf.com"
    for URL in $URL_LIST; do
        FAIL_COUNT=0
        for ((i=1;i< =3;i++)); do
            HTTP_CODE=$(curl -o /dev/null --connect-timeout 3 -s -w "%{http_code}" $URL)
            if [ $HTTP_CODE -ne 200 ]; then
                let FAIL_COUNT++
            else
                break
            fi
        done
        if [ $FAIL_COUNT -eq 3 ]; then
            echo "Warning: $URL Access failure!"
        fi
    done
    
       方法3:错误次数保存到数组
    
    
    #!/bin/bash  
    URL_LIST="www.baidu.com www.agasgf.com"
    for URL in $URL_LIST; do
        NUM=1
        while [ $NUM -le 3 ]; do
            HTTP_CODE=$(curl -o /dev/null --connect-timeout 3 -s -w "%{http_code}" $URL)
            if [ $HTTP_CODE -ne 200 ]; then
                FAIL_COUNT[$NUM]=$IP  #创建数组,以$NUM下标,$IP元素
                let NUM++
            else
                break
            fi
        done
        if [ ${#FAIL_COUNT[*]} -eq 3 ]; then
            echo "Warning: $URL Access failure!"
            unset FAIL_COUNT[*]    #清空数组
        fi
    done
    
    10、检查MySQL主从同步状态
    #!/bin/bash  
    USER=bak
    PASSWD=123456
    IO_SQL_STATUS=$(mysql -u$USER -p$PASSWD -e  show slave statusG  |awk -F:  /Slave_.*_Running/{gsub(": ",":");print $0} )  #gsub去除冒号后面的空格
    for i in $IO_SQL_STATUS; do
        THREAD_STATUS_NAME=${i%:*}
        THREAD_STATUS=${i#*:}
        if [ "$THREAD_STATUS" != "Yes" ]; then
            echo "Error: MySQL Master-Slave $THREAD_STATUS_NAME status is $THREAD_STATUS!"
        fi
    done
    

    动手练一练,让你的Shell功底上升一个段位!

    未完待续...

  • 相关阅读:
    POJ 1953 World Cup Noise
    POJ 1995 Raising Modulo Numbers (快速幂取余)
    poj 1256 Anagram
    POJ 1218 THE DRUNK JAILER
    POJ 1316 Self Numbers
    POJ 1663 Number Steps
    POJ 1664 放苹果
    如何查看DIV被设置什么CSS样式
    独行DIV自适应宽度布局CSS实例与扩大应用范围
    python 从入门到精通教程一:[1]Hello,world!
  • 原文地址:https://www.cnblogs.com/linuxprobe/p/11478692.html
Copyright © 2011-2022 走看看