美文网首页
分享几个实用脚本

分享几个实用脚本

作者: 六月天的安静 | 来源:发表于2018-03-26 16:24 被阅读544次

    Shell面试题及企业运维实战案

    1、批量生成随机字符文件名:

    要求:使用for循环在/oldboy目录下批量创建10个html文件,其中每个文件需要包含10个随机小写字母加固定字符串oldboy
    问题分析:本题考查的第一个知识点就是生成10个随机小写字母,这里采用openssl命令的方法来实现。

    openssl  rand  -base64  40 | sed  ‘s#[^a-z]##g’ | cut -c 2-11
      //利用openssl生成40个随机数,并用sed将非小写字符删除,然后利用cut取出其中10位
    

    参考脚本

    [root@oldboy scripts]# cat randnum.sh
    #!/bin/sh
    Path = /oldboy                               //定义生成文件的路径
    [ -d "$Path" ] || mkdir -p $Path             //如果定义的路径不存在则创建。
    for n in `seq 10`
    do
    random = $(openssl rand -base64 40 | sed ‘s#[^a-z]##g’ | cut -c 2-11) 
                                          //将10位随机字符赋值给变量
    touch $Path/${random}_oldboy.html        //根据题意生成所需要的文件
    done
    
    结果:apquvdpqbk_oldboy.html     bmqiwhfpgv_oldboy.html
          ......
    

    2、批量改名

    将上述(第1题)所得文件名中的oldboy字符串全部改成oldgirl(最好用for循环并且将扩展名全部改成大写)

    • 方法1:
    [root@oldboy script]# cat chname.sh
    #!/bin/bash
    Filename = _oldgirl.HTML        //定义替换后的目标字符串。
    Dirname = "/oldboy"            //定义操作目录。
    cd $Dirname || exit 1          //切换到指定目录下,如果不成功则退出。
    for n in `ls`
    do
    name = $(echo ${n} | awk -F '_' '{print $1}') //定义替换后的目标。
    mv $n ${name}${Filename}       //实际mv改名操作命令
    done
    
    • 方法2:
    [root@oldboy scripts]# cat chname.sh
    #!/bin/bash
    Path = "/oldboy"
    cd $Path && \
    ls | awk -F '_' '{print "mv "$0" "$1"_oldgirl.HTML"}' | bash
    
    • 方法3:
    [root@oldboy script]# rename oldboy.html oldgirl.HTML *.html
    

    3、批量创建5个系统账号(oldboy01-oldboy10),并设置密码(密码为随机数,要求是字符和数字的混合)

    #!/bin/bash
    . /etc/init.d/functions
    user="oldboy"
    passfile="/tmp/user.log"
    for num in `seq -w 10`
    do
       useradd $user$num    //创建用户
       pass="`echo "test$RANDOM" | md5sum | cut -c3-11`"
           //若多次用到随机数,就要将其定义成变量。
       echo "$pass" | passwd --stdin $user$num   //设置密码
       echo -e "user:$user$num\tpasswd:$pass">>$passfile 
          //记录设置的账号和密码信息
    done
    echo ------this is oldboy trainning class contents------------
    cat $passfile
    

    4、扫描网络内存活主机

    写一个Shell脚本,判断10.0.0.0/24网络里,当前在线的IP有哪些?
    (1)问题分析
    判断IP在线最常见的方法就是使用ping命令,其实还有一个不错的命令就是nmap,这个nmap命令有可能需要执行括号内的命令安装(yum install nmap -y)。
    (2)参考答案
    方法1:并发ping方案

    [root@oldboy scripts]# cat alive.sh
    #!/bin/bash
    CMD="ping -W 2 -c 2"   //定义ping命令及参数
    Ip="10.0.0."
    for n in $(seq 254)
    do
        {
        $CMD $Ip$n &> /dev/null      //对指定Ip实行ping政策。
        if [ $? -eq 0 ];then
            echo "$Ip$n is ok"      //打印提示
        fi
        }&    //Shell的并发检测功能,批量ping,快捷返回结果
    done
    

    方法2:nmap方案

    #!/bin/bash
    CMD = "nmap -sP"
    Ip = "10.0.0.0/24"
    CMD2 = "namp -sS"
    $CMD $Ip | awk '/Nmap scan report for/ {print $NF}'
    

    5、数据库备份:

    #!/bin/bash
    PATH="/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin"
    
    TARGET_DIR="/data/OA/mysql-backup/"
    
    if [ -z $TARGET_DIR ];then
        echo "相关变量没有设置!"
        exit 100;
    fi
    
    MYSQL_HOST="10.6.205.30"
    MYSQL_USER="root"
    MYSQL_PASSWORD="123456"
    MYSQL_CHARACTER="gbk"
    
    DB=$(mysql -h$MYSQL_HOST -u$MYSQL_USER -p$MYSQL_PASSWORD -e "show databases;" 2> /dev/null  |egrep -v "Database|information_schema|mysql|performance_schema")
    echo $DB
    
    if [ ! -d ${TARGET_DIR}/`date +%F` ];then
        mkdir -p ${TARGET_DIR}/`date +%F`
    fi 
    
    for db in $DB
    do
         mysqldump -h$MYSQL_HOST -u$MYSQL_USER -p$MYSQL_PASSWORD --default-character-set=$MYSQL_CHARACTER -x -B $db  > ${TARGET_DIR}/`date +%F`/$db-`date +%F`.sql
    done
    
    if [ $? -eq 0 ];then
        tar zcf  ${TARGET_DIR}/`date +%F`.tar.gz   ${TARGET_DIR}/`date +%F`  && rm -rf ${TARGET_DIR}/`date +%F`
        find ${TARGET_DIR}/*  -name "*.tar.gz" -a -mtime +30  -exec rm -f {} \;
    fi
    
    

    6、筛选符合长度的单词

    计算变量内容的长度,常见的方法有4种:

    [root@oldboy scripts]# char=oldboy
    [root@oldboy scripts]# echo $char | wc -L
    6
    [root@oldboy scripts]# echo ${#char}
    6
    [root@oldboy scripts]# expr length $char
    6
    [root@oldboy scripts]# echo $char | awk '{print length($0)}'
    6
    

    方法1:通过数组方法来实现

    arr = (I am oldboy teacher welcome to oldboy training class)
    for ((i=0;i<${#arr[$i]};i++))
    do 
       if [ ${#arr[$i]} -lt 6 ]
          then 
            echo "${arr[$i]}"
       fi
    done
    echo ------------------------
    for word in ${arr[*]}
    do
       if [ `expr length $word` -lt 6 ];then
            echo $word
       fi
    done
    
    本例列出了用两种for循环打印数组元素的方法
    

    方法2:使用for循环列举取值列表法

    for word in I am oldboy teacher welcome to oldboy training class
    do
      if [ `echo $word | wc -L` -lt 6 ];then
          echo $word
      fi
    done
    
    
    chars = "I am oldboy teacher welcome to oldboy training class"  //定义字符串
    for word in $chars
    do
       if [ `echo $word | wc -L` -lt 6 ];then
           echo $word
       fi
    done
    
    

    方法3:使用awk循环实现

    [root@oldboy scripts]# chars = "I am oldboy teacher welcome to oldboy training class"
    [root@oldboy scripts]# echo $chars | awk '{for(i=1;i<=NF;i++) if(length($i)<=6) print $i}'
    

    7、比较两个整数的大

    开发Shell脚本,分别实现以脚本传参和read读入的方式比较两个整数的大小。用条件表达式(禁止用if)进行判断并以屏幕输出的方式提醒用户比较的结果。注意:一共是开发两个脚本。再用脚本传参和read读入的方式实现时,需要对变量是否为数字及传参个数是否正确给予提示。

    • 参考答案1:
    [root@oldboy scripts]# cat compare.sh
    #!/bin/bash
    read -p "Pls input two num:" a b   //请求用户输入两个参数,读入后分别赋值给变量a和b。
    
    #no1
    [ -z "$a" ]||[ -z "$b" ]&&{//若$a变量长度为0或$b变量长度为0,即任何一个变量为0,则执
                              行命令。
       echo "Pls input two num again." //a或b没值,表示用户输入错误,给出提示。
       exit 1                          //以返回值1退出脚本
    
    }
    #no2
    expr $a + 10 &>/dev/null  //判断$a是否为整数,不输出任何信息
    RETVAL1 = $?   //将返回值赋值给RETVAL1,后面会用这个返回值做判断
    expr $b + 10 &>/dev/null   //判断$b是否为整数,不输出任何信息
    RETVAL2 = $?   //将返回值赋值给RETVAL2, 后面会用这个返回值做判断
    test $RETVAL1 -eq 0 -a $RETVAL2 -eq 0 || {//利用test进行返回值是否为0的判断,如果有一个返回值不为0,则说明有一个变量不为整数,不合要求,打印提示后退出。
         echo "Pls input two "num" again."
         exit 2
    }
    #no3
    [ $a -lt $b ] && {//整数比较,$a是否小于$b。
       echo "$a < $b"
       exit 0
    }
    #no4
    [ $a -eq $b ] && {//整数比较,$a是否等于$b.
       echo "$a < $b"
       exit 0
    }
    #no5
    [ $a -gt $b ] && {//整数比较,$a是否大于$b。
       echo "$a < $b"
       exit 0
    }
    
    • 参考答案2
    [root@oldboy scripts]# cat compare.sh
    #!/bin/sh
    a=$1 //接收脚本的第一个参数$1赋值给a。
    b=$2 //接收脚本的第二个参数$2赋值给b。
    #no1
    [ $# -ne 2 ] && {//传参专用判断手法,判断传参个数是否为2个
        echo "USAGE:$0 NUM1 NUM2" //传参不符合要求,给出用法提示。
        exit 1 //以返回值1退出脚本
    }
    #no2
    expr $a + 10 &>/dev/null  //整数判断
    RETVAL1=$?
    expr $b + 10 &>/dev/null  //整数判断
    RETVAL2=$?
    test $RETVAL1 -eq 0 -a $RETVAL2 -eq 0 || {
         echo "Pls input two "num" again."
         exit 2
    }
    #no3
    [ $a -lt $b ] && {
        echo "$a < $b"
        exit 0
    }
    #no4
    [ $a -eq $b ] && {
        echo "$a = $b"
        exit 0
    }
    #no5 
    [ $a -gt $b ] && {
        echo "$a > $b"
        exit 0
    }
    
    

    8、WEB及MySQL服务异常监测

    if条件语句实现对Nginx Web服务及MySQL数据库服务是否正常的检测,如果服务未启动,则启动相应的服务。本例同样适用于其他的Web服务和数据库服务。
    (1)分析问题
    监控Web服务和数据库服务是否异常的常见方法:

    • 端口监控
      1)在服务器本地监控服务端口的常见命令有netstatsslsof
      2)从远端监控服务器本地端口的命令有telnetnmapnc

    • 监控服务进程或进程数
      此方法适合本地服务器,注意,过滤的是进程的名字。命令为:
      ps -ef | grep nginx | wc -l
      ps -ef | grep mysql | wc -l

    • 在客户端模拟用户访问
      使用wgetcurl命令进行测试(如果检测数据库,则需要转为通过web服务器去访问数据库),并对测试结果做三种判断
      1)利用返回值(echo $?)进行判断
      2)获取特殊字符串以进行判断(需要事先开发好程序)
      3)根据HTTP响应header的情况进行判断

    • 登入MySQL数据库判断
      通过MySQL客户端连接数据库,根据返回值或返回内容判断。例如:
      mysql -uroot -poldboy123 -e "select version(); &/dev/null;echo $?"

    此外,对端口进程等进行判断时,尽量先通过grep过滤端口和进程特殊标记字符串,然后结合wc将过滤到的结果转成行数再比较,这样相对简单有效,且经过wc -l命令处理之后的结果一定是数字,这样在进行判断就会比较方便。如果单纯的根据具体的列取具体的值判断会很麻烦,如果确实想采用取值判断的方法,那就尽量用字符串比较的语法。
    (2)监控MySQL数据库异常
    1)MySQL数据库环境准备

    [root@oldboy ~]# yum install mysql-server -y
    [root@oldboy ~]# /etc/init.d/mysqld start
    正在启动 mysqld:            [确定]
    [root@oldboy ~]# netstat -lntup | grep mysql
    tcp   0   0  0.0.0.0:3306   0.0.0.0:*   LISTEN   2275/mysqld   
    

    2)通过命令行检测数据库服务是否正常,只有先确定命令行是正确的,才能确保将它放到脚本里也是正确的。
    首先采用端口监控的方式。在服务器本地监控端口的命令有netstatsslsof,具体实现多种命令的方法如下:

    [root@oldboy scripts]# netstat -lnt | grep 3306 | awk -F "[ :]+" '{print $5}' //根据具体的列取值的判断方法,获取列值,然后看看其是否等于3306,不推荐使用这种取值的方法,因为第一取值麻烦;第二如果使用数字比较,当端口不存在时就会报错,而一旦使用了取值判断方法,即使看起来是数字,也要尽量使用字符串进行比较,否则你将掉进坑里,很久都会爬不上来
    3306
    
    [root@oldboy scripts]# netstat -lntup | grep 3306 | wc -l  //过滤关键字端口,转成数字,此方法很好
    1
    
    [root@oldboy scripts]# netstat -lntup | grep mysql | wc -l  //过滤关键字进程,转成数字,此方法很好
    1
    
    [root@oldboy scripts]# ss -lntip | grep mysql | wc -l  //ss类似于netstat命令,参数选项可通用。
    1
    
    
    [root@oldboy scripts]# ss -lntup | grep 3306  wc -l  //ss类似于netstat命令,参数选项可通用
    1
    
    
    [root@oldboy scripts]# lsof -i tcp:3306 | wc -l  //利用lsof检查tcp协议的3306端口
    2
    
    • 从远端监控服务器监控本地端口的命令有telnetnmapnc,这三个命令有可能需要事先安装好才能使用,安装方法为:
    [root@oldboy scripts]# yum install telnet nmap nc -y
    
    [root@oldboy scripts]# nmap 127.0.0.1 -p 3306 | grep open | wc -l
    //查看远端3306端口是否开通,过滤open关键字,结果返回1,说明有open关键字,表示3306端口是通的。
    1
    
    [root@oldboy scripts]# echo -e "\n" | telnet 127.0.0.1 3306 2>/dev/null | grep Connected | wc -l  //telnet是常用来检测远端服务器端口是否通畅的一个好用的命令,在非交互式时需要采用特殊写法才行,过滤的关键字为Connected,返回1,说明有Connected,表示3306端口是通的。
    1
    
    
    [root@oldboy scripts]# nc -w 2 127.0.0.1 3306 &>/dev/null  //nc的命令很强大,这里用来检测端口。根据执行命令的返回值判断端口是否通畅,如果返回0,则表示通畅,-w为超时时间
    [root@oldboy scripts]# echo $?
    0
    

    本例为了统一IP地址,因此使用的都是同一个Ip,即127.0.0.1,在实际工作中,应该使用服务器的IP来替代。

    • 下面对服务进程或进程数进行监控(适合本地服务器)
    [root@oldboy scripts]# ps -ef | grep mysql | grep -v grep | wc -l
    3
    
    • 以下是在客户端模拟用户访问的方式进行监控
      使用wgetcurl命令访问URL地址来测试。根据执行命令的返回值判断成功与否,本例的URL使用了网上的地址,在实际工作中应使用开发人员提供给我们的访问数据库的程序地址。
    [root@oldboy scripts]# wget --spider --timeout=10 --tries=2 www.baidu.com &>/dev/null  //在wget后面加url的检测方法,&>/dev/null表示不输出,只看返回值。--spider的意思是模拟爬取,--timeout=10的意思是10秒超时,--tries=2表示不成功,则重试两次。
    [root@oldboy scripts]# echo $? //查看命令执行的返回值,0为成功。
    0
    
    
    [root@oldboy scripts]# wget -T 10 -q --spider http://www.baidu.com >&/dev/null  //用法同上,-q表示安静的。
    [root@oldboy scripts]# echo $?  //查看命令执行的返回值,0位成功
    0
    
    
    [root@oldboy scripts]# curl -s -o /dev/null http://www.baidu.com //利用curl进行检测,-s为沉默模式,-o /dev/null表示将输出定向到空。
    [root@oldboy scripts]# echo $? //查看命令执行的返回值,0为成功。
    0
    

    3)、开发监控MySQL数据库的脚本

    脚本1:
    #!/bin/sh
    echo method1------------------------------------------
    if [ `netstat -lnt | grep 3306 | awk -F "[ :]+" '{print $5}'` -eq 3306 ]
    //这里的判断思路不是很好,最好不要用整数进行比较,因为一旦端口不存在,取值就会为空,进行整数比较会报错。还有不要根据列取具体的值,而是要过滤关键字,通过wc转成行数判断。
        then
            echo "MySQL is Running."
    else 
            echo "MySQL is Stopped."
            /etc/init.d/mysqld start
    fi
    
    脚本2:
    echo method2------------------------------------------
    if [ "`netstat -lnt | grep 3306 | awk -F "[ :]+" '{print $5}'`" = "3306" ]
    //用字符串的方式进行比较就好多了,避免了脚本1中整数比较的错误发生,但是取值麻烦了一些。
        then
            echo "MySQL is Running."
    else
            echo "MySQL is Stopped."
            /etc/init.d/mysqld start
    fi
    
    脚本3:
    echo method3------------------------------------------
    if [ `netstat -lntup | grep mysqld | wc -l` -gt 0 ]
    //过滤进程名,转成数字,很优秀的取值判断方法
        then
            echo "MySQl is Running."
    else
            echo "MySQL is Stopped."
            /etc/init.d/mysqld start
    fi
    
    脚本4:
    echo method4--------------------------------------------
    if [ `lsof -i tcp:3306 | wc -l` -gt 0 ]
    //过滤端口转成数字,很优秀的取值方法
        then
            echo "MySQl is Running."
    else 
            echo "Mysql is Stopped."
            /etc/init.d/mysqld start
    fi
    
    脚本5:
    echo method5---------------------------------------------
    [ `rpm -qa namp | wc -l` -lt 1 ] && yum install namp -y &>/dev/null
    //防止因nmap没有安装而导致的错误
    if [ `nmap 127.0.0.1 -p 3306 2>/dev/null | grep open | wc -l` -gt 0 ]
    //远端的端口检查,推荐使用,同理,这里也不需要过滤出open,然后再做字符串比较,转成数字最佳。
        echo "MySQL is Running."
    else
        echo "MySQL is Stipped."
        /etc/init.d/mysqld start
    fi
    
    脚本6:
    echo method6-----------------------------------------------
    [ `rpm -qa nc | wc -l` -lt 1 ] && yum install nc -y &>/dev/null
    if [ `nc -w 2 127.0.0.1 3306 &>/dev/null&&echo ok | grep ok | wc -l` -gt 0 ] 
    //这个判断有点特若别,即nc执行成功,则输出和之后的过滤都没问题,最后转换成数字,思路决定出路。
        then
            echo "MySQL is Running."
    else 
            echo "MySQL is Stopped."
            /etc/init.d/mysqld start
    fi
    
    脚本7:
    echo method7----------------------------------------------
    if [ `ps -ef | grep -v grep | grep mysql | wc -l` -gt 0 ]
    //传统的过滤进程的方法。grep -v grep是排除此命令本身
        then
            echo "MySQl is Running."
    else 
            echo "MySQL is Stopped."
            /etc/init.d/mysqld start
    fi
    

    (3)监控Nginx Web服务异常
    监控Nginx Web服务异常的方法和监控MySQl数据库一样,也是使用端口、进程或通过wget/curl访问来进行检测。
    1)通过命令行检测Nginx服务是否正常,同样只有命令行是正确的,才能确保它放到脚本里也是正确的。
    首先采用端口监控的方式。再监控Nginx和监控数据库端口时,除了端口不同,其他的命令方法都是相同的。在服务器本地监控端口的命令有netstat,ss,lsof,如下:

    [root@oldboy ~]# netstat -lnp | grep -w 80 | awk -F "[ :]+" '{print $5}'
    80
    
    [root@oldboy ~]# netstat -lntup | grep -w 80 | wc -l
    1
    
    [root@oldboy ~]# netstat -lntup | grep mysql | wc -l
    1
    
    [root@oldboy ~]# ss -lntup | grep -w 80 | wc -l
    1
    
    [root@oldboy ~]# ss -lntup | grep mysql | wc -l
    1
    
    [root@oldboy ~]# lsof -i tcp:80 | wc -l
    3
    

    在远端监控服务器本地端口的命令有telnetnmapnc,如下:

    [root@oldboy ~]# nmap 127.0.0.1 -p 80 | grep open | wc -l
    1
    
    [root@oldboy ~]# echo -e "\n" | telnet 127.0.0.1 80 2>/dev/null | grep Connected | wc -l
    1
    
    [root@oldboy ~]# nc -w 2 127.0.0.1 80 &>/dev/null
    [root@oldboy ~]# echo $?
    0
    

    对服务器进程或进程数进行监控的方式(适合本地服务器)如下:

    [root@oldboy ~]# ps -ef | grep nginx | grep -v grep | wc -l
    2
    

    以下是在客户端模拟用户访问的监控方式。先通过wgetcurl命令进行测试。执行wget或curl命令之后,再看返回值($?),为0,则成功。

    [root@oldboy ~]# wget --spider --timeout=10 --tries=2 http:127.0.0.1 &>/dev/null
    [root@oldboy ~]# echo $?
    0
    
    [root@oldboy ~]# wget -T 10 -q --spider http:127.0.0.1 &>/dev/null
    [root@oldboy ~]# echo $?
    0
    
    [root@oldboy ~]# curl -s -o /dev/null http://127.0.0.1
    [root@oldboy ~]# echo $?
    0
    

    以下是获取字符串的方式(判断字获取的字符串是否和事先设定的相等)。

    [root@oldboy ~]# curl http://127.0.0.1 
    //根据指定的返回值判断服务是否正常
    

    以下是根据HTTP相应header的结果进行判断(200、301、302都表示正常)

    [root@oldboy ~]# curl -I -s -w "%{http_code}\n" -o /dev/null http://127.0.0.1
    200
    
    注:  -I : 仅返回头部信息。
         -s :  slient 减少输出的信息,比如进度
         -w :用于在一次完整且成功的操作后输出指定格式的内容到标准输出(write-out)
    

    3)开发监控Nginx Web服务的脚本,这里同样给出多个参考脚本。

    #!/bin/bash
    echo http method1-----------------------------------------
    if [ "`netstat -lnt | grep 80 | awk -F "[ :]+" '{print $5}'`" = "80" ]
    //字符串比较语法,取值太麻烦,不如过滤后转为行数再比较的方法好。
        then 
            echo "Nginx is Running."
    else 
            echo "Nginx is Stopped."
            /etc/init.d/nginx start
    fi
    
    脚本2:
    echo http method2-----------------------------------------
    if [ `netstat -lntup | grep nginx | wc -l` -gt 0 ]
    //通过检查端口的命令,过滤进程名(比过滤端口好)转成数字后再比较,这是推荐的用法。
        then 
            echo "Nginx is Running."
    else 
            echo "Nginx is Stopped."
            /etc/init.d/nginx start
    fi
    
    脚本3:
    echo http method3------------------------------------------
    if [ `lsof -i tcp:80 | wc -l` -gt 0 ]
        then 
            echo "Nginx is Running."
    else
            echo "Nginx is Stopped."
            /etc/init.d/nginx start
    fi
    
    脚本4:
    echo http method4-------------------------------------------
    [ `rpm -qa nmap | wc -l ` -lt 1 ] && yum install nmap -y &>/dev/null
    if [ `nmap 127.0.0.1 -p 80 2>/dev/null | grep open | wc -l` -gt 0]
    //nmap检测方法,优势是从远端进行检查,推荐使用。
        then
            echo "Nginx is Running."
    else 
            echo "Nginx is Stopped."
            /etc/init.d/nginx start
    fi
    
    脚本5
    echo http method5--------------------------------------------
    [ `rpm -qa nc | wc -l` -lt 1 ] && yum install nc -y &>/dev/null
    if [ `nc -w 2 127.0.0.1 80 &>/dev/null&&echo ok | grep ok | wc -l` -gt 0 ]
        then 
            echo "Nginx is Running."
    else
            echo "Nginx is Stopped."
            /etc/init.d/nginx start
    fi
    
    脚本6:
    echo http method6---------------------------------------------
    if [ `ps -ef | grep -v grep | grep nginx | wc -l` -ge 1 ]
    //过滤进程方式,排除自身
        then
            echo "Nginx is Running."
    else
            echo "Nginx is Stopped."
            /etc/init.d/nginx start
    fi
    
    脚本7:
    echo http method7---------------------------------------------
    if [[ `curl -I -s -o /dev/null -w "%{http_code}\n" http://127.0.0.1` =~[23]0[012] ]]
    //获取状态码,然后做正则数字匹配(目标是200、301、302,但实际上多余了几个201、202、300),这是 [[]] 的特殊匹配用法之一。
        then 
            echo "Nginx is Running."
    else
            echo "Nginx is Stopped."
            /etc/init.d/nginx start
    fi
    
    脚本8:
    echo http method8----------------------------------------------
    if [ `curl -I http://127.0.0.1 2>/dev/null | head -1 | egrep "200|301|302" | wc -l` -eq 1 ]
    //此方法通过扩展的egrep过滤正确的状态码,然后利用wc转成数字,此方法比较优秀,推荐使用。
        then
            echo "Nginx is Running."
    else 
            echo "Nginx is Stopped."
            /etc/init.d/nginx start
    fi
    
    脚本9:
    echo http method9-----------------------------------------------
    if [ "`curl -s http://127.0.0.1`" = "自己定义的字符串"]
    //根据访问网站URL,将返回的结果和期待的值进行比较,这个方法略麻烦,但是结果最为准确,适用于数据库及更深层次的对网站集群后端各个应用的检测。
        then
            echo "Nginx is Running."
    else
            echo "Nginx is Stopped."
    fi
    

    9、写一个脚本计算一下linux系统所有进程占用内存的大小的和。

    #!/bin/bash
    count=0
    #这个循环会遍历出每个进程占用的内存大小
    for i in `ps -avx | awk '{print $6}' | grep -v 'RSS'`
    do
        #将遍历出来的数字进行累加
        count=$[ $count+$i ]
    done
    #就得到所有进程占用内存大小的和了
    echo "$count/kb"
    
    
    #也可以使用awk一条命令计算
    ps -aux | grep -v 'RSS TTY' | awk '{sum=sum+$6};END{print sum}'
    

    10、设计一个简单的脚本,监控远程的一台机器(假设IP为123.23.11.21)的存活状态,当发现宕机时发一封邮件给自己。

    #!/bin/bash
    ip=123.23.11.21
    email="user@example"
    while 1
    do
        ping -c10 $ip > /dev/null 2>/dev/null
        if [ $? != "0" ]
        then
            #调用一个用于发邮件的脚本
            python /usr/local/sbin/mail.py $email "$ip down" "$ip is down"
        fi
        sleep 30
    done
    

    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('1234567@qq.com','aaaaaaaaaa','1234567@qq.com',to,subject,content)
    if __name__ == "__main__":
        main()
    
    #####脚本使用说明######
    #1. 首先定义好脚本中的邮箱账号和密码
    #2. 脚本执行命令为:python mail.py 目标邮箱 "邮件主题" "邮件内容"
    
    

    11、

    需求:

    • 找到/123目录下所有后缀名为.txt的文件
    • 批量修改.txt为.txt.bak
    • 把所有.bak文件打包压缩为123.tar.gz
    • 批量还原文件的名字,即把增加的.bak再删除
    #!/bin/bash
    now=`date +%F_%T`
    mkdir /tmp/123_$now
    for txt in `ls /123/*.txt`
    do
      mv $txt $txt.bak
      for f in $txt
      do
        cp $txt.bak /tmp/123_$now
      done
    done
    
    cd /tmp/
    tar czf 123.tar.gz 123_$now/
    
    for txt in `ls /123/*.txt.bak`
    do
      name=`echo $txt |awk -F '.' '{OFS="."} {print $1,$2}'`
      mv $txt $name
    done
    

    12、设计一个shell脚本来备份数据库,首先在本地服务器上保存一份数据,然后再远程拷贝一份,本地保存一周的数据,远程保存一个月。

    假定,我们知道mysql root账号的密码,要备份的库为discuz,本地备份目录为/bak/mysql, 远程服务器ip为192.168.123.30,远程提供了一个rsync服务,备份的地址是 192.168.123.30::backup . 写完脚本后,需要加入到cron中,每天凌晨3点执行。

    #!/bin/bash
    PATH=$PATHi:/usr/local/mysql/bin
    week=`date +%w`
    today=`date +d`
    passwd="123456"
    backdir="/data/mysql"
    r_backupIP="192.168.123.30::backup"
    
    exec 1>/var/log/mysqlbak.log 2>/var/log/mysqlbak.log
    echo "mysql backup begin at `date +%F %T`."
    
    # 本地备份
    mysqldump -uroot -p$passwd --default-character-set=utf8 discuz >$backdir/$week.sql
    # 同步备份到远程机器
    rsync -az $backdir/$week.sql $r_backupIP/$today.sql
    
    echo "mysql backup end at `date +%F %T`."
    
    

    然后加入cron

    0 3 * * * /bin/bash /usr/local/sbin/mysqlbak.sh
    

    13、服务器上跑的是LNMP环境,近期总是有502现象。502为网站访问的状态码,200正常,502错误是nginx最为普通的错误状态码。由于502只是暂时的,并且只要一重启php-fpm服务则502消失,但不重启的话,则会一直持续很长时间。所以有必要写一个监控脚本,监控访问日志的状态码,一旦发生502,则自动重启一下php-fpm

    我们设定:

    • access_log /data/log/access.log
    • 脚本死循环,每10s检测一次(假设每10s钟的日志条数为300左右)
    • 重启php-fpm的方法是/etc/init.d/php-fpm restart
    #!/bin/bash
    access_log="/data/log/access.log"
    N=10
    while :
    do
       # 因为10秒大概产生300条日志记录
       tail -n300 $access_log > /tmp/log
       # 拿出log中包含502的日志行数
       n_502=`grep -c "502" /tmp/log`
       # 如果行数大于10
       if [ $n_502 -ge $N ]
       then
          # 就记录一下系统状态
          top -bn1 > /tmp/`date +%H%M%S`-top.log
          vmstat 1 5 > /tmp/`date +%H%M%S`-vm.log
          # 然后才重启服务,并把错误信息重定向
          /etc/init.d/php-fpm restart 2> /dev/null
          # 重启php-fpm服务后,应先暂缓1分钟,而后继续每隔10s检测一次
          sleep(60)
       fi
       sleep(10)
    done
    

    14、需求: 根据web服务器上的访问日志,把一些请求量非常高的ip给拒绝掉!

    分析: 我们要做的,不仅是要找到哪些ip请求量不合法,并且还要每隔一段时间把之前封掉的ip(若不再继续请求了)给解封。 所以该脚本的关键点在于定一个合适的时间段和阈值。

    比如, 我们可以每一分钟去查看一下日志,把上一分钟的日志给过滤出来分析,并且只要请求的ip数量超过100次那么就直接封掉。 而解封的时间又规定为每半小时分析一次,把几乎没有请求量的ip给解封!

    参考日志文件片段:

    157.55.39.107 [20/Mar/2015:00:01:24 +0800] www.aminglinux.com “/bbs/thread-5622-3-1.html” 200 “-” “Mozilla/5.0 (compatible; bingbot/2.0; +http://www.bing.com/bingbot.htm)”
    61.240.150.37 [20/Mar/2015:00:01:34 +0800] www.aminglinux.com “/bbs/search.php?mod=forum&srchtxt=LNMP&formhash=8f0c7da9&searchsubmit=true&source=hotsearch” 200 “-” “Mozilla/5.0 (compatible; bingbot/2.0; +http://www.bing.com/bingbot.htm)”
    
    

    脚本实现如下:

    #!/bin/bash
    ## 日志文件路径
    log_file="/home/logs/client/access.log"
    ## 当前时间减一分钟的时间
    d1=`date -d "-1 minute" +%H:%M`
    ## 当前时间的分钟段
    d2=`date +%M`
    ## iptables命令所在的路径
    ipt="/sbin/iptables"
    ## 用于存储访问日志里的ip
    ips="/tmp/ips.txt"
    
    ## 封ip
    block(){
       ## 把日志文件中的ip过滤出来,去掉重复的ip,并统计ip的重复次数以及对ip进行排序,最后将结果写到一个文件中
       grep "$d1:" $log_file |awk '{print $1}' |sort -n |uniq -c |sort -n > $ips
       ## 将文件里重复次数大于100的ip迭代出来
       for ip in `awk '$1 > 100 {print $2}' $ips`
       do
          ## 通过防火墙规则对这些ip进行封禁
          $ipt -I INPUT -p -tcp --dport 80 -s $ip -j REJECT
          ## 将已经封禁的ip输出到一个文件里存储
          echo "`date +%F-%T` $ip" >> /tmp/badip.txt
       done
    }
    
    ## 解封ip
    unblock(){
       ## 将流量小于15的规则索引过滤出来
       for i in `$ipt -nvL --line-number |grep '0.0.0.0/0' |awk '$2 < 15 {print $1}' |sort -nr`
       do
          ## 通过索引来删除规则
          $ipt -D INPUT $i
       done
       ## 清空规则中的数据包计算器和字节计数器
       $ipt -Z
    }
    
    ## 为整点或30分钟就是过了半个小时,就需要再进行分析
    if [ $d2 == "00" ] || [ $d2 == "30" ]
    then
       unblock
       block
    else
       block
    fi
    
    

    相关文章

      网友评论

          本文标题:分享几个实用脚本

          本文链接:https://www.haomeiwen.com/subject/lkmrcftx.html