• 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
    
  • 相关阅读:
    二叉查找中使用位运算符
    Python2021专业版激活码
    南邮计算机方向
    7.字符串、异常处理、文件和流(C++学习笔记)
    6.多态与抽象(C++学习笔记)
    5.对象类与继承(C++学习笔记)
    4.数组与指针(C++学习笔记)
    3.C++函数(C++学习笔记)
    2.C++控制语句(C++学习笔记)
    1.基本知识(C++学习笔记)
  • 原文地址:https://www.cnblogs.com/tianhao-luo/p/14534699.html
Copyright © 2020-2023  润新知