shell执行流控制语句实例详解
Posted 是大姚呀
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了shell执行流控制语句实例详解相关的知识,希望对你有一定的参考价值。
shell执行流控制语句
文章目录
1、for循环语句
for语句的作⽤为循环执⾏指定动作,其语句结构如下:
for 定义变量
do 使⽤变量,执⾏动作
done 结束标志
for语句的基本格式有以下四种:
1)in后使用罗列方法定义变量值
示例:
for WESTOS in westos linux lee
do echo $WESTOS
done
2)in后如果变量值连续,可以使用{起始值…结束值}定义变量值
示例:
for WESTOS in {10…1}
do echo $WESTOS
done
3)in后使用seq连续选择命令定义变量值
即(seq 起始值 结束值),这一命令可以设置步长(seq 起始值 步长 结束值)
示例:
for WESTOS in $(seq 1 2 10)
do echo $WESTOS
done
4)使用表达式方式定义变量值
即(单次表达式;条件表达式;末尾循环体)。for循环执行时,会先判断条件表达式是否成立,如果条件成立则执行中间循环体语句,执行完中间循环体后接着执行末尾循环体 ,在执行完末尾循环体后对条件表达式再次进行判断,若条件还成立,则继续重复中间循环体,当条件不成立时则跳出for循环。
示例:
for ((WESTOS=0;WESTOS<10;WESTOS++))
do echo $WESTOS
done
实验步骤:
1)使用for语句在in后使用罗列方法定义变量WESTOS的值为131—135,在循环中执行ping 172.25.254.$WESTOS
检测这些主机⽹络是否通畅,这里我们进行实验的虚拟主机westosa的IP地址为172.25.254.133,因此只有172.25.254.133主机⽹络通畅
2)in后变量WESTOS的值为131—135连续,可以使用{起始值…结束值}方式定义变量值,利用for语句循环检测172.25.254.131—172.25.254.135主机⽹络是否通畅
3)in后使用seq连续选择命令(seq 起始值 结束值)
定义变量WESTOS的值为131—135,利用for语句循环检测172.25.254.131—172.25.254.135主机⽹络是否通畅;另外,我们可以在seq中设置步长(seq 起始值 步长 结束值)
,定义变量WESTOS的值为131、133、135,利用for语句循环检测172.25.254.131、172.25.254.133、172.25.254.135主机⽹络是否通畅
4)使用表达式方式定义变量WESTOS初值为131,WESTOS变量值范围不能超出135,在每次循环结束后对变量值进行自增,利用for语句循环检测172.25.254.131—172.25.254.135主机⽹络是否通畅
脚本练习:
(1)编写脚本check_host.sh批量检测主机网络是否能够ping通
思路: in后使用seq连续选择命令定义变量HOST_ID的值为131—140,利用for语句循环检测172.25.254.131—172.25.254.135主机⽹络是否通畅
改进: 这里为了实现脚本和用户之间的交互,我们可以将执行脚本时脚本后输入的所有字符(脚本中用$@表示)赋值给变量HOST_ID,循环检测用户指定范围的主机⽹络是否通畅
(2)编写脚本creat_user.sh建立指定用户列表文件userlist中的所有用户,每建立一个用户就会显示这个用户创建成功
思路: 脚本主要分为三部分,首先编写一个输出函数,根据命令执行成功与否决定输出提示信息的颜色(31表示红色,32表示绿色);接着对脚本执行条件进行设定,只有root用户可以执行该脚本,脚本后必须指定用户列表文件,指定的用户列表文件必须是存在的;最后将查看用户列表文件显示的所有字符串作为用户名赋值给变量USER,使用for语句循环执行创建用户命令,每成功建立一个用户就会显示该用户创建成功
脚本运行结果如下:
(3)编写脚本creat_user.sh建立指定用户列表文件中的所有用户并将每个用户的密码设置为密码列表文件中其所对应的密码
思路: 这里需要将文件行数对应的序号作为循环语句的循环变量(可以对应用户列表、密码列表两个文件),先统计用户列表文件的行数即有几个用户,确定循环变量赋值时的结束值,接着使用sed命令显示循环变量对应的用户列表文件中行并将显示的结果赋值给用户名变量,使用sed命令显示循环变量对应的密码文件中行并将显示的结果赋值给密码变量,执行创建用户的操作,如果创建成功即修改该用户的密码为密码变量对应的值,如果创建不成功则显示用户已存在
注: 使用sed -n $= filename
统计指定文件行数,-n表示不显示处理文件内容,给指定文件每一行添加行号并显示最后一行的行号即统计文件行数,以确定脚本编写时的循环次数
脚本运行结果如下:
2、while条件语句
while语句作⽤是在条件为真执⾏动作,这一条件语句的结构为:
while ture
do 执⾏动作
done 结束标志
实验步骤:
编写脚本程序,使用while语句在条件为真时循环输出提示语,提示用户输入字符串并将用户输入的内容赋值给变量WORD,输出显示变量WORD的值
脚本运行结果如下:
3、until条件语句
until语句作⽤是在条件为假执⾏动作,这一条件语句的结构为:
until false
do 执⾏动作
done 结束标志
实验步骤:
编写脚本程序,使用until语句在条件为假—执行脚本的用户为root时循环输出提示语,提示用户输入字符串并将用户输入的内容赋值给变量WORD,输出显示变量WORD的值
脚本运行结果如下:在执行脚本的用户为root时,脚本正常运行;在执行脚本的用户不为root时,脚本不执行
4、if 条件判断语句
if 语句作⽤是多次判定条件执⾏动作, 这一语句可以将多个条件判断结合起来,其代码结构如下:
if
then
执⾏动作
elif
then
执⾏动作
else
执⾏动作
fi 结束标志
实验步骤:
编写脚本程序,使用 if 语句对用户执行脚本时输入的数字进行判断,如果输入的数字为5则输出显示five,如果输入的数字为4则输出显示four,否则输出显示error
脚本运行结果如下:
脚本练习:
(1)编写数字竞猜脚本:输出提示语提示用户输入数字,对shell中的$RANDOM随机数变量值进行%模10取余操作得到0-9范围内的一个随机数,将用户输入的数字的值与生成的随机数的值作对比,如果相等则提示猜对了,如果不等则再次提示用户输入数字直到猜对
脚本运行结果如下:
(2)编写数字竞猜提示脚本:输出提示语提示用户输入数字,将用户输入的数字的值与脚本中设定的随机数的值作对比,如果相等则提示猜对了,如果不等则判断用户输入的数字的值大于/小于脚本中设定的随机数的值,提示用户输入数字大了/小了,接着再次提示用户输入数字直到猜对
脚本运行结果如下:
5、case应答语句
if 语句是判断机制,从第一个条件开始判断直到满足某一个条件为止,执行满足的判断条件所对应的命令语句,但这种每次从头开始判断的机制效率较低;case 语句是点名机制,会横向对比它所掌握的所有条件元素,符合哪个元素就执行哪个元素对应的语句,语句执行效率较高。case应答语句的结构为:
case $1 in
word1|WORD1)
action1
;;
word2|WORD2)
action2
;;
*)
action3
esac 结束标志
实验步骤:
1)编写脚本程序,使用 if 语句对用户执行脚本时输入的字符串进行判断,如果输入的字符串为westos则输出显示linux,如果输入的字符串为linux则输出显示westos,否则输出显示error
脚本运行结果如下:可以看到if 语句是从第一个条件开始判断直到满足某一个条件为止,当用户输入linux或其他字符时都执行了两次判断
2)编写脚本程序,使用 case 语句对用户执行脚本时输入的字符串进行判断,如果输入的字符串与westos匹配则输出显示linux,如果输入的字符串与linux匹配则输出显示westos,否则输出显示error
脚本运行结果如下:可以看到case 语句符合哪个元素就直接执行哪个元素对应的语句,当用户输入linux或其他字符时都只执行了一次判断
脚本练习:
(1)编写对用户进行管理的脚本ctrl_user.sh
思路: 执行脚本时输出提示语,提示用户输入需要执行的动作并将用户输入的内容赋值给变量ACTION,根据变量ACTION的值使用case语句匹配执行不同的用户管理操作。1)变量ACTION的值为create时执行创建用户操作,输出提示语提示用户输入用户名,当用户输入用户名为exit时退出当前动作并再次提示用户输入需要执行的动作,当用户输入用户名为其他字符时执行创建用户操作,如果创建成功则输出提示语提示用户输入密码,为创建好的用户设置密码并输出显示用户创建成功,完成后再次提示用户输入需要执行的动作;如果创建失败则输出显示该用户已存在,并再次提示用户输入用户名。2)变量ACTION的值为delete时执行删除用户操作,输出提示语提示用户输入用户名,当用户输入用户名为exit时退出当前动作并再次提示用户输入需要执行的动作,当用户输入用户名为其他字符时执行删除用户操作,如果删除成功则输出显示用户删除成功,完成后再次提示用户输入需要执行的动作;如果删除失败则输出显示该用户不存在,并再次提示用户输入用户名。3)变量ACTION的值为exit时结束脚本运行。
注: 当需要反复执行某一功能模块时不一定要编写函数,可以使用while等循环语句结合break等终止条件进行实现
脚本运行结果如下:
6、 continue / break / exit 终止条件
终止条件 | 作用 |
---|---|
contiue | 终⽌此次循环提前进⼊下个循环 |
break | 终⽌当前所在语句块的所有动作进⾏语句外的其他动作 |
exit | 退出脚本 |
实验步骤:
1)编写脚本,定义变量NUM的值为1—10,使用for语句循环输出显示变量NUM的值,并在变量NUM的值为6时输出lucky number !!
脚本运行结果如下:可以看到不仅输出了1—10这10个数字,还在变量NUM的值为6时输出了lucky number !!
2)修改脚本,在设定变量NUM值为6时输出lucky number !!的语句后加上终止条件continue
脚本运行结果如下:可以看到在变量NUM值为6时输出lucky number !!后,没有输出数字6,这是因为终止条件continue 终⽌了此次for循环提前进⼊下个循环
3)修改脚本,设定终止条件为break,并在for循环外添加输出一行分隔符的语句
脚本运行结果如下:可以看到在变量NUM值为6时输出lucky number !!后,不再输出剩余数字,直接输出了一行分隔符,这是因为终止条件break终⽌了当前所在语句块的所有动作,直接进⾏语句外的其他动作
4)修改脚本,设定终止条件为exit
脚本运行结果如下:可以看到在变量NUM值为6时输出lucky number !!后,不再输出剩余数字,也没有输出分隔符,这是因为终止条件exit直接退出了脚本运行
7、expect交互应答语句
当我们执行ssh远程连接命令时,有时让输入用户密码,有时需要输入是否——yes/no继续建立连接,如果我们想要编写一个可以自动执行远程连接操作的脚本,就需要根据shell中具体的交互信息作出不同的回答,类似这种情况在编写脚本时就需要使用expect语句。
实验步骤:
1)编写问题脚本,运行脚本时逐个输出提示语提示用户输入姓名、年龄和学科,读取用户输入的字符串并将其赋值给相应的变量,输出显示变量值的组合语句
脚本运行结果如下:这里有两种回答方式,一是按照输出提示语逐个输入回答问题;二是将所有回答使用EOF按顺序输入给脚本
2)为了保证脚本的执行效率,我们需要使用expect语句来根据shell中具体的交互信息自动作出不同的回答,系统默认没有安装expect,需要先进行安装
3)安装完成后,当我们编写问题脚本(.sh结尾),脚本中需要用户多次输入内容回答问题时,可以编写相应的应答expect脚本(以.exp结尾)自动检测其监控执行的脚本(.sh)所提示的问题,根据问题的关键字匹配对应的回答给问题脚本。except和shell一样有自己运行的环境(#!/usr/bin/expect),应答expect脚本主要有以下四种编写方式:
方法一: 在 expect 环境中使用多个单独的内部命令expect,判断交互中输出的信息里是否包含某些关键字,如果有则立即根据关键字匹配对应的回答并将回答send发送给问题脚本
注意:
a)每个回答后的 \\r 必须写,否则会卡住出错;
b)spwan监控执行脚本,传递交互指令;
c)脚本结束标志可以为xcept eof、interact,except eof表示结束当前except运行环境,interact表示保留当前except运行环境并退出;
使用expect xxx.exp
命令运行except脚本,运行结果如下:
注意: 要给expect脚本(以.exp结尾)及其监控执行的脚本(.sh结尾)加上可执行权限
方法二: 我们可以在一个expect模块中写入多个关键字,这样当expect脚本中回答数量多于问题脚本(.sh结尾)所提示的问题时,多出的回答不会导致匹配出错,这里exp_continue参数的功能是使同一expect模块中的匹配语句可以继续执行(模块内最后一个回答不用写exp_continue参数,否则会卡住出错)
方法三: 我们可以使用变量读取执行except脚本时脚本后用户输入的字符串,将其作为问题关键字对应匹配的回答,实现了动态应答功能,这里set timeout 数字
表示应答出现问题出错时最多等待几秒就结束运行,$argv 0
表示except脚本后跟的第一个字符,以此类推
使用expect xxx.exp
命令运行except脚本并在脚本后输入相应字符串,运行结果如下:
方法四: 我们也可以在shell环境下,将expect的相关命令使用EOF输入到except运行环境中运行,注意此时expect模块中的内容要顶格写,此时可以使用sh xxx.exp的方式运行expect脚本
使用sh xxx.exp
命令运行except脚本并在脚本后输入相应字符串,运行结果如下:
脚本练习:
(1)编写脚本host_list.sh检测172.25.254.131-172.25.254.135网络是否开启,如果网络正常则生成解析列表host_list,解析列表格式为:ip 主机名称
思路: 使用for循环依次ping172.25.254.131-172.25.254.135网络,如果可以ping通则将网络ip和通过远程连接执行hostname命令得到的主机名保存在解析列表文件host_list中,这里要注意,当我们需要进行远程连接时,有时系统会提示请回答连接主机的密码,有时系统会提示请回答是否进行连接,所以我们需要编写一个expect自动应答函数,监控执行远程连接命令,根据提示的问题自动匹配回答
脚本运行结果如下:运行脚本后生成了解析列表host_list,这里我们进行实验的虚拟主机westosa的IP地址为172.25.254.133,因此只有172.25.254.133主机⽹络通畅,westosa的主机名称为westosa.westos.org
以上是关于shell执行流控制语句实例详解的主要内容,如果未能解决你的问题,请参考以下文章