Shell入门-while循环和until循环

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可以理解为frontground
  • jobs:查看当前执行的脚本或任务
  • 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
"
[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
原文地址:https://www.cnblogs.com/tianhao-luo/p/14534699.html