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腳本在背景運作的知識
用法:
-
:把腳本while1.sh放到背景執行(常用的方法)sh while1.sh &
-
:停止執行目前腳本或任務ctrl+c
-
:暫停執行目前腳本或任務ctrl+z
-
:把目前腳本或任務放到背景執行bg
-
:把目前腳本或任務放到前台執行,如果有多個任務,可以使用fg加任務編号調出對應的腳本任務,如fg 2,是指調出第二個腳本任務,fg可以了解為frontgroundfg
-
:檢視目前執行的腳本或任務jobs
-
:關閉執行的腳本任務,即以“kill %任務編号”的形式關閉腳本,這個任務編号,可以通過jobs來獲得kill
實踐上面的指令:
[[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