一.什么是运行流程控制
- 脚本默认的程序运行方式是自上而下运行
- 在我们的生产环境中,有的动作需要重复做,有的动作需要满足某些条件做
- 如何按照我们需要的逻辑运行动作,这就是流程控制
二.条件运行流程控制
条件运行流程控制是脚本在运行时,需要有几个分支,在符合那个条件运行那个分支
在脚本中我们通常用if语句来编写条件流程控制
1. if单分支结构
语法:
#!/bin/bash
if [条件]
then
动作1
动作2
... ...
fi
当系统/分区使用容量超过80%时给root用户发送警告
[root@timinglee ~]# vim demo_disk.sh
#!/bin/bash
Disk_Status=`df -h / |tr -s ' ' | grep dev | cut -d " " -f 5 | cut -d % -f 1`
if [ "$Disk_Status" -lt "80" ]
then
echo "Waring: / is full !!" | mail -s Disk_Waring root
fi
2. if双分支结构
语法:
#!/bin/bash
if [条件]
then
动作1
动作2
... ...
else
动作1
动作2
...
给定用户判断用户是否存在,如果存在显示用户存在,如果不存在建立用户
[root@timinglee ~]# vim demo_disk.sh
#!/bin/bash
id $1 &> /dev/null
if [ "$?" = "0" ]
then
echo $1 is exist
else
useradd $1
fi
3. if多分支结构
语法:
if 条件表达式1
then
命令序列1
elif 条件表达式2
then
命令序列2
elif 条件表达式3
then
命令序列3
else
命令序列n
fi
给定一个文件名称,判定文件是否存在,如果存在显示文件的类型,如果不存在显示文件不存在
[root@timinglee ~]# vim checkfile_demo.sh
#!/bin/bash
if [ -z "$1" ]
then
echo Please input a checkfilename following $0 !!
elif [ ! -e "$1" ]
then
echo $1 is not exist
elif [ -L "$1" ]
then
echo $1 is link file
elif [ -f "$1" ]
then
echo $1 is common file
elif [ -d "$1" ]
then
echo $1 is directory
fi
三.循环运行流程控制
循环运行流程是代码在运行时在某个位置需要用相同动作来处理多个对象
1.无判定循环
在脚本中我们通常用for语句来完成无判定循环
语法1:
#!/bin/bash
for NUM in l 2 3
do
echo $NUM
done
语法2:
#!/bin/bash
for NUM in {1..10}
do
echo $NUM
done
语法3:
#!/bin/bash
for number in `seq 1 2 10`
do
echo $number
done
语法4:
#!/bin/bash
for ((NUM=1;NUM<=10;NUM++))
do
echo $NUM
done
2.判断循环
a)while语句
使用while循环结构,当条件满足时反复执行指定动作,直到条件不满足时结束
语法:
while 条件
do
动作1
动作2
...
done
b)until语句
使用unitl循环结构,当条件不满足时反复执行指定动作,直到条件满足时结束
语法:
until 条件表达式
do
动作1
动作2
...
done
用大小写字母和数字生成一个5位的随机密码
#!/bin/bash
n=1
STRING='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
until [ "$n" -gt "6" ]
do
NUM=$[$RANDOM%${#STRING}]
PASSWD="${PASSWD}${STRING:NUM:1}"
((n++))
done
echo $PASSWD
四.选择运行流程控制
- 当脚本接收到操作者某个动作指令,脚本按照动作指令选择运行脚本中的某段代码,这就是选择流程控制
- 判断语句也可以达到选择流程控制的目的,但是其效率低下,因此我们在脚本中对于选择流程控制使用case来完成
语法:
case var in
选择指令1|。。。|。。。)
动作1
动作2
...
;;
选择指令2|。。。|。。。)
动作1
动作2
...
;
*)
动作1
动作2
esac
当在脚本后输入easylee时,输出linux,在脚本后输出linux时,输出easylee,如果既不是easylee也不 是linux时输出error
[root@timinglee ~]# vim demo_case.sh
#!/bin/bash
case $1 in
linux|LINUX)
echo easylee
;;
easylee|EASYLEE)
echo linux
;;
*)
echo error
esac
加减乘除计算器
#!/bin/bash
case $2 in
+)
echo $[$1+$3]
;;
-)
echo $[$1-$3]
;;
"*")
echo $[$1*$3]
;;
/)
echo $[$1/$3]
;;
*)
echo "error , Please use + - * / for number"
esac
五.自动应答
在书写脚本时通常会遇到交互命令的执行,如何自动完成跟命令的交互,这就是自动应答的作用
1.固定位置的交互应答
如果交互命令的问题固定,那么我们可以通过输入重定向来完成交互动作
#!/bin/bash
for USERNAME in user1 user2 user3
do
passwd $USRNAME <<EOF
123
123
EOF
done
2.非固定位置的交互应答
如果交互命令的问题位置不固定,那么我们需要用到expect来完成自动应答
a)创建交互命令
[root@timinglee ~]# vim ask.sh
#!/bin/bash
read -p "What is your name: " NAME
#read -p "How old are you: " AGE
read -p "Which subject you study: " SUB
read -p "Are you happy ? " FEEL
echo $NAME is $AGE\'s old study $SUB feel $FEEL
注:在交互脚本中我们可以使用#注释问题来还原问题有的时候有有的时候没有这个场景
b)应答语句基本写法
[root@timinglee ~]# vim demo_answer.exp
#!/usr/bin/expect
set timeout 5
spawn sh ask.sh
expect {
"name" { send "lee\r";exp_continue }
"old" { send "18\r";exp_continue }
"subject" { send "linux\r";exp_continue }
"happy" { send "happy\r"}
}
expect eof
应答语句中的变量
#!/usr/bin/expect
spawn sh ask.sh
set timeout 5
set NAME [ lindex $argv 0]
set AGE [ lindex $argv 1]
set SUB [ lindex $argv 2]
set FEEL [ lindex $argv 3]
expect {
"name" { send "$NAME\r";exp_continue }
"old" { send "$AGE\r";exp_continue }
"subject" { send "$SUB\r";exp_continue }
"happy" { send "$FEEL\r"}
}
expect eof
注:set NAME [ lindex $argv 0] 表示expect脚本后跟的第一串字符后面的1-3以此类推
整合shell和expect到脚本中
#!/bin/bash
/usr/bin/expect <<EOF
spawn sh ask.sh
expect {
"name" { send "$1\r";exp_continue }
"old" { send "$2\r";exp_continue }
"subject" { send "$3\r";exp_continue }
"happy" { send "$4\r"}
}
expect eof
EOF
六.流程中断控制器
在程序运行时因为需求我们需要在某个位置中断,那么我们就要使用流程中断控制器
常用的流程中断控制器有一下几个:
func()
{
for i in {1..10}
do
[ "$i" -eq "4" ] && {
echo lucky
# return
# continue
# break
exit
}
echo $i
done
echo 1 func run done
}
func
echo 2 $0 run done