五、流程控制语句-if选择结构
if选择结构
箴言1:只要正确,就要一直向前冲
if选择结构-单分支
当'条件成立'时执行相应的操作。否则,不执行任何操作
格式1:
if 条件判断表达式;then 条件判断成立时,要执行的操作 fi
格式2
if 条件判断表达式 then 条件判断成立时,要执行的操作 fi
或者:
if [ condition ];then command command fi if test 条件;then 命令 fi if [[ 条件 ]];then 命令 fi [ 条件 ] && command
例子1:
#!/bin/bash ping -c 3 localhost &> /dev/null if [ $? -eq 0 ];then echo aaaaa fi
例子2:
#!/bin/bash read -p "please input ip address " addr if [ -z $addr ];then echo "你没有输入要ping的ip地址" exit fi ping -c 3 $addr &> /dev/null if [ $? -eq 0 ];then echo "$addr is onlines" fi echo "script over!!!"
提示:分号相当于命令分号,上面两种语法等同。
特殊写法:if [ -f "$file1" ];then echo 1;fi相当于[ -f "$file1" ] && echo 1
下面举几个使用if条件句的例子
范例1:单分支if条件句整数比较大小
[root@localhost ~]#cat if_01.sh a=$1 b=$2 if [ $a -gt $b ] then echo "yes,$a >= $b" fi if [ $a -le $b ] then echo "yes,$a<=$b" fi [root@localhost ~]# sh if_01.sh 4 5 yes,4<=5
范例2:使用read及脚本传参如何实现上述比较
解答:
[root@localhost ~]# cat if_01.sh
read -p "pls input two numbers:" a b if [ $a -gt $b ] then echo "yes,$a >= $b" fi if [ $a -le $b ] then echo "yes,$a<=$b" fi
[root@localhost ~]# sh if_01.sh
pls input two numbers:100 99 yes,100 >= 99
提示:思考以上脚本有什么缺点?
范例3:实现如果/server/scripts下面存在if3.sh就打印if3.sh存在。(如果执行脚本后发现文件不存在,就创建这个脚本)
方法1:if条件句实现
[root@localhost scripts]# cat if4.sh #!/bin/bash FILEPATH="server/scripts" if [ -e "$FILEPATH/if3.sh" ] then echo "$FILEPATH/if3.sh is exist." fi if [ ! -e "$FILEPATH/if3.sh" ] then [ ! -d $FILEPATH ] && mkdir -p $FILEPATH [ -d $FILEPATH ] && { cd $FILEPATH touch if3.sh echo "if3.sh is touched." } fi
[root@localhost scripts]# sh -x if4.sh
+ FILEPATH=server/scripts + '[' -e server/scripts/if3.sh ']' + '[' '!' -e server/scripts/if3.sh ']' + '[' '!' -d server/scripts ']' + mkdir -p server/scripts + '[' -d server/scripts ']' + cd server/scripts + touch if3.sh + echo 'if3.sh is touched.' if3.sh is touched.
范例4:判断系统内存大小,低于100M就进行邮件报警
[root@localhost scripts]# free -m
total used free shared buffers cached Mem: 988 769 218 0 97 313 -/+ buffers/cache: 358 629 Swap: 2047 0 2047
[root@localhost scripts]# free -m|awk '/buffers\// {print $NF}'
629
[root@localhost scripts]# cat judge_system.sh
cur_free=`free -m|awk '/buffers\// {print $NF}'` chars="current memory is $cur_free." if [ $cur_free -lt 650 ] then echo $chars echo $chars|mail -s "chars" 12345678@qq.com fi
[root@localhost scripts]# sh judge_system.sh
current memory is 629.
用定时任务每分钟检查(如果每分钟检查的话,就不用输出了):
[root@localhost scripts]# cat judge_system.sh chars="current memory is $cur_free." if [ $cur_free -lt 650 ] then echo $chars|mail -s "chars" 12345678@qq.com fi
[root@localhost scripts]# crontab -e
#judge..... * * * * * /bin/bash /server/scripts/judge_system.sh >&/dev/null
if选择结构-双分支
箴言2:分叉路口,二选一
当'条件成立'时执行命令序列1。否则,执行命令序列2
格式1:
if 条件判断表达式;then 条件判断成立时,要执行的操作 else 条件判断不成立时,要执行的操作 fi
格式2:
if 条件判断表达式 then 条件判断成立时,要执行的操作 else 条件判断不成立时,要执行的操作 fi
或者:
if [ condition ];then command1 else command2 fi [ 条件 ] && command1 || command2
特殊写法:
if [ -f “$file1” ];then echo 1;else echo 0;fi相当于:[ -f “$file1” ] && echo 1 || echo 0
例子1:
如果httpd服务在运行着就输出 "网站服务正在运行"
如果httpd服务没有运行 就把网站服务开启
#!/bin/bash service httpd status &> /dev/null if [ $? -eq 0 ];then echo "网站服务正在运行" else service httpd start fi
例子2:
#!/bin/bash service sshd status &> /dev/null if [ $? -eq 0 ];then echo "sshd in running" else service sshd start fi
例子3:
检查任意一个服务的状态
如果服务是运行着的,就输出服务名is running
如果服务没有运行,就启动服务。
#!/bin/bash service $1 status &> /dev/null if [ $? -eq 0 ];then echo "$1 is running!!!!" else service $1 start fi
只检查服务vsftpd httpd sshd crond mysql中的任意一个服务的状态,如果不是这5个,就提示用户能够检查服务名并退出脚本
#!/bin/bash read -p "请输入服务名" servername if [ $ servername=="vsftpd" -o $servername=="httpd" -o $servername="sshd" -o $servername="crond" -o $servername=mysql];then service $servicename status &> /dev/null if [ $? -eq 0 ];then echo $ servicename is running else service $servicename start fi fi
根据学生输入的成绩判断学生成绩的优劣。学生成绩的分数范围在1~100区间。成绩分数小于60输出不及格;成绩分数大于等于60输出 及格
read -p "请输入学生成绩:" chengji if [ -z $chengji ];then exit fi if [ $chengji -ge 1 ]&& [ $chengji -le 100 ] then if [ $cengji -lt 60 ] then echo "不及格" else echo "及格" fi else echo "输入格式错误" fi
#ifelse_exam1脚本用于判断输入的文件名是否有对应的文件存在
#!/bin/bash #if语句用于判断输入的文件是否不存在,不存在则执行then和else间的命令 if [ ! -e "$1" ] then echo "file $1 do not exist." exit 1 #输入的文件存在时,执行else和fi间的命令 else echo "file $1 exist." fi
#ifelse_exam2脚本用于删除一个文件并判断是否执行了该操作
#!/bin/bash #提示用户输入要删除的文件 echo "Please input the file which you want to delete:" read file #通过if/else结构判断文件是否被删除 if rm -f "$file" then echo "Delete the file $file successfully!" else echo "Delete the file $file failed!" fi
每周一的 23:30 备份当前数据库服务器上所有的binlog日志文件到系统的/binlogdir目录里.
#!/bin/bash mysql="/var/lib/mysql" date=(date +\%Y\%m\%d) cd $mysql if [ -e /binlogdir ];then tar -zcf /binlogdir/binlog-$date.tar.gz data-bin.* &> /dev/null else mkdir /binlogdir tar -zcf /binlogdir/binlog-$date.tar.gz data-bin.* &> /dev/null fi
小试牛刀:
让用户自己输入字符串,如果用户输入的是hello,请打印world,否则打印“请输入hello”
read定义变量 if....else...
实现:
#!/bin/env bash read -p '请输入一个字符串:' str if [ "$str" = 'hello' ];then echo 'world' else echo '请输入hello!' fi 1 #!/bin/env bash 2 3 read -p "请输入一个字符串:" str 4 if [ "$str" = "hello" ] 5 then 6 echo world 7 else 8 echo "请输入hello!" 9 fi echo "该脚本需要传递参数" 1 if [ $1 = hello ];then 2 echo "hello" 3 else 4 echo "请输入hello" 5 fi #!/bin/env bash A=hello B=world C=hello if [ "$1" = "$A" ];then echo "$B" else echo "$C" fi read -p '请输入一个字符串:' str; [ "$str" = 'hello' ] && echo 'world' || echo '请输入hello!'
if选择结构-多分支
箴言3:选择很多,能走的只有一条
相当于if语句嵌套。针对多个条件分别执行不同的操作
格式1:
if 条件判断表达式1;then 条件1判断成立时,要执行的操作
elif 条件判断表达式2;then 条件2判断成立时,要执行的操作
if 条件判断表达式N;then 条件N判断成立时,要执行的操作
else 以上所有的条件判断都不成立时,要执行的操作 fi
或者:
if [ condition1 ];then command1 结束 elif [ condition2 ];then command2 结束 else command3 fi
注释:
如果条件1满足,执行命令1后结束;如果条件1不满足,再看条件2,如果条件2满足执行命令2后结束;如果条件1和条件2都不满足执行命令3结束.
语法:
if [ condition1 ];then command1 if [ condition2 ];then command2 fi else if [ condition3 ];then command3 elif [ condition4 ];then command4 else command5 fi fi
注释:
如果条件1满足,执行命令1;如果条件2也满足执行命令2,如果不满足就只执行命令1结束;
如果条件1不满足,不看条件2;直接看条件3,如果条件3满足执行命令3;如果不满足则看条件4,如果条件4满足执行命令4;否则执行命令5
根据学生输入的成绩判断学生成绩的优劣。
学生成绩的分数范围在1~100区间
成绩 分数小于60 输出 不及格
成绩 分数大于等于60且小于80 输出 良好
成绩 分数大于80且小于100 输出 优秀
如果输入的成绩超出成绩区间,就输出提示信息:成绩的分数范围在1~100区间
#!/bin/bash read -p "输入成绩" cj if [ -z $cj ];then echo "你没有输入成绩分数" exit else if [ $cj -eq 0 ];then echo "补考" elif [ $cj -lt 0 ];then echo "输入的成绩超过范围,有效范围在1-100"
elif [ $cj -ge 1 ]&&[ $cj -lt 60 ];then echo "不及格"
elif [ $cj -ge 60 ]&&[ $cj -lt 80 ];then echo "良好"
elif [ $cj -ge 80 ]&&[ $cj -le 100 ];then echo "优秀"
elif [ $cj -gt 1 ];then echo "输入的成绩超过范围,有效范围在1-100" fi fi
练习:写一个脚本
传递一个参数(单字符就行)给脚本,如参数为q、Q、quit或Quit,就退出脚本;否则,就显示用户的参数;
#!/bin/bash # if [ $1 = 'q' ];then echo "Quiting..." exit 1 elif [ $1 = 'Q' ];then echo "Quiting..." exit 2 elif [ $1 = 'quit' ];then echo "Quiting..." exit 3 elif [ $1 = 'Quit' ];then echo "Quiting..." exit 4 else echo $1 fi
#ifelifelse_exam1.sh脚本
#!/bin/bash #提示用户输入分数(0~100) echo "Please Input a integer(0-100): " read score #判断学生的分数类别 if [ "$score" -lt 0 -o "$score" -gt 100 ] then echo "The score what you input is not integer or score is not in (0-100)" elif [ "$score" -ge 90 ] then echo "The grade is A!" elif [ "$score" -ge 80 ] then echo "The grade is B! " elif [ "$score" -ge 70 ] then echo "The grade is C!" elif [ "$score" -ge 60 ] then echo "The grade is D! " else echo "The grade is E! " fi
判断是否是闰年
#ifelifelse-exam2.sh脚本的执行结果 #!/bin/bash #提示输入年份 echo "Please input a year: " read year #设置取余参数 let "n1=$year % 4" let "n2=$year % 100" let "n3=$year % 400" #判断输入的年份是否是闰年 if [ ! "$n1" -eq 0 ] then leap=0 elif [ ! "$n2" -eq 0 ] then leap=1 elif [ ! "$n3" -eq 0 ] then leap=0 else leap=1 fi #输出用户输入的年份是否是闰年 if [ "$leap" -eq 1 ] then echo "$year is a leap year!" else echo "$year is not a leap year!" fi
范例5:多分支if条件句整数比较大小
[root@localhost scripts]# cat if_02.sh read -p "pls input two numbers:" a b if [ $a -gt $b ] then echo "yes,$a > $b" elif [ $a -eq $b ] then echo "yes,$a=$b" else echo "yes,$a<$b" fi
[root@localhost scripts]# sh if_02.sh
pls input two numbers:4 5
yes,4<5
范例6:以命令行脚本传参的方式比较两个数的大小,请用多分支if语句来实现。
法1:多分支if语句实现对传入的参数进行判断的方法
[root@localhost scripts]# cat if_02.sh
a=$1 b=$2 if [ $# -ne 2 ] then echo "Usage:sh $0 num1 num2" exit 1 fi if [ $a -gt $b ] then echo "yes,$a > $b" elif [ -eq $b ] then echo "yes,$a=$b" else echo "yes,$a<$b" fi
法2:多分支if语句实现对参数个数及类型严格判断的方法
[root@localhost scripts]# cat if_02.sh a=$1 b=$2 if [ $# -ne 2 ] then echo "Usage:sh $0 num1 num2" exit 1 fi [ -n "`echo $1|sed ' s/[0-9]//g'`" ]&& echo "第一个参数必须为数字" && exit 1 [ -n "`echo $2|sed ' s/[0-9]//g'`" ]&& echo "第二个参数必须为数字" && exit 1 if [ $a -gt $b ] then echo "yes,$a > $b" elif [ -eq $b ] then echo "yes,$a=$b" else echo "yes,$a<$b" fi
扩展:判断字符串是否为数字的多种方法
法1:sed加正则表达式
命令行传参:
组合语法判断1:
[ -n "`echo $num|sed ' s/[0-9]//g'`" -a -n "`echo $2|sed ' s/[0-9]//g'`" ] &&\
echo "两个参数都必须为数字" && exit 1
组合语法判断2:
[ -n "`echo $num|sed ' s/[0-9]//g'`" -a -n "`echo $2|sed ' s/[0-9]//g'`" ] &&{ echo "两个参数都必须为数字 exit 1 }
单个判断语法:
[ -n "`echo $1|sed ' s/[0-9]//g'`" ] && echo "第一个参数必须为数字" && exit 1 [ -n "`echo $2|sed ' s/[0-9]//g'`" ] && echo "第二个参数必须为数字" && exit 1
普通变量判断:
[ -n "`echo $num|sed ' s/[0-9]//g'`" ] && echo "第二个参数必须为数字" && exit 1
条件表达式,大括号的用法:
[ -n "`echo $num|sed ' s/[0-9]//g'`" ] && { echo "第二个参数必须为数字" exit 1 }
法2:变量的子串替换加正则表达式
[root@localhost scripts]# num=oldboy512
[root@localhost scripts]# [ -z "`echo "${num//[0-9]/}"`" ] && echo 1 || echo 0
0
[root@localhost scripts]# num=512old512
[root@localhost scripts]# [ -z "`echo "${num//[0-9]/}"`" ] && echo 1 || echo 0
0 #这个说明前面的结果不为0,即有非数字字符
[root@localhost scripts]# num=521
[root@localhost scripts]# [ -z "`echo "${num//[0-9]/}"`" ] && echo 1 || echo 0
1 #这个说明前面的结果去掉数字后为0,即没有非数字字符
法3:变量的子串替换加正则表达式(特殊判断思路)
思路:如果num长度不为0,并且把num中的非数字部分删除,然后看结果是不是等于num本身,如果两者都成立就是数字。
-z “$num” #如果num长度不为0表达式 “$num” ="${num//[^0-9]/}" #把num中的非数字部分删除,然后结果是不是等于num本身,如果两者都成立就是数字。
完整表达式:
[root@localhost scripts]# [ -n "$num" -a "$num" = "$num//[^0-9]/" ] && echo "it is num"
法4:expr计算判断
expr $1 + 0>/dev/null 2>&1 #把变量和整数相加看是否成功执行 [ $? -eq 0 ] && eccho init
范例5:通过read读入变量方式的多分支if语句比较整数大小
[root@localhost scripts]#cat if-multi.sh #!/bin/bash #this scripts is created by oldboy #fun:compare two num read -t 10 -p "pls input two num:" a b if [ $a -gt $b ];then echo "yes,$a > $b" elif [ -eq $b ];then echo "yes,$a=$b" else echo "yes,$a<$b" fi
另一种写法:用(())代替[]
[root@localhost scripts]#cat if-multi.sh #!/bin/bash #this scripts is created by oldboy #fun:compare two num read -t 10 -p "pls input two num:" a b if (( $a > $b ));then echo "yes,$a > $b" elif [ -eq $b ];then echo "yes,$a=$b" else echo "yes,$a<$b" fi
特别提示:一般生产运维中的脚本,使用read的方式很少,除非为用户写交互式程序脚本。一般为传参或者定义变量的方式。
范例6:生产环境监控MySQL服务的实战例子
问题描述:监控MySQL服务是否正常启动,如果没有正常启动,就启动MySQL服务。这里需要大家实现准备MySQL服务的基本环境。
法1:本方法的实现思路是过滤出MySQL端口3306进行判断。具体脚本如下:
[root@localhost script]# cat check_db.sh #!/bin/bash ### portNum=`netstat -lnt | grep 3306|awk -F '[ :]+' '{print $5}'` #这里的思路不是最佳的 if [ #portNum -eq 3306 ];then #这里的判断最好用字符串判断的语法;假如端口不存在,显示[: -eq: unary operator expected echo "db is running" else /data/3306/mysql restart #这是多实例MySQL启动脚本 fi
思考:本脚本的好处和局限是什么?
或者:
[root@localhost script]# cat check_db.sh
#!/bin/bash ### portNum=`netstat -lnt | grep 3306|awk -F '[ :]+' '{print $5}'` if [ $portNum -eq 3306 ];then echo "db is running" else /etc/init.d/mysqld restart #普通MySQL服务启动 fi
解决-eq: unary operator expected的方法:不规范;对于多实例脚本启动有效,但对普通MYSQL启动问题仍然存在
[root@localhost script]# cat check_db01.sh #!/bin/bash ### portNum=`netstat -lnt | grep 3306|awk -F '[ :]+' '{print $5}'` if [ $portNum == “3306” ];then echo "db is running" else /data/3306/mysql restart fi
通过端口判断更简易实现脚本
[root@localhost script]# cat check_db02.sh #!/bin/bash ### portNum=`netstat -lnt | grep 3306|wc -l` if [ #portNum -eq 1 ];then echo "db is running" else /data/3306/mysql restart fi
法2:本方法的实现思路是如果MySQL端口和端口同时存在,即认为MySQL服务正常。
(1)写脚本前首先人工检查MySQL服务是否OK
[root@localhost script]# /data/3306/mysql start 正在启动 mysqld:
[root@localhost ~]# netstat -lnt | grep 3306
tcp 0 0 0.0.0.0:3306 0.0.0.0:* LISTEN
[root@localhost script]# ps -ef|grep mysql|grep -v grep|wc -l
2 #通过把进程转换成为行数,即进程个数,方便做判断。
[root@localhost ~]# netstat -lnt | grep 3306|wc -l
1 #通过把端口转换为行数,即端口个数,方便做判断
提示:根据以上结果可以知道MySQL服务是正常的(多数情况下)。
(2)实际的脚本监控内容
方法1:
[root@localhost script]# cat check_db03.sh #!/bin/bash ### portNum=`netstat -lnt | grep 3306|wc -l` mysqlProcessNum=`ps -ef|grep mysql|grep -v grep|wc -l` if [ #portNum -eq 1 -a $mysqlProcessNum -eq 2 ];then echo "db is running" else /data/3306/mysql restart fi
或者
[root@localhost script]# cat check_db03.sh #!/bin/bash ### portNum=`netstat -lnt | grep 3306|wc -l` mysqlProcessNum=`ps -ef|grep mysql|grep -v grep|wc -l` if [ #portNum -eq 1 ] && [ $mysqlProcessNum -eq 2 ];then echo "db is running" else /data/3306/mysql restart fi
方法2:
[root@localhost script]# cat if-judge-db0.sh #!/bin/bash ### MYSQL=/data/3306/mysql LogPath=/tmp/mysql.log portNum=`netstat -lnt | grep 3306|wc -l` mysqlProcessNum=`ps -ef|grep mysql|grep -v grep|wc -l` if [ #portNum -eq 1 ] && [ $mysqlProcessNum -eq 2 ];then echo "db is running" else $MYSQL start >$LogPath sleep 10 portNum=`netstat -lnt | grep 3306|wc -l` mysqlProcessNum=`ps -ef|grep mysql|grep -v grep|wc -l` if [ #portNum -ne 1 ] && [ $mysqlProcessNum -ne 2 ];then while true do killall mysqld >/dev/null 2>&1 [ $? -ne 0 ] && break sleep 1 done $MYSQL start >>$LogPath && status="successful" || status="failure" mail -s "mysql startup status is $status" 1092327070@qq.com < $LogPath fi fi
法3:本方法的实现思路是:模拟web服务器,通过mysql账户连接mysql,然后根据返回命令状态或返回内容确认mysql是否正常(推荐)
(1)手动检查(写脚本之前都离不开手工检查):
[root@localhost script]# mysql -uroot -p 'oldboy' -S /data/3306/mysql.sock -e "select version();"
(1)简单的脚本实现:
法1:
法2:
[root@localhost script]# cat check_db.sh #!/bin/bash ### mysqlStatus=`mysql -uroot -p 'oldboy' -S /data/3306/mysql.sock -e "select version();" >& /dev/null` if [ $? -eq 0 ];then echo "db is running" else /data/3306/mysql restart fi
复杂点的脚本实现:
#!/bin/bash ### MYSQL=/data/3306/mysql LogPath=/tmp/mysql.log mysqlStatus=`mysql -uroot -p 'oldboy' -S /data/3306/mysql.sock -e "select version();" >&/dev/null` if [$? -eq 0 ];then echo "db is running" exit 0 else $MYSQL start >$LogPath sleep 10 mysqlStatus=`mysql -uroot -p 'oldboy' -S /data/3306/mysql.sock -e "select version();" >&/dev/null` if [ $? -ne 0 ];then while true do killall mysqld >/dev/null 2>&1 [ $? -ne 0 ] && break sleep 1 done $MYSQL start >>$LogPath && status="successful" || status="failure" mail -s "mysql startup status is $status" 12345678@qq.com < $LogPath fi fi
法4:更专业的监控数据库生成脚本解决方案
#!/bin/bash ### MYSQL=/data/3306/mysql LogPath=/tmp/mysql.log mysqlStatus=`mysql -uroot -p 'oldboy' -S /data/3306/mysql.sock -e "select version();" >&/dev/null` if [$? -eq 0 ];then echo "db is running" else [ -x $MYSQL ] && $MYSQL start >$LogPath sleep 10 mysqlStatus=`mysql -uroot -p 'oldboy' -S /data/3306/mysql.sock -e "select version();" >&/dev/null` if [ $? -ne 0 ];then while true do killall mysqld >/dev/null 2>&1 [ $? -ne 0 ] && break sleep 1 done [ -x $MYSQL ] && $MYSQL start >>$LogPath && status="successful" || status="failure" mail -s "mysql startup status is $status" 1092327070@qq.com < $LogPath fi fi
层层嵌套结构
箴言4:多次判断,带你走出人生迷雾。
if [ condition1 ];then command1 if [ condition2 ];then command2 fi else if [ condition3 ];then command3 elif [ condition4 ];then command4 else command5 fi fi 注释: 如果条件1满足,执行命令1;如果条件2也满足执行命令2,如果不满足就只执行命令1结束; 如果条件1不满足,不看条件2;直接看条件3,如果条件3满足执行命令3;如果不满足则看条件4,如果条件4满足执行命令4;否则执行命令5
2. 应用案例
㈠ 判断两台主机是否ping通
**需求:**判断当前主机是否和远程主机是否ping通
① 思路
使用哪个命令实现 ping -c次数 根据命令的执行结果状态来判断是否通$? 根据逻辑和语法结构来编写脚本(条件判断或者流程控制)
② 落地实现
#!/bin/env bash # 该脚本用于判断当前主机是否和远程指定主机互通 # 交互式定义变量,让用户自己决定ping哪个主机 read -p "请输入你要ping的主机的IP:" ip # 使用ping程序判断主机是否互通 ping -c1 $ip &>/dev/null if [ $? -eq 0 ];then echo "当前主机和远程主机$ip是互通的" else echo "当前主机和远程主机$ip不通的" fi
或者:
#!/bin/bash # Name:ping.sh # Path:/shell02/ # Usage:/shell02/ping.sh # ... #使用ping命令来判断是否和远程主机互通 if [ $# -ne 1 ];then echo "Usage:$0 remote_ip" && exit fi 或者 [ $# -ne 1 ] && echo "Usage:$0 remote_ip" && exit ping -c1 $1 &>/dev/null [ $? -eq 0 ] && echo "当前主机和远程主机$1是互通的。" ||echo "当前主机和远程主机$1是不通的。" 说明:exit直接退出程序
㈡ 判断一个进程是否存在
**需求:**判断web服务器中httpd进程是否存在
① 思路
查看进程的相关命令 ps pgrep
根据命令的返回状态值来判断进程是否存在
根据逻辑用脚本语言实现
② 落地实现
#!/bin/env bash # 判断一个程序(httpd)的进程是否存在 pgrep httpd &>/dev/null if [ $? -ne 0 ];then echo "当前httpd进程不存在" else echo "当前httpd进程存在" fi 或者 test $? -eq 0 && echo "当前httpd进程存在" || echo "当前httpd进程不存在"
③ 补充命令
pgrep命令:以名称为依据从运行进程队列中查找进程,并显示查找到的进程id 选项 -o:仅显示找到的最小(起始)进程号; -n:仅显示找到的最大(结束)进程号; -l:显示进程名称; -P:指定父进程号;pgrep -p 4764 查看父进程下的子进程id -g:指定进程组; -t:指定开启进程的终端; -u:指定进程的有效用户ID。
㈢ 判断一个服务是否正常
**需求:**判断门户网站是否能够正常访问
① 思路
1.可以判断进程是否存在,用/etc/init.d/httpd status判断状态等方法
2.最好的方法是直接去访问一下,通过访问成功和失败的返回值来判断
Linux环境,wget curl elinks -dump
② 落地实现
#!/bin/env bash # 判断门户网站是否能够正常提供服务 #定义变量 web_server=www.itcast.cn #访问网站 wget -P /shell/ $web_server &>/dev/null [ $? -eq 0 ] && echo "当前网站服务是ok" && rm -f /shell/index.* || echo "当前网站服务不ok,请立刻处理"
3. 课堂练习
㈠ 判断用户是否存在
**需求1:**输入一个用户,用脚本判断该用户是否存在
#!/bin/env bash 2 read -p "请输入一个用户名:" user_name 3 id $user_name &>/dev/null 4 if [ $? -eq 0 ];then 6 echo "该用户存在!" 7 else 8 echo "用户不存在!" 9 fi #!/bin/bash # 判断 用户(id) 是否存在 read -p "输入壹个用户:" id id $id &> /dev/null if [ $? -eq 0 ];then echo "该用户存在" else echo "该用户不存在" fi #!/bin/env bash read -p "请输入你要查询的用户名:" username grep -w $username /etc/passwd &>/dev/null if [ $? -eq 0 ] then echo "该用户已存在" else echo "该用户不存在" fi #!/bin/bash read -p "请输入你要检查的用户名:" name id $name &>/dev/null if [ $? -eq 0 ] then echo 用户"$name"已经存在 else echo 用户"$name"不存在 fi #!/bin/env bash #判断用户是否存在 read -p "请写出用户名" id id $id if [ $? -eq 0 ];then echo "用户存在" else echo "用户不存在" fi #!/bin/env bash read -p '请输入用户名:' username id $username &>/dev/null [ $? -eq 0 ] && echo '用户存在' || echo '不存在'
㈡ 判断软件包是否安装
**需求2:**用脚本判断一个软件包是否安装,如果没安装则安装它(假设本地yum已配合)
㈢ 判断当前主机的内核版本
**需求3:**判断当前内核主版本是否为2,且次版本是否大于等于6;如果都满足则输出当前内核版本
思路: 1. 先查看内核的版本号 uname -r 2. 先将内核的版本号保存到一个变量里,然后再根据需求截取出该变量的一部分:主版本和次版本 3. 根据需求进步判断 #!/bin/bash kernel=`uname -r` var1=`echo $kernel|cut -d. -f1` var2=`echo $kernel|cut -d. -f2` test $var1 -eq 2 -a $var2 -ge 6 && echo $kernel || echo "当前内核版本不符合要求" 或者 [ $var1 -eq 2 -a $var2 -ge 6 ] && echo $kernel || echo "当前内核版本不符合要求" 或者 [[ $var1 -eq 2 && $var2 -ge 6 ]] && echo $kernel || echo "当前内核版本不符合要求" 或者 #!/bin/bash kernel=`uname -r` test ${kernel:0:1} -eq 2 -a ${kernel:2:1} -ge 6 && echo $kernel || echo '不符合要求' 其他命令参考: uname -r|grep ^2.[6-9] || echo '不符合要求'
vsftpd服务器已启动...
vsftpd监听的端口是:
vsftpd的进程PID是:
参考1: #!/bin/bash service vsftpd status &>/dev/null if [ $? -eq 0 ];then port=`netstat -tnltp|grep vsftpd|cut -d: -f2|cut -d' ' -f1` pid=`pgrep -l vsftpd|cut -d ' ' -f1` echo -e "vsftpd服务器已启动...\nvsftpd监听的端口是:$port\nvsftpd的进程PID是:$pid" else service vsftpd start &>/dev/null port=`netstat -tnltp|grep vsftpd|cut -d: -f2|cut -d' ' -f1` pid=`pgrep -l vsftpd|cut -d ' ' -f1` echo -e "vsftpd服务器已启动...\nvsftpd监听的端口是:$port\nvsftpd的进程PID是:$pid" fi 参考2: [root@server shell02]# cat liufeng.sh #!/bin/bash service $1 status if [ $? -eq 0 ];then echo " '$1'服务器已启动..." a=$( netstat -tnulp | grep $1 ) array=($a) echo "$1的监听端口是:$(echo ${array[3]} | cut -d: -f2) " echo "$1的进程ID为:$(echo ${array[6]}| cut -d/ -f1)" else echo "$1进程未启动!" fi 参考3: vim /lt/2.sh #! /bin/bash duankou=`netstat -ntlp|grep vsftpd|cut -d: -f2|cut -d" " -f1` pid=`pgrep -o vsftpd` vim 1.sh pgrep -l vsftpd >/dev/null if [ $? -eq 0 ];then echo "vsftpd服务器已启动..." echo "vsftpd监听的端口是:$duankou" echo "vsftpd的进程PID是:$pid" else echo "vsftpd服务器没启动" service vsftpd start source /lt/2.sh fi
参考:https://note.youdao.com/ynoteshare1/index.html?id=b402ca42248d060e7bdd5ee145f47cc5&type=notebook##/0367BDF68CCB4774B3846EE70F9B5237