shell中的执行流控制
1 for语句
shell中的执行流是从上往下依次执行,使用不同的语句可以优化代码,使得代码结构更加清晰同时减少代码运行时间。
1.1 作用及语句结构
- 作用:为循环执行动作
- for语句结构:
for ##定义变量
do ##使用变量,执行动作
done ##结束标志
1.2 for语句的基本格式
1)格式1
#!/bin/bash
for WESTOS in `seq 1 10` ##表示从1到10循环输出
do
echo $WESTOS
done
#!/bin/bash
for WESTOS in `seq 1 2 10` ##自定义步长,表示从1开始步长为2直到10
do
echo $WESTOS
done
默认步长为1:
自定义步长为2:
2)格式2
for WESTOS in westos linux lee
do
echo $WESTOS
done
3)格式3
for WESTOS in {10..1}
do
echo $WESTOS
done
注意:for语句的格式1不能逆序输出
4)格式4
for ((USER=1;USER<5;USER++))
do
echo $USER
done
2 条件语句
2.1 while…do
- 作用:条件为真执行动作
- 语句结构:
while true ##条件为真
do ##条件成立所作循环动作
done
2.2 until…do
- 作用:条件为假执行动作
- 语法结构:
until false ##条件为假
do ##条件不成立所做动作
done
注意:同while一样,unit后面的false可以替换成某个条件
2.3 if语句
- 作用:多次判定条件执行动作
- 代码结构:
if ##首次判定
then ##条件成立执行动作
elif ##首次判定不成立时再次判定
then ##条件成立执行动作
……
else ##所有条件不成立执行动作
fi ##结束
2.4 case语句
- case的功能性较强,它是一个点名机制。 if主要是字符对比,需要从上到下依次执行,效率低(写脚本时,选择最优的方法即可)
- 语法结构:
case $1 in
word|WORD) ##case后面直接可以这样写,不需要再去转换大小写
action1
;;
word1|WORD1)
action2
;;
……
*)
action3 ##前面都不满足时执行
esac
3 expect自动应答
expect可以实现自动的针对系统中提出的一些问题做出应答,节省手动回答问题的时间,举个例子,如下所示:
问题脚本:
#!/bin/bash
read -p "what's your name:" NAME
read -p "How old are you: " AGE
read -p "Which objective: " OBJ
read -p "Are you ok? " OK
echo $NAME is $AGE\'s old study $OBJ feel $OK
应答脚本:
#!/usr/bin/expect
set timeout 1 ##回答问题的等待时间为1s,答不出来就跳过
set NAME [ lindex $argv 0 ] ##执行脚本时后面所跟的第一串字符,下面的依次类推
set AGE [ lindex $argv 1 ]
set OBJ [ lindex $argv 2 ]
set FEEL [ lindex $argv 3 ]
spawn /mnt/ask.sh ##回答哪个脚本里的问题
expect {
"name" { send "$NAME\r";exp_continue }##遇到问题中有name时,回答变是量NAME的值,以下同理 ;exp_continue表示回答继续
"old" { send "$AGE\r";exp_continue }
"objective" { send "$OBJ\r";exp_continue }
"ok" { send "$FEEL\r" }
}
expect eof ##退出expect交互环境
interact ##不退出交互环境
1)编写一个问题脚本:
此时运行该脚本时,回答问题需要手动输入:
2)为了解决不能自动回答,且可能发生回答的答案与问题不符的情况,可以编写expect文件。首先需要安装expect软件:
3)编写应答脚本,应答脚本必须以 .exp 结尾,其解释器如下图所示:
这里在第一次调用应答脚本时,由于问题脚本的权限限制,所以无法调用该脚本,此时输入“chmod a+x ask.sh”给该文件加上可执行权限即可;注意exp脚本的调用使用expect命令:
4)上面的回答方式是固定的,一旦问题发生改变,那么应答脚本的回复也会出现错乱。为了解决该问题可以使用传参的方式来保证问题和答案的匹配性:
此时运行该脚本时,需要在后面将参数,也就是问题的答案传进入:
5)以上的方式是问题脚本和回答脚本分别写在两种类型的文件中,如果问题和答案脚本有很多,就容易混乱。所以也可以使用shell脚本写答案:
执行shell脚本时传参进入:
4 break,continue,exit
参数 | 含义 |
---|---|
break | 终止当前所在语句所有动作进行语句外的其他动作 |
continue | 终止此次循环提前进入下一次循环 |
exit | 脚本退出 |
1)程序依次执行到exit时,会直接退出脚本,所以不会输出end,此时默认的退出值是0:
如下表示退出时,设定退出值为33,此时输入echo $? 表示查看退出值,可以看到退出值为33。当再次查看退出值时,看到退出值恢复为默认的0:
如下输入系统无法识别的命令后,查看退出值,退出值为127:
注意:
退出值不同数字的含义:0表示成功;2表示权限拒绝;1~125表示运行失败或脚本命令,系统命令错误或参数传递错误;126表示找到该命令了,但是无法执行;127表示未找到在运行的命令;128表示命令被系统强制结束
2)break会跳出当前循环,跳出后输出end,然后结束:
3)continue会跳出本次循环,然后继续下一次循环,所以在4的时候跳出本次循环,继续进行下次循环:
5 脚本练习
1)编写名为check_host.sh的脚本,用此脚本检测10台与您当前主机直连主机是否网络通畅:
2)使用for语句和if语句写一个10秒倒计时:
注意:bye那条语句起到了覆盖前一条语句结果的作用,所以该语句必须和上一条语句长度相同或更长;echo -n表示不换行;\r表示回车:
当最后倒计时结束后,bye会覆盖前面的语句,最终被显示出来:
3)使用for和if语句写一个1分10秒倒计时:
4)编写一个脚本要求如下,若http服务不存在,则显示不存在;若http服务存在,输入 sh ctrl_service.sh start httpd 后服务:就开启服务;输入 sh ctrl_service.sh stop httpd就关闭:
5)编写一个名为host_list.sh的脚本,检测10-20主机的网络是否开启: