一 while循环
语法 while 条件; do … ; done
案例1:每隔30s检查下系统负载,当系统负载大于10,就发送邮件
分析:如果不用while循环,我们只能使用任务计划cron,但这样的最小时间是1分钟,达不到隔30s检查一次的要求
#!/bin/bash
while : //这里的:冒号可以用true代替,写的是死循环
do
load=`w|head -1|awk -F 'load average: ' '{print $2}'|cut -d. -f1` //给负载load赋值
if [ $load -gt 10 ]
then
top|mail -s "load is high: $load" asldkfls@11.com
fi
sleep 30
done
像这种死循环的脚本,为了不让他意外的终止,我们可以打开一个screen来运行他
我们来解析下上面案例中的命令w|head -1|awk -F 'load average: ' '{print $2}'|cut -d. -f1
[root@lijie-01 ~]# w|head -1|awk -F 'load average: ' '{print $2}'|cut -d. -f1
0
[root@lijie-01 ~]# w //查看负载
06:56:07 up 13:59, 2 users, load average: 0.05, 0.03, 0.05
USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT
root pts/0 192.168.75.1 04:52 10:39 0.66s 0.40s vim while.sh
root pts/2 192.168.75.1 05:57 7.00s 0.10s 0.00s w
[root@lijie-01 ~]# uptime //截取负载信息的第一行
06:56:12 up 13:59, 2 users, load average: 0.04, 0.03, 0.05
[root@lijie-01 ~]# w|head -1 //效果等同于上面一条命令
07:04:21 up 14:07, 2 users, load average: 0.00, 0.01, 0.05
[root@lijie-01 ~]# uptime|awk -F 'load average:' '{print $2}' //以load average:作为分隔符截取负载信息第一行的第二段
0.02, 0.02, 0.05
[root@lijie-01 ~]# uptime|awk -F 'load average:' '{print $2}'|cut -d. -f1 //再以.作为分隔符截取第一段
0
[root@lijie-01 ~]# uptime|awk -F 'load average: ' '{print $2}'|cut -d. -f1 //load average: 后面加上空格以去掉上面一条命令运行结果前面的0
0
[root@lijie-01 ~]# uptime|awk -F 'load average:' '{print $2}'|cut -d. -f1|sed 's/ //' //也可以再用 sed 's/ //'过滤一次以去掉上面一条命令运行结果前面的0
0
我们还可以写成
#!/bin/bash
while true
do
load='w|head -1|awk -F `load average: ` `{print $2}` |cut -d. -f1'
if [ $load -gt 10 ]
then
/usr/lib/zabbix/alertscripts/mail.py xxx@qq.com "load high" " $load"
fi
sleep 30
done
运行结果出错
[root@lijie-01 shell]# sh while.sh
while.sh: 第 5 行:[: 参数太多
我们来排查错误,发现load赋值语句的引号有问题,修改后提示以下错误
[root@lijie-01 shell]# sh while.sh
while.sh:行4: average:: 未找到命令
while.sh: 第 5 行:[: -gt: 期待一元表达式
^[while.sh:行4: average:: 未找到命令
while.sh: 第 5 行:[: -gt: 期待一元表达式
while.sh:行4: average:: 未找到命令
while.sh: 第 5 行:[: -gt: 期待一元表达式
结果发现load赋值语句是系统命令,最外层应该使用反引号,修改后再运行,由于我们写的是死循环,因此脚本处于一直运行的状态,如下:
[root@lijie-01 shell]# sh while.sh
为了能更明显的观察到现象,我们将脚本修改为当负载小于10发送邮件
[root@lijie-01 shell]# cat !$
cat while.sh
#!/bin/bash
while :
do
load=`w|head -1|awk -F 'load average: ' '{print $2}'|cut -d. -f1`
if [ $load -lt 10 ]
then
/usr/lib/zabbix/alertscripts/mail.py 476189605@qq.com "load high" " $load"
fi
exit
done
过了30s后,就正常收到邮件了
while循环案例2:做一个让用户不停输入我们想要东西的脚本
[root@lijie-01 shell]# cat !$
cat while2.sh
#!/bin/bash
while :
do
read -p "Please input a number: " n
if [ -z "$n" ]
then
echo "你还没有输入的,请输入!"
continue
fi
n1=`echo $n|sed 's/[0-9]//g'`
if [ ! -z "$n1" ]
then
echo "你需要输入一个纯数字!"
continue
fi
break
done
echo $n
下面来执行
[root@lijie-01 shell]# sh -x while2.sh
+ :
+ read -p 'Please input a number: ' n
Please input a number:
+ '[' -z '' ']'
+ echo '你还没有输入的,请输入!'
你还没有输入的,请输入!
+ continue
+ :
+ read -p 'Please input a number: ' n
Please input a number: 12324dfff
+ '[' -z 12324dfff ']'
++ sed 's/[0-9]//g'
++ echo 12324dfff
+ n1=dfff
+ '[' '!' -z dfff ']'
+ echo '你需要输入一个纯数字'
你需要输入一个纯数字
+ continue
+ :
+ read -p 'Please input a number: ' n
Please input a number: 3425
+ '[' -z 3425 ']'
++ sed 's/[0-9]//g'
++ echo 3425
+ n1=
+ '[' '!' -z '' ']'
+ break
+ echo 3425
3425
[root@lijie-01 shell]#
二 break跳出循环
break用于循环语句中
#!/bin/bash
for i in `seq 1 5`
do
echo $i
if [ $i == 3 ] //如果是数字间的比较,可以使用-eq;如果比较的对象包含数字外的其他字符,则必须要使用==来比较
then
break
fi
echo $i
done
echo abc
执行过程如下:
[root@lijie-01 shell]# sh -x break.sh
++ seq 1 5
+ for i in '`seq 1 5`'
+ echo 1
1
+ '[' 1 == 3 ']'
+ for i in '`seq 1 5`'
+ echo 2
2
+ '[' 2 == 3 ']'
+ for i in '`seq 1 5`'
+ echo 3
3
+ '[' 3 == 3 ']'
+ break
+ echo abc
abc
[root@lijie-01 shell]#
三 continue结束本次循环
忽略continue之下的代码,直接进行下一次循环
#!/bin/bash
for i in `seq 1 5`
do
echo $i
if [ $i == 3 ]
then
continue //当i=3时,跳出本次循环
fi
echo $i
done
echo abc
执行过程如下:
[root@lijie-01 shell]# sh continue.sh
1
1
2
2
3
4
4
5
5
abc
[root@lijie-01 shell]#
四 exit退出整个脚本
[root@lijie-01 shell]# cat !$
cat exit.sh
#!/bin/bash
for i in `seq 1 5`
do
echo $i
if [ $i == 3 ]
then
exit 2
fi
echo $i
done
echo abc
[root@lijie-01 shell]# sh exit.sh
1
1
2
2
3
[root@lijie-01 shell]# echo $?
2
[root@lijie-01 shell]#