天天看點

Shell入門-while循環和until循環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.每隔兩秒輸出系統負載

[[email protected] shell]# cat 10_1_1.sh 
#!/bin/bash
#***********************************************
#Author:        luotianhao
#Mail:          [email protected]
#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
[[email protected] 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裡面,使用微秒機關。通過在腳本的結尾使用&符号來在背景運作腳本

[[email protected] shell]# cat 10_1_2.sh 
#!/bin/bash
#***********************************************
#Author:        luotianhao
#Mail:          [email protected]
#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
[[email protected] shell]# sh 10_1_2.sh &
[1] 42470
[[email protected] 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來獲得

實踐上面的指令:

[[email protected] shell]# sh 10_1_2.sh &
[1] 51671
[[email protected] shell]# fg
sh 10_1_2.sh
^Z
[1]+  已停止               sh 10_1_2.sh
[[email protected] shell]# bg
[1]+ sh 10_1_2.sh &
[[email protected] shell]# jobs
[1]+  運作中               sh 10_1_2.sh &
[[email protected] shell]# fg 1
sh 10_1_2.sh
^C
[[email protected] shell]# jobs
[[email protected] shell]# 
           

使用kill關閉任務

[[email protected] shell]# sh 10_1_2.sh &
[1] 53378
[[email protected] shell]# sh 10_1_2.sh &
[2] 53412
[[email protected] shell]# jobs
[1]-  運作中               sh 10_1_2.sh &
[2]+  運作中               sh 10_1_2.sh &
[[email protected] shell]# kill %2
[[email protected] shell]# jobs
[1]-  運作中               sh 10_1_2.sh &
[2]+  已終止               sh 10_1_2.sh
[[email protected] shell]# 
           

有關程序管理的linux指令如下:

  • kill、killall、pkill:殺掉程序
  • ps:檢視程序
  • pstree:顯示程序樹
  • top:顯示程序
  • renice:改變優先權
  • nohup:使用者退出系統後繼續工作
  • pgrep:查找比對條件的程序
  • strace:跟蹤一個程序的系統調用情況
  • ltrace:跟蹤程序調用庫函數的情況

例子:計算從1加到100之和

[[email protected] shell]# cat 10_3_1.sh 
#!/bin/bash
#***********************************************
#Author:        luotianhao
#Mail:          [email protected]
#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"
[[email protected] shell]# sh 10_3_1.sh 
totalsum is:5050
           

記錄一個小bug,判斷是否是整數的時候:判斷失效了。

[[email protected] shell]# sh 10_4_1.sh 
pls input your number:a
2
pls input integer number
[[email protected] 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

寫在了一起,正确的是需要有一個空格的

[[email protected] shell]# cat 10_4_1.sh 
#!/bin/bash
#***********************************************
#Author:        luotianhao
#Mail:          [email protected]
#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"
[[email protected] 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
[[email protected] shell]# 
           

使用while守護程序的方式監控網站,每隔5秒确定一次網站是否正常。網站是惠而浦srm的登入頁

[[email protected] shell]# cat 10_6_1.sh 
#!/bin/bash
#***********************************************
#Author:        luotianhao
#Mail:          [email protected]
#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
[[email protected] 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
           

引入函數庫,使得輸出更專業

[[email protected] shell]# cat 10_6_2.sh 
#!/bin/bash
#***********************************************
#Author:        luotianhao
#Mail:          [email protected]
#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
[[email protected] 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
           

實踐:

[[email protected] shell]# cat 10_9_1.sh 
#!/bin/bash
#***********************************************
#Author:        luotianhao
#Mail:          [email protected]
#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
[[email protected] 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