1、1第八章 编写Shell管理脚本(二)2课程回顾课程回顾l如何为变量赋值?如何查看变量的值?l在变量应用中,反撇号的用途是什么?l变量$0、$1、$?、$分别是什么含义?l有哪些方式可以执行Shell脚本中的语句?3技能展示技能展示l熟悉条件测试的应用l会使用if条件语句l会使用for、while循环语句l会使用case分支语句l了解其他控制语句及函数的使用4编写编写Shell管理管理脚本(二)脚本(二)本章结构本章结构使用使用if条件语条件语句句条件测试操作条件测试操作 case语句语句 if语句的结构语句的结构 until循环循环 if语句应用示例语句应用示例 使用使用for循环循环语句语
2、句 其他控制语句其他控制语句 for语句的结构语句的结构 for语句应用示例语句应用示例 while语句的结构语句的结构 while语句应用示例语句应用示例 使用使用while循循环语句环语句 循环控制语句循环控制语句 shift 语句语句函数的定义和调用函数的定义和调用 Shell函数应函数应用用 函数的参数传递函数的参数传递 5条件测试操作条件测试操作ltest命令用途:测试特定的表达式是否成立,当条件成立时,命令执行后的返回值为0,否则为其他数值格式:test 条件表达式 条件表达式 l常见的测试类型测试文件状态字符串比较整数值比较逻辑测试6条件测试操作条件测试操作l测试文件状态格式:操
3、作符 文件或目录 l常用的测试操作符-d:测试是否为目录(Directory)-e:测试目录或文件是否存在(Exist)-f:测试是否为文件(File)-r:测试当前用户是否有权限读取(Read)-w:测试当前用户是否有权限写入(Write)-x:测试当前用户是否可执行(Excute)该文件-L:测试是否为符号连接(Link)文件rootlocalhost#-d/etc/vsftpd rootlocalhost#echo$?0rootlocalhost#-d/etc/hosts rootlocalhost#echo$?1返回值为返回值为0,表示上一,表示上一步测试的条件成立步测试的条件成立ro
4、otlocalhost#-e/media/cdrom&echo YESYES rootlocalhost#-e/media/cdrom/Server&echo YES“rootlocalhost#如果测试的条件成立如果测试的条件成立则输出则输出“YES”7条件测试操作条件测试操作l整数值比较格式:整数1 操作符 整数2 l常用的测试操作符-eq:等于(Equal)-ne:不等于(Not Equal)-gt:大于(Greater Than)-lt:小于(Lesser Than)-le:小于或等于(Lesser or Equal)-ge:大于或等于(Greater or Equal)rootloc
5、alhost#who|wc-l5rootlocalhost#who|wc-l-le 10&echo YESYES rootlocalhost#df-hT|grep/boot|awk print$612%rootlocalhost#BootUsage=df-hT|grep/boot|awk print$6|cut-d%-f 1rootlocalhost#echo$BootUsage12rootlocalhost#$BootUsage-gt 95&echo YES 如果登录用户数小于或如果登录用户数小于或等于等于10则输出则输出 YES如果如果/boot分区的磁盘使用率分区的磁盘使用率超过超过95
6、%则输出则输出 YES8条件测试操作条件测试操作l字符串比较格式:字符串1 =字符串2 字符串1 !=字符串2 -z 字符串 l常用的测试操作符=:字符串内容相同!=:字符串内容不同,!号表示相反的意思-z:字符串内容为空rootlocalhost#read-p Location:FilePathLocation:/etc/inittabrootlocalhost#$FilePath=/etc/inittab&echo YESYES rootlocalhost#$LANG!=en.US&echo$LANGzh_CN.UTF-8 如果键入路径与指定的如果键入路径与指定的目录一致则输出目录一致则输
7、出 YES如果当前的语言环境不是如果当前的语言环境不是 en_US,则输出则输出LANG变量的值变量的值9条件测试操作条件测试操作l逻辑测试格式:表达式1 操作符 表达式2 .l常用的测试操作符-a或&:逻辑与,“而且”的意思l 前后两个表达式都成立时整个测试结果才为真,否则为假-o或|:逻辑或,“或者”的意思l 操作符两边至少一个为真时,结果为真,否则结果为假!:逻辑否l 当指定的条件不成立时,返回结果为真rootlocalhost#echo$USERrootrootlocalhost#$USER!=teacher&echo Not teacherNot teacherrootlocalho
8、st#$USER=teacher|echo Not teacherNot teacher如果发现用户不是如果发现用户不是 teacher则提示:则提示:“Not teacher”与上一命令行效果相同与上一命令行效果相同10if条件语句条件语句 单分支单分支l当“条件成立”时执行相应的操作if 条件测试命令条件测试命令 then 命令序列命令序列fiif 磁盘已用空间磁盘已用空间80%then 报警报警fiif 条件测试命令条件测试命令命令序列命令序列fi 结束判断结束判断条件为真条件为真 then条件为假条件为假11if条件语句条件语句 单分支单分支l应用示例:如果/boot分区的空间使用超过
9、80%,输出报警信息#!/bin/bashRATE=df-hT|grep/boot|awk print$6|cut-d%-f1 if$RATE -gt 80 then echo Warning,DISK is full!fi12if条件语句条件语句 双分支双分支l当“条件成立”、“条件不成立”时执行不同操作if 条件测试命令条件测试命令 then 命令序列命令序列1 else 命令序列命令序列2fiif 3306端口是否在监听状态端口是否在监听状态 then mysqld 服务已运行服务已运行 else 启动启动 mysqld 服务服务fiif 条件测试命令条件测试命令命令序列命令序列1条件为
10、真条件为真 then命令序列命令序列2条件为假条件为假 elsefi 结束判断结束判断13if条件语句条件语句 双分支双分支l应用示例:判断mysqld是否在运行,若已运行则输出提示信息,否则重新启动mysqld服务#!/bin/bashservice mysqld status&/dev/null if$?-eq 0 then echo mysqld service is running.else /etc/init.d/mysqld restartfi14if条件语句条件语句 多分支多分支l相当于if语句嵌套,针对多个条件执行不同操作if 条件测试命令条件测试命令1 ;then 命令序列命
11、令序列1elif 条件测试命令条件测试命令2 ;then 命令序列命令序列2elif .else 命令序列命令序列nfiif 条件测试命令条件测试命令1命令序列命令序列1条件为真条件为真 then命令序列命令序列n条件为假条件为假 elseelif 条件测试命令条件测试命令2命令序列命令序列2条件为真条件为真 thenfi 结束判断结束判断15小结小结l请思考:如何判断/media/cdrom目录是否存在?提示用户输入一个整数,如何判断该值是否小于100?结合环境变量PWD,如何判断当前所在的工作目录是否为/usr/src?逻辑测试操作符&与|的区别是什么?if语句结构有哪几种分支类型?语法格
12、式分别是什么?16for循环语句循环语句l根据变量的不同取值,重复执行一组命令操作for 变量名变量名 in 取值列表取值列表do 命令序列命令序列done for 收件人收件人 in 邮件地址列表邮件地址列表do 发送邮件发送邮件done for 变量变量=取值取值1取值取值1取值取值ndone 结束循环结束循环do 命令序列命令序列取值取值n 已使用已使用17for循环语句循环语句l应用示例1:依次输出3条文字信息,包括一天中的“Morning”、“Noon”、“Evening”字串rootlocalhost#vi showday.sh#!/bin/bashfor TM in Mornin
13、g Noon Eveningdo echo The$TM of the day.done rootlocalhost#sh showday.shThe Morning of the day.The Noon of the day.The Evening of the day 验证脚本执行结果验证脚本执行结果18for循环语句循环语句l应用示例2:对于使用“/bin/bash”作为登录Shell的系统用户,检查他们在“/opt”目录中拥有的子目录或文件数量,如果超过100个,则列出具体个数及对应的用户帐号#!/bin/bashDIR=/optLMT=100ValidUsers=grep/bin/
14、bash/etc/passwd|cut-d:-f 1for UserName in$ValidUsersdo Num=find$DIR-user$UserName|wc-l if$Num -gt$LMT ;then echo$UserName have$Num files.fidone 获得使用获得使用bash作为登录作为登录Shell的用户名列表的用户名列表19while循环语句循环语句l重复测试指定的条件,只要条件成立则反复执行对应的命令操作 while 命令或表达式命令或表达式 do 命令列表命令列表 done while 可用内存可用内存/dev/null i=expr$i+1done
15、 执行执行 let i+也可以也可以使变量使变量i的值递增的值递增121while循环语句循环语句l应用示例2:批量删除上例中添加的20个系统用户帐号#!/bin/bashi=1while$i -le 20 do userdel-r stu$i i=expr$i+1done 22case多重分支语句多重分支语句l根据变量的不同取值,分别执行不同的命令操作case 变量值变量值 in 模式模式1)命令序列命令序列1 ;模式模式2)命令序列命令序列2 ;*)默认执行的命令序列默认执行的命令序列esaccase 变量变量=模式模式1esac 结束分支结束分支命令序列命令序列1;有有变量变量=模式模式
16、2变量变量=其他值其他值(*)默认命令序列默认命令序列无无是是否否否否命令序列命令序列2;有有无无是是23case多重分支语句多重分支语句l应用示例1:编写脚本文件 mydb.sh,用于控制系统服务mysqld当执行./mydb.sh start 时,启动mysqld服务当执行./mydb.sh stop 时,关闭mysqld服务如果输入其他脚本参数,则显示帮助信息#!/bin/bash case$1 in start)echo Start MySQL service.;stop)echo Stop MySQL service.;*)echo Usage:$0 start|stop ;esac
17、24case多重分支语句多重分支语句l应用示例2:提示用户从键盘输入一个字符,判断该字符是否为字母、数字或者其它字符,并输出相应的提示信息#!/bin/bashread -p Press some key,then press Return:“KEYcase$KEY“in a-z|A-Z)echo Its a letter.;0-9)echo Its a digit.;*)echo Its function keys、Spacebar or other keys.esac25until循环语句循环语句luntil语句根据条件执行重复操作until 条件测试命令条件测试命令do 命令序列命令序列
18、doneuntil 条件测试命令条件测试命令条件为假条件为假条件为真条件为真done 结束循环结束循环do 命令序列命令序列26shift迁移语句迁移语句l用于迁移位置变量,将$1$9 依次向左传递例如,若当前脚本程序获得的位置变量如下:l$1=file1、$2=file2、$3=file3、$4=file4则执行一次shift命令后,各位置变量为:l$1=file2、$2=file3、$3=file4再次执行shift命令后,各位置变量为:l$1=file3、$2=file427shift迁移语句迁移语句l应用示例:通过命令行参数传递多个整数值,并计算总和rootlocalhost#vi s
19、howday.sh#!/bin/bashResult=0while$#-gt 0 do Result=expr$Result+$1 shiftdoneecho The sum is:$Resultrootlocalhost#./sumer.sh 12 34 56The sum is:102 验证脚本执行结果验证脚本执行结果28while 命令命令 do break done循环控制语句循环控制语句lbreak语句在for、while、until等循环语句中,用于跳出当前所在的循环体,执行循环体后的语句通常在循环体中与条通常在循环体中与条件语句一起使用件语句一起使用跳跳出出循循环环29while
20、 do continue done循环控制语句循环控制语句lcontinue在for、while、until等循环语句中,用于跳过循环体内余下的语句,重新判断条件以便执行下一次循环通常在循环体中与条通常在循环体中与条件语句一起使用件语句一起使用继继续续下下次次循循环环30Shell函数应用函数应用lShell函数概述在编写Shell脚本程序时,将一些需要重复使用的命令操作,定义为公共使用的语句块,即可称为函数合理使用Shell函数,可以使脚本内容更加简洁,增强程序的易读性,提高执行效率31Shell函数应用函数应用l定义新的函数l调用已定义的函数l向函数内传递参数function 函数名函数名
21、 命令序列命令序列 函数名函数名()命令序列命令序列或者或者函数名函数名函数名函数名 参数参数1 参数参数2 .32Shell函数应用函数应用l应用示例:在脚本中定义一个加法函数,用于计算2个整数的和调用该函数计算(12+34)、(56+789)的和#!/bin/bashadder()echo expr$1+$2adder 12 34adder 56 789rootlocalhost#sh adderfun.sh46845 验证脚本执行结果验证脚本执行结果33本章总结本章总结编写编写Shell管理管理脚本(二)脚本(二)使用使用if条件语条件语句句条件测试操作条件测试操作 case语句语句 i
22、f语句的结构语句的结构 until循环循环 if语句应用示例语句应用示例 使用使用for循环循环语句语句 其他控制语句其他控制语句 for语句的结构语句的结构 for语句应用示例语句应用示例 while语句的结构语句的结构 while语句应用示例语句应用示例 使用使用while循循环语句环语句 循环控制语句循环控制语句 shift 语句语句函数的定义和调用函数的定义和调用 Shell函数应函数应用用 函数的参数传递函数的参数传递 34实验案例实验案例1:使用:使用Shell脚本管理系统脚本管理系统l需求描述编写脚本程序用于监测系统服务httpd的运行状态l 当服务状态失常时在“/var/log
23、/htmon.log”文件中记入日志l 自动将状态失常的httpd服务重新启动l 若重启httpd服务失败,则尝试重新启动服务器主机l 周一至周五期间每隔15分钟执行一次监测任务编写脚本程序用于批量添加用户l 提供交互,能根据提示指定添加用户的数量(少于100)、用户名前缀,并能设置帐号的失效时间、初始密码l 用户名编号统一使用2位数,如使用“01”、“02”的形式编写脚本批量删除用户l 通过命令行参数指定要删除用户的名称前缀l 删除以该前缀开头的所有用户,但要防止误删除root用户35实验案例实验案例1:使用:使用Shell脚本管理系统脚本管理系统l实现思路编写htmon.sh脚本文件用于监
24、测httpd服务状态l 通过“service httpd status”命令的返回值判断服务状态l 使用重定向符号“”追加记录日志l 结合crond计划任务定期执行编写myuadd.sh脚本用于批量添加用户帐号l 使用read命令提示用户输入变量值进行交互l 使用while语句循环执行添加用户的命令操作l 使用if语句判断用户编号,小于10时自动在前缀后补“0”编写myudel.sh脚本用于批量删除用户帐号l 通过位置参数“$1”传递要删除用户的名称前缀l 结合“grep-v root”排除掉root用户l 使用for循环批量删除符合条件的用户36实验案例实验案例2:编写系统服务控制脚本:编写
25、系统服务控制脚本l需求描述为已安装的zebra程序编写 zebrad 服务控制脚本l 启动服务:/etc/init.d/zebrad startl 终止服务:/etc/init.d/zebrad startl 重启服务:/etc/init.d/zebrad restartl 查看服务状态:/etc/init.d/zebrad statusl 未正确指定“start”、“stop”、“restart”、“status”参数时,输出用法帮助信息后退出l 在启动、终止服务时应显示相关提示信息将zebrad添加为系统服务37实验案例实验案例2:编写系统服务控制脚本:编写系统服务控制脚本l实现思路参考已有的系统脚本建立 zebrad 脚本文件将启动、终止zebra程序等执行操作分别定义为函数l 通过“/usr/local/sbin/zebra-d”命令启动zebra服务l 结合“/var/run/zebra.pid”文件中的PID号终止zebra进程l 通过判断“zebra-d”进程信息确定zebra服务状态设置case分支语句l 读取执行脚本时提供的未知参数“$1”,并进行比较l 若为“start”、“stop”等字串,分别调用对应函数l 否则执行默认操作,显示用法帮助信息并退出执行“chkconfig-add zebrad”添加为系统服务