返回顶部

zhangfd

个人博客,仅供学习使用

导航

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\n\
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\n\
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 \n\
*/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}\n" 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}\n" 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 "\n" |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}\n" 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

posted on 2020-04-30 13:08  zhangfd  阅读(459)  评论(0编辑  收藏  举报