while循环和until循环
本篇包含的主要内容:
- while循环和until循环的写法及进入循环体的条件
- 将脚本放入后台运行的方法
- whlie按行读取文件
Shell脚本语言的循环语句常见的有while、until、for及select循环语句。
while循环语句
基础语法:
while <条件表达式>
do
指令
done
类似Java中while的用法,当条件表达式为true时,会执行do以下的指令;否则不进入循环体执行指令
until循环语句
基础语法:
until <条件表达式>
do
指令
done
until循环语句的用法与while循环语句的用法类似,区别是until会在条件表达式不成立时,进入循环执行指令;条件表达式成立时,终止循环。
实践
1.每隔两秒输出系统负载
[root@localhost shell]# cat 10_1_1.sh
#!/bin/bash
#***********************************************
#Author: luotianhao
#Mail: tianhao.luo@hand-china.com
#Version: 1.0
#Date: 2021-03-14
#FileName: 10_1_1.sh
#Description: This is a test script.
#***********************************************
while true
do
uptime
sleep 2
done
[root@localhost shell]# sh 10_1_1.sh
17:16:29 up 4 days, 6:13, 2 users, load average: 0.04, 0.06, 0.05
17:16:31 up 4 days, 6:13, 2 users, load average: 0.04, 0.06, 0.05
17:16:33 up 4 days, 6:13, 2 users, load average: 0.04, 0.06, 0.05
17:16:36 up 4 days, 6:13, 2 users, load average: 0.03, 0.06, 0.05
17:16:38 up 4 days, 6:13, 2 users, load average: 0.03, 0.06, 0.05
将负载追加到log里面,使用微秒单位。通过在脚本的结尾使用&符号来在后台运行脚本
[root@localhost shell]# cat 10_1_2.sh
#!/bin/bash
#***********************************************
#Author: luotianhao
#Mail: tianhao.luo@hand-china.com
#Version: 1.0
#Date: 2021-03-14
#FileName: 10_1_2.sh
#Description: This is a test script.
#***********************************************
#==>这里的条件和之前的true有区别,注意[]两端有空格
while [ 1 ]
do
#==>将负载输出到日志文件里面
uptime >> /u01/learn/shell/uptime.log
#===>单位为微秒
usleep 2000000
done
[root@localhost shell]# sh 10_1_2.sh &
[1] 42470
[root@localhost shell]#
在实际工作中,一般会通过客户端SSH连接服务器,因此可能就会有在脚本或命令执行期间不能中断的需求,若中断,则会前功尽弃,更要命的是会破坏系统数据。下面是防止脚本执行中断的几个可行方法:
1)使用sh /server/scripts/while_01.sh &命令,即使用&在后台运行脚本。
2)使用nohup /server/scripts/uptime.sh &命令,即使用nohup加&在后台运行脚本。
3)利用screen保持会话,然后再执行命令或脚本,即使用screen保持当前会话状态。
让Shell脚本在后台运行的知识
用法:
sh while1.sh &
:把脚本while1.sh放到后台执行(常用的方法)ctrl+c
:停止执行当前脚本或任务ctrl+z
:暂停执行当前脚本或任务bg
:把当前脚本或任务放到后台执行fg
:把当前脚本或任务放到前台执行,如果有多个任务,可以使用fg加任务编号调出对应的脚本任务,如fg 2,是指调出第二个脚本任务,fg可以理解为frontgroundjobs
:查看当前执行的脚本或任务kill
:关闭执行的脚本任务,即以“kill %任务编号”的形式关闭脚本,这个任务编号,可以通过jobs来获得
实践上面的命令:
[root@localhost shell]# sh 10_1_2.sh &
[1] 51671
[root@localhost shell]# fg
sh 10_1_2.sh
^Z
[1]+ 已停止 sh 10_1_2.sh
[root@localhost shell]# bg
[1]+ sh 10_1_2.sh &
[root@localhost shell]# jobs
[1]+ 运行中 sh 10_1_2.sh &
[root@localhost shell]# fg 1
sh 10_1_2.sh
^C
[root@localhost shell]# jobs
[root@localhost shell]#
使用kill关闭任务
[root@localhost shell]# sh 10_1_2.sh &
[1] 53378
[root@localhost shell]# sh 10_1_2.sh &
[2] 53412
[root@localhost shell]# jobs
[1]- 运行中 sh 10_1_2.sh &
[2]+ 运行中 sh 10_1_2.sh &
[root@localhost shell]# kill %2
[root@localhost shell]# jobs
[1]- 运行中 sh 10_1_2.sh &
[2]+ 已终止 sh 10_1_2.sh
[root@localhost shell]#
有关进程管理的linux命令如下:
- kill、killall、pkill:杀掉进程
- ps:查看进程
- pstree:显示进程树
- top:显示进程
- renice:改变优先权
- nohup:用户退出系统后继续工作
- pgrep:查找匹配条件的进程
- strace:跟踪一个进程的系统调用情况
- ltrace:跟踪进程调用库函数的情况
例子:计算从1加到100之和
[root@localhost shell]# cat 10_3_1.sh
#!/bin/bash
#***********************************************
#Author: luotianhao
#Mail: tianhao.luo@hand-china.com
#Version: 1.0
#Date: 2021-03-14
#FileName: 10_3_1.sh
#Description: This is a test script.
#***********************************************
i=1
sum=0
while((i<=100))
do
((sum=sum+i))
((i++))
done
[ "$sum" -ne 0 ] && printf "totalsum is:$sum\n"
[root@localhost shell]# sh 10_3_1.sh
totalsum is:5050
记录一个小bug,判断是否是整数的时候:判断失效了。
[root@localhost shell]# sh 10_4_1.sh
pls input your number:a
2
pls input integer number
[root@localhost shell]# sh 10_4_1.sh
pls input your number:1
2
pls input integer number
原shell文件如下,能发现什么问题吗?
expr $num +1 &>/dev/null
[ 0 -eq $? ] || {
echo "pls input integer number"
exit 1;
}
下面是正确的shell文件,能发现我们写expr表达式的时候,把+1
写在了一起,正确的是需要有一个空格的
[root@localhost shell]# cat 10_4_1.sh
#!/bin/bash
#***********************************************
#Author: luotianhao
#Mail: tianhao.luo@hand-china.com
#Version: 1.0
#Date: 2021-03-14
#FileName: 10_4_1.sh
#Description: This is a test script.
#***********************************************
#<===记录输入的次数
total=0
#<===生成小于等于60的随机数
s=$((RANDOM%61))
#<===指定中文字符集放置乱码
export LANG="zh_CN.UTF-8"
read -p "pls input your number:" num
expr $num + 1 &>/dev/null
[ 0 -eq $? ] || {
echo "pls input integer number"
exit 1;
}
while [ $num -ne $s ]
do
[ $num -gt $s ] && {
read -p "your input is bigger,pls input again:" num
} || {
read -p "your input is less,pls input again:" num
}
((total++))
done
echo "your all input price is $total"
[root@localhost shell]# sh 10_4_1.sh
pls input your number:40
your input is less,pls input again:50
your input is less,pls input again:55
your input is bigger,pls input again:53
your input is bigger,pls input again:52
your all input price is 4
[root@localhost shell]#
使用while守护进程的方式监控网站,每隔5秒确定一次网站是否正常。网站是惠而浦srm的登录页
[root@localhost shell]# cat 10_6_1.sh
#!/bin/bash
#***********************************************
#Author: luotianhao
#Mail: tianhao.luo@hand-china.com
#Version: 1.0
#Date: 2021-03-14
#FileName: 10_6_1.sh
#Description: This is a test script.
#***********************************************
[ $# -ne 1 ] && {
echo $"usage $0 url"
exit 1
}
while true
do
[ $( curl -o /dev/null --connect-timeout 5 -s -w "%{http_code}" $1|egrep -w "200|301|302"|wc -l ) -ne 1 ] && {
echo "$1 is error"
} || {
echo "$1 is ok"
}
sleep 5
done
[root@localhost shell]# sh 10_6_1.sh http://223.247.145.215:82/oauth/
http://223.247.145.215:82/oauth/ is ok
http://223.247.145.215:82/oauth/ is ok
http://223.247.145.215:82/oauth/ is ok
http://223.247.145.215:82/oauth/ is ok
http://223.247.145.215:82/oauth/ is ok
http://223.247.145.215:82/oauth/ is ok
引入函数库,使得输出更专业
[root@localhost shell]# cat 10_6_2.sh
#!/bin/bash
#***********************************************
#Author: luotianhao
#Mail: tianhao.luo@hand-china.com
#Version: 1.0
#Date: 2021-03-14
#FileName: 10_6_1.sh
#Description: This is a test script.
#***********************************************
. /etc/init.d/functions
[ $# -ne 1 ] && {
echo $"usage $0 url"
exit 1
}
while true
do
[ $( curl -o /dev/null --connect-timeout 5 -s -w "%{http_code}" $1|egrep -w "200|301|302"|wc -l ) -ne 1 ] && {
action "$1 is error" /bin/false
} || {
action "$1 is ok" /bin/true
}
sleep 5
done
[root@localhost shell]# sh 10_6_2.sh http://223.247.145.215:82/oauth/
http://223.247.145.215:82/oauth/ is ok [ 确定 ]
http://223.247.145.215:82/oauth/ is ok [ 确定 ]
http://223.247.145.215:82/oauth/ is ok [ 确定 ]
whlie循环按行读文件的方式
方式1:采用exec读取文件,然后进入while循环处理。
exec <FILE
sum=0
while read line
do
cmd
done
方式2:使用cat读取文件内容,然后通过管道进入while循环处理。
cat FILE_PATH|while read line
do
cmd
done
方式3:在while循环结尾done处通过输入重定向指定读取的文件。
while read line
do
cmd
done<FILE
实践:
[root@localhost shell]# cat 10_9_1.sh
#!/bin/bash
#***********************************************
#Author: luotianhao
#Mail: tianhao.luo@hand-china.com
#Version: 1.0
#Date: 2021-03-14
#FileName: 10_9_1.sh
#Description: This is a test script.
#***********************************************
while read line
do
echo $line
done<$1
[root@localhost shell]# sh 10_9_1.sh /etc/hosts
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
registry-1.docker.io. 52.5.11.128
registry-1.docker.io. 23.22.155.84
registry-1.docker.io. 18.232.227.119
registry-1.docker.io. 35.174.73.84
registry-1.docker.io. 54.85.107.53
registry-1.docker.io. 3.94.35.164
registry-1.docker.io. 54.236.131.166
registry-1.docker.io. 107.23.149.57