zoukankan      html  css  js  c++  java
  • shell 编程 07 -- if 条件语句的知识与实践

    shell 编程 07 -if 条件句的知识与实践

    7.1 if条件句

    7.1.1 if -- 单分支结构语法

    • if 条件句单分支结构语法:
    if [ 条件 ]
    	then 
    		指令
    fi
    # 或-------------------------------------
    if [ 条件 ];then
    	指令
    fi
    ## 等价情况-------------------------------
    [ -f "$file" ] && echo 1 ## 等价于
    if [ -f "$file" ]; then 
    	echo 1
    fi
    

    7.1.2 if-else -- 双分支结构语法

    • if 条件句双分支结构语法:
    if [ 条件 ]
    	then 
    		指令集1
    else 
    	指令集2
    fi
    # 等价于--------------------------------------
    [ -f "$file" ] && echo 1 || echo 0
    ## 放在一行时的写法,加分号 ;--------------------
    if [ -f "$file" ] ;then echo 1;else echo 0;fi
    

    7.1.3 if - elif - else -- 多分支结构语法

    • if 条件句多分支结构语法:
    if [ 条件 ]
    	then 
    		指令1
    elif 条件2
    	then
    		指令2
    else
    	指令3
    fi
    ## 其中elif可有多个-----------------------
    elif 条件3
    	then
    		指令3
    ...
    

    7.1.4 if条件语句多种条件表达式语法

    前文已经说过,if条件语句(包括双多分支if)的“<条件表达式>”部分可以是test、[]、[[]]、(())等条件表达式,甚至还可以直接使用命令作为条件表达式,具体的语法如下。

    (1)test条件表达式

    if test 表达式
    	then
    		指令
    fi
    

    (2)[] 单中括号条件表达式

    if [ 字符串或算术表达式 ]
    	then
    		指令
    fi
    

    (3)[[]] 双中括号条件表达式

    if [[ 字符串表达式  ]]
    	then
    		指令
    fi
    

    (4)(( )) 双括号条件表达式

    if (( 算术表达式  ))
    	then
    		指令
    fi
    

    (5)命令表达式

    if 命令
    	then
    		指令
    fi
    

    7.1.5 测试文件中条件表达式的语句改成if条件语句

    [root@zabbix 0507]# [ -f /etc/hosts ]&& echo 1
    1
    [root@zabbix 0507]# [[ -f /etc/hosts ]]&& echo 1 
    1
    [root@zabbix 0507]# test -f /etc/hosts && echo 11
    -----------------------------------------------------
    ## 改成如下if语句
    [root@zabbix 0507]# cat if.sh 
    if [ -f /etc/hosts ]
        then 
    	echo "[1]"
    fi
    if [[ -f /etc/hosts ]]
        then 
    	echo "[[1]]"
    fi
    if test -f /etc/hosts
        then 
    	echo "test1"
    fi
    [root@zabbix 0507]#
    

    7.1.6 if单分支实例1:内存大小检查


    开发shell脚本判断系统剩余内存的大小,如果低于100M 就邮件报给管理员,并且加入系统定时任务,每三分钟执行一次检查。


    分析:对于开发程序而言,一般来说应该遵循下面的3步法则。

    (1)分析需求明白开发需求,是完成程序的大前提,因此,分析需求至关重要,一切不以需求为主的程序开发,都是不倡导的!

    (2)设计思路设计思路就是根据需求,把需求进行拆解,分模块逐步实现,例如本题可以分为如下几步:

    • 1)获取当前系统剩余内存的值(先在命令行实现)。

    • 2)配置邮件报警(可采用第三方邮件服务器)。

    • 3)判断取到的值是否小于100MB,如果小于100MB,就报警(采用if语句)。

    • 4)编码实现Shell脚本。

    • 5)加入crond定时任务,每三分钟检查一次。

    (3)编码实现编码实现就是具体的编码及调试过程,工作中很可能需要先在测试环境下调试,调试好了,再发布到生产环境中。本例的最终实现过程如下。

    1. 如何取内存,内存取哪个值?(buff/cache)注意:内存大小是下面命令中对应buffers/cache那一行结尾的值(buffers)。

    ## free -m 结果为4行的取法
    free -m |awk 'NR==3 {print $NF}'
    free -m |grep "buffers/" |awk '{print $NF}'
    free -m |grep buffers/ |awk '{print $NF}'
    free -m|awk '/buffers/ {print $NF}'  -- 匹配buffers所在行,取出最后一列
    ## free -m 结果为3行的取法
    [root@zabbix scripts]# free -m
                  total        used        free      shared  buff/cache   available
    Mem:            974         104         732           7         137         715
    Swap:          2047           0        2047
    [root@zabbix scripts]# free -m|awk 'NR==2 {print $6}'
    137
    

    2. 发邮件,CenOS6及以上版本默认postfix服务要开启

    echo -e "set from=zhangfd2020@163.com smtp=smtp.163.com
    
    set smtp-auth-user=zhangfd2020@163.com smtp-auth-password=用户授权密码 smtp-auth=login" >> /etc/mail.rc
    tail -2 /etc/mail.rc
    systemctl start postfix
    echo "postfix function exp" > /tmp/moox.txt
    mail -s "title content" 2144865225@qq.com < /tmp/moox.txt
    echo "postfix function exp"|mail -s "title content" 2144865225@qq.com
    
    ## 脚本函数
    #### config mail service ####
    function postfix(){
    	echo -e "set from=zhangfd2020@163.com smtp=smtp.163.com
    
    set smtp-auth-user=zhangfd2020@163.com smtp-auth-password=用户授权密码 smtp-auth=login" >> /etc/mail.rc
    
    	systemctl start postfix
    }
    postfix
    

    3. 编写脚本(以centos7为例),并测试执行

    cat judge_system_mem.sh
    #!/bin/bash
    
    cur_free=`free -m|awk '/Mem/ {print $6}'`
    chars="current memory is $cur_free ."
    if [ $cur_free -lt 100 ]
    	then 
    		echo $chars |tee /tmp/messages.txt ## 屏幕输出提示,并写入文件
    		#echo $chars |mail -s "$chars" 2144865225@qq.com
    		mail -s "$chars" 2144865225@qq.com < /tmp/messages.txt
    fi
    --------------------------------------------------------------
    ## 测试执行
    sh judge_system_mem.sh
    

    4. 将脚本加入定时任务,每分钟检查,达到阈值就报警

    echo -e "# monitor free -m 
    
    */3 * * * * /bin/sh /server/scripts/judge_system_mem.sh >/dev/null 2>&1"
    >> /var/spool/cron/root
    
    1. 扩展
    取磁盘空间,df -h -- avail
    取MySQL,lsof -i:3306 或 netstat -lntup|grep mysqld|wc -l
    

    7.1.7 if双分支实例2:判断服务是否正常

    • 用if 双分支实现对nginx或MySQL服务是否正常进行判断,使用进程数、端口、URL的方式判断,如果进程没起,则启动进程。

    • 扩展了解:

      1. 监控web服务是否正常,不低于5中思路
      2. 监控db服务是否正常,不低于5中思路

    方法:

    1. 端口
      本地:netstat 、ss、lsof
      远程:telnet、nmap、nc
      telnet-nc-nmap:查看远端的端口是否通畅3个简单实用案例!

    2. 进程(本地):ps -ef|grep [n]ginx|wc -l

    3. wget、curl(http方式,判断根据返回值或返回内容)

    4. header(http),(http方式,根据状态码判断)

    5. 数据库特有:通过MySQL客户端连接,根据返回值或返回内容判断

    检查MySQL进程

    cat check.db.sh
    #!/bin/bash
    # local
    # if [ `ps -ef|grep [m]ysqld |wc -l ` -gt 0 ] 
    # if [ `netstat -lntup|grep [m]ysqld |wc -l ` -gt 0 ] 
    # if [ `lsof -i tcp:3306 |wc -l ` -gt 0 ] 
    
    # remote
    # if [ `nc -w 2 10.0.0.52 3306 &>/dev/null && echo OK|grep OK |wc -l` -gt 0 ]
    if [ `nmap 10.0.0.52 -p 3306 2>/dev/null |grep open |wc -l` -gt 0 ]
    	then 
    		echo "mysql is running."
    else 
    	echo "mysql is stoped."
    	echo "mysql will be started.starting..."
    	systemctl start mysqld
    fi
    

    检查web服务进程

    curl -I -s -o /dev/null -w "%{http_code}
    " http://10.0.0.71 -- 获取http_code
    [root@zabbix scripts]# cat check_web.sh 
    #!/bin/bash
    
    if [ `curl -I http://10.0.0.71 2>/dev/null |head -1|grep 200 |wc -l` -eq 1 ] 
    # if [ "`curl -s  http://10.0.0.71 &>/dev/null  && echo $?`" = "0"  ]
    # if [ "`curl -s  http://10.0.0.71`" = "bbs..."  ]
    #if [ "`curl -I -s -o /dev/null -w "%{http_code}
    " http://10.0.0.71`" = "200" ]
        then
    	echo "httpd is running."
    else
        echo "httpd is stopped."
    fi
    

    7.1.8 if 多分支实例3:数值比较大小

    [root@zabbix scripts]# cat com_if.sh 
    #!/bin/bash
    
    read -p "pls input two nums:" num1 num2
    a=$num1
    b=$num2
    
    ## no.1 -- check num of args
    if [ -z "$a" -o -z "$b" ] ;then
        echo "USAGE: sh "$0" num1 num2"
        exit 1
    fi
    ## no.2 -- check int of first arg
    if [ "`echo "$a" | sed -r 's/[^0-9]//g'`" != "$a" ] ;then
        echo "first arg must be int,please input a intger."
        exit 2
    fi
    ## -- check int of second arg 
    if [ !"`echo "$b"|sed -r 's/[^0-9]//g'`" = "$b" ] ;then
        echo "second arg must be int,please input a intger."
        exit 3
    fi
    ## no.3 compare
    if [ "$a" -eq "$b" ] ;then
        echo "$a = $b"
        exit 0
    elif
    [ "$a" -lt "$b" ] ;then
        echo "$a < $b"
        exit 0
    else
        echo "$a > $b"
        exit 0
    fi
    

    7.1.9 范例4:传参方式添加用户

    • 题目:实现通过传参的方式往/etc/user.conf里添加用户。具体要求你如下:
    1. 命令用法:
      USAGE:sh adduser {-add|-del|-search} username
    2. 传参要求:
      如果参数为-add时,表示添加后面接的用户名;
      如果参数为-del时,表示删除后面接的用户名;
      如果参数为-search,表示查找后面接的用户名。
    3. 如果有同名的用户则不能添加,没有对应用户则无需删除,查找到用户以及没有用户时给出明确提示。
    4. /etc/user.conf不能被所有外部用户直接删除及修改。
    5. 参考案例:open***通过ldap或ad统一认证解决方案思路分享
    • 参考答案:
    [root@zabbix 0508]# cat user.sh 
    #!/bin/bash
    File=/tmp/user.conf
    [ -f $File ] || {
    	echo "$File not exist,touch $File."
    } 
    chmod 644 $File
    if [ $# -ne 2 ];then
    	echo "USAGE:sh $0 {-add|-del|-search} username"
    	exit 1
    fi
    Option=$1
    Username=$2
    [ "$Option" = "-add" -o "$Option" = "-del" -o "$Option" = "-search" ]||{
    	echo "fisrt arg must be {-add|-del|-search}"
    	exit 2
    }
    if [ 0 -lt `echo $Username|grep -E "[^a-z|A-Z|0-9|_]"|wc -l` ]
    	then 
    		echo "username must be in {a-z|A-Z|0-9]|_}"
    		exit 2
    fi
    funCheckUser(){
    	[ `grep -w $Username $File|wc -l` -gt 0 ] && return 0 || return 1 	
    }
    funAddUser(){
    	funCheckUser
    	if [ $? -eq 0 ] ;then
        	    echo "$Username existed." 
        	    exit 0
    	else
        	    echo "$Username" >> $File
                echo "$Username has been added."
                exit 0
    	fi
    }
    funDelUser(){
    	funCheckUser
    	if [ $? -eq 0 ] ;then
        	echo "$Username existed.start deleting.." 
        	sed -i /^$Username$/d $File &>/dev/null
        	[ $? -eq 0 ] && echo "$Username has been deleted." || echo "delete $Username failed. "
        	exit 0
        else
        	echo "$Username not exist,do nothing."
    		exit 0
    	fi
    }
    funSearchUser(){
    	funCheckUser
    	if [ $? -eq 0 ] ;then
        	echo "$Username existed." 
        	exit 0
        else
        	echo "$Username not exist." 
        	exit 1
    	fi
    }
    case $Option in
    	-add)
    		funAddUser
    		;;
    	-del)
    		funDelUser
    		;;
    	-search)
    		funSearchUser
    		;;
    	*)
    		echo "USAGE:sh $0 {-add|-del|-search} username"
    		;;
    esac
    [root@zabbix 0508]# sh user.sh -add moox
    moox has been added.
    [root@zabbix 0508]# sh user.sh -search moox
    moox existed.
    [root@zabbix 0508]# sh user.sh -del moox
    moox existed.start deleting..
    moox has been deleted.
    [root@zabbix 0508]# sh user.sh -search moox
    moox not exist.
    
    

    7.2 if条件语句企业案例精讲

    7.2.1 监控Web和数据库的企业案例


    范例7-4:用if条件语句针对Nginx Web服务或MySQL数据库服务是否正常进行检测,如果服务未启动,则启动相应的服务。


    开发程序前的三部曲:

    分析问题先想一想监控Web服务和MySQL数据库服务是否异常的方法有哪些

    (1)监控Web服务和MySQL数据库服务是否异常的常见方法:

    监控事项 操作命令
    监控端口 1)在服务器本地监控端口常见命令:netstat、ss、lsof
    2)从远端监控服务器本地端口命令:telnet、nmap、nc
    监控服务进程或进程数 此方法适合本地服务器:过滤的是进程的名字
    ps -ef |grep nginx |wc -l
    ps -ef |grep mysqld| wc -l
    在客户端模拟用户访问 wget、curl命令进行测试:
    1)利用返回值$?进行判断
    2)获取特殊字符串进行判断--事先开发好程序
    3)根据HTTP响应header的情况进行判断
    登录MySQL数据库判断 mysql -u root -p mysql -e "select version();" &>/dev/null ;echo $?

    查看远端端口是否通畅的3个简单实用的案例见:http://oldboy.blog.51cto.com/2561410/942530

    (2)监控MySQL数据库异常

    ​ 1)MySQL数据库环境准备

    yum install -y mysql-server 
    systemctl astart mysqld
    netstat -lntup|grep mysql
    

    ​ 2)通过命令行检测数据库服务是否正常

    ## 本地命令 netstat、ss、lsof
    netstat -lntup|grep 3306|awk -F "[ :]+" 'print $5'
    netstat -lntup|grep 3306|wc -l
    netstat -lntup|grep mysql|wc -l
    ss -lntup|grep 3306|wc -l
    ss -lntup|grep mysql|wc -l
    lsof -i tcp:3306|wc -l
    ## 远端命令 telnet、nmap、nc
    yum install -y telnet nmap nc 
    nmap 127.0.0.1 -p|grep 3306|grep open|wc -l
    echo -e "
    " |telnet 127.0.0.1 3306 2>/dev/null|grep Connected|wc -l
    nc -w 2 127.0.0.1 3306 &>/dev/null  	# -w指定超时时间
    echo $?
    

    ....

    内容较多不在赘述...

    相关核心代码

    [root@oldboy C07]# cat 7_4_1.sh
    #!/bin/sh
    echo method1-------------------
    if [ `netstat -lnt|grep 3306|awk -F "[ :]+" '{print $5}'` -eq 3306 ]
    then
        echo "MySQL is Running."
    else
        echo "MySQL is Stopped."
        /etc/init.d/mysqld start
    fi
    echo method2-------------------
    if [ "`netstat -lnt|grep 3306|awk -F "[ :]+" '{print $5}'`" = "3306" ]
    then
        echo "MySQL is Running."
    else
        echo "MySQL is Stopped."
        /etc/init.d/mysqld start
    fi
    
    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
    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
    echo method5-------------------
    [ `rpm -qa nmap|wc -l` -lt 1 ] && yum install nmap -y &>/dev/null
    if [ `nmap 127.0.0.1 -p 3306 2>/dev/null|grep open|wc -l` -gt 0 ]
      then
        echo "MySQL is Running."
    else
        echo "MySQL is Stopped."
        /etc/init.d/mysqld start
    fi
    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 ]
      then
        echo "MySQL is Running."
    else
        echo "MySQL is Stopped."
        /etc/init.d/mysqld start
    fi
    echo method7-------------------
    if [ `ps -ef|grep -v grep|grep mysql|wc -l` -ge 1 ]
      then
        echo "MySQL is Running."
    else
        echo "MySQL is Stopped."
        /etc/init.d/mysqld start
    fi
    
    
    [root@oldboy C07]# cat 7_4_2.sh
    #!/bin/sh
    echo http method1-------------------
    if [ `netstat -lnt|grep 80|awk -F "[ :]+" '{print $5}'` -eq 80 ]
      then
        echo "Nginx is Running."
    else
        echo "Nginx is Stopped."
        /etc/init.d/nginx start
    fi
    echo http method2-------------------
    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
    
    
    
    echo http method3-------------------
    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
    echo http method4-------------------
    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
    echo http method5-------------------
    [ `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 ]
      then
        echo "Nginx is Running."
    else
        echo "Nginx is Stopped."
        /etc/init.d/nginx start
    fi
    echo http method6-------------------
    [ `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
    echo http method7-------------------
    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
    
    echo http method8-------------------
    if [[ `curl -I -s -o /dev/null -w "%{http_code}
    " http://127.0.0.1` =~ [23]0[012] ]]
      then
        echo "Nginx is Running."
    else
        echo "Nginx is Stopped."
        /etc/init.d/nginx start
    fi
    
    
    echo http method9-------------------
    if [ `curl -I http://127.0.0.1 2>/dev/null|head -1|egrep "200|302|301"|wc -l` -eq 1  ]
      then
        echo "Nginx is Running."
    else
        echo "Nginx is Stopped."
        /etc/init.d/nginx start
    fi
    echo http method10-------------------
    if [ "`curl -s http://127.0.0.1`" = "oldboy"  ]
      then
        echo "Nginx is Running."
    else
        echo "Nginx is Stopped."
        /etc/init.d/nginx start
    fi
    
    
    [root@oldboy C07]# cat 7_6.sh
    #!/bin/bash
    a=$1
    b=$2
    #no.1 judge arg nums.
    if [ $# -ne 2 ];then
        echo "USAGE:$0 arg1 arg2"
        exit 2
    fi
    
    #no.2 judge if int
    expr $a + 1 &>/dev/null
    RETVAL1=$?
    expr $b + 1 &>/dev/null
    RETVAL2=$?
    if [ $RETVAL1 -ne 0 -a $RETVAL2 -ne 0 ];then
        echo "please input two int again"
        exit 3
    fi
    
    if [ $RETVAL1 -ne 0 ];then
        echo "The first num is not int,please input again"
        exit 4
    fi
    
    if [ $RETVAL2 -ne 0 ];then
        echo "The second num is not int,please input again"
        exit 5
    fi
    
    #no.3 compart two num.
    if [ $a -lt $b ];then
        echo "$a<$b"
    elif [ $a -eq $b ];then
        echo "$a=$b"
    else
        echo "$a>$b"
    fi
    
    
    [root@oldboy C07]# cat 7_9.sh
    #!/bin/sh
    if [ $# -ne 1 ]
      then
        echo $"usage:$0{start|stop|restart}"
        exit 1
    fi
    if [ "$1" = "start" ]
      then
         rsync --daemon
         if [ `netstat -lntup|grep rsync|wc -l` -ge 1 ]
           then
             echo "rsyncd is started."
             exit 0
         fi
    elif [ "$1" = "stop" ]
      then
        pkill rsync
        if [ `netstat -lntup|grep rsync|wc -l` -eq 0 ]
          then
            echo "rsyncd is stopped."
            exit 0
        fi
    elif [ "$1" = "restart" ]
      then
        pkill rsync
        sleep 2
        rsync --daemon
    else
        echo $"usage:$0{start|stop|restart}"
        exit 1
    fi
    
  • 相关阅读:
    在网络中传输数据(I)
    WinForm DataGrid 中在 DataGridBoolColumn 的列标题上加一个 CheckBox 实现全选和全不选
    datagrid 相关
    Agile Framework视频演示发布
    asp.net(含:模拟登陆,照片列表)
    会计电算化常考题目一
    jquery实例教学一
    ASP .net(照片列表详细功能CRUD演示)
    会计电算化常考题目
    ASP.NET(get和post比较)
  • 原文地址:https://www.cnblogs.com/moox/p/12808242.html
Copyright © 2011-2022 走看看