03: 迴圈結構 case語句 、 函式及中斷控制 總結和答疑
NSD SHELL DAY03
1 案例1:使用for迴圈結構
1.1 問題
本案例要求編寫一個Shell指令碼chkhosts.sh,利用for迴圈來檢測多個主機的存活狀態,相關要求及說明如下:
- 對192.168.4.0/24網段執行ping檢測
- 指令碼能遍歷ping各主機,並反饋存活狀態
執行檢測指令碼以後,反饋結果如圖-1所示。
圖-1
1.2 方案
在Shell指令碼應用中,常見的for迴圈採用遍歷式、列表式的執行流程,通過指定變數從值列表中迴圈賦值,每次複製後執行固定的一組操作。
for迴圈的語法結構如下所示:
- for 變數名 in 值列表
- do
- 命令序列
- done
- for 變數名 in {1..5}
- do
- 命令序列
- done
- for 變數名 in `seq 5`
- do
- 命令序列
- done
- for 變數名 in `ls /etc/*.conf`
- do
- 命令序列
- done
1.3 步驟
實現此案例需要按照如下步驟進行。
步驟一:練習for迴圈基本用法
指令碼1,通過迴圈批量顯示5個hello world:
- [[email protected] ~]# vim for01.sh
- #!/bin/bash
- for i in 1 2 3 4 5
- do
- echo "hello world"
- done
- [[email protected] ~]# chmod +x for01.sh
- [
指令碼2,通過迴圈批量顯示10個hello world:
- [[email protected] ~]# vim for02.sh
- #!/bin/bash
- for i in {1..10}
- do
- echo "hello world"
- done
- [[email protected] ~]# chmod +x for02.sh
- [[email protected] ~]# ./for02.sh
指令碼3,通過迴圈批量顯示10個數字:
- [[email protected] ~]# vim for03.sh
- #!/bin/bash
- for i in {1..10}
- do
- echo "$i"
- done
- [[email protected] ~]# chmod +x for03.sh
- [[email protected] ~]# ./for03.sh
步驟二:批量檢測多個主機的存活狀態
1)編寫指令碼如下:
命令備註:ping命令可以測試某臺主機的連通性,
使用-c選項可以設定ping的次數,
使用-i選項可以設定多次ping之間的間隔時間(單位秒),
使用-W選項可以設定ping不通時的超時時間(單位秒)。
- [[email protected] ~]# vim chkhosts.sh
- #!/bin/bash
- for i in {1..254}
- do
- ping -c 3 -i 0.2 -W 1 192.168.4.$i &> /dev/null
- if [ $? -eq 0 ] ; then
- echo "Host 192.168.4.$i is up."
- else
- echo "Host 192.168.4.$i is down."
- fi
- done
- [[email protected] ~]# chmod +x chkhosts.sh
4)測試、驗證指令碼
- … …
- [[email protected] ~]# ./chkhosts.sh
- Host 192.168.4.5 is up.
- Host 192.168.4.6 is down
- … …
步驟三:建立賬戶的案例
建立users.txt,寫入無規律的賬戶名稱,最後使用for迴圈讀取該檔案,批量建立賬戶並設定密碼。
- [[email protected] ~]# vim addfor.sh
- #!/bin/bash
- for i in `cat /root/user.txt`
- do
- useradd $i
- echo 123456 | passwd --stdin $i
- done
附加擴充套件知識(C語言風格的for迴圈語法格式)
- [[email protected] ~]# vim cfor.sh
- #!/bin/bash
- for ((i=1;i<=5;i++))
- do
- echo $i
- done
2 案例2:使用while迴圈結構
2.1 問題
本案例要求編寫2個使用while迴圈的指令碼程式,分別實現以下目標:
- 提示使用者猜測一個隨機數,直到才對為止
- 檢測192.168.4.0/24網段,列出不線上的主機地址
2.2 方案
while迴圈屬於條件式的執行流程,會反覆判斷指定的測試條件,只要條件成立即執行固定的一組操作,直到條件變化為不成立為止。所以while迴圈的條件一般通過變數來進行控制,在迴圈體內對變數值做相應改變,以便在適當的時候退出,避免陷入死迴圈。
while迴圈的語法結構如下所示:
- while 條件測試
- do
- 命令序列
- done
- while :
- do
- 命令序列
- done
2.3 步驟
實現此案例需要按照如下步驟進行。
步驟一:練習while迴圈基本用法
指令碼1,無心的死迴圈指令碼:
- [[email protected] ~]# vim while01.sh
- #!/bin/bash
- i=1
- while [ $i -le 5 ]
- do
- echo "$i"
- done
- [[email protected] ~]# chmod +x while01.sh
- [[email protected] ~]# ./while01.sh //死迴圈,需要使用Ctrl+C終止指令碼
指令碼2,有效迴圈指令碼:
- [[email protected] ~]# vim while02.sh
- #!/bin/bash
- i=1
- while [ $i -le 5 ]
- do
- echo "$i"
- let i++
- done
- [[email protected] ~]# chmod +x while02.sh
- [[email protected] ~]# ./while02.sh
指令碼3,死迴圈的一般格式:
- [[email protected] ~]# vim while03.sh
- #!/bin/bash
- while :
- do
- echo "hello world"
- done
- [[email protected] ~]# chmod +x while03.sh
- [[email protected] ~]# ./while03.sh //死迴圈,需要使用Ctrl+C終止指令碼
步驟二:提示使用者猜測一個隨機數,直到才對為止
使用系統自帶變數RANDOM提取隨機數(1-100),使用while :製作死迴圈。
指令碼編寫參考如下:
- [[email protected] ~]# vim guess.sh
- #!/bin/bash
- num=$[RANDOM%100+1]
- i=0
- while :
- do
- read -p "隨機數1-100,你猜:" guess
- let i++ //猜一次,計數器加1,統計猜的次數
- if [ $guess -eq $num ];then
- echo "恭喜,猜對了"
- echo "你猜了$i次"
- exit
- elif [ $guess -gt $num ];then
- echo "猜大了"
- else
- echo "猜小了"
- fi
- [[email protected] ~]# chmod +x guess.sh
執行指令碼並驗證結果:
- [[email protected] ~]# ./guess.sh
步驟三:檢測192.168.4.0/24網段,列出不線上的主機地址
1)任務需求及思路分析
要求的是“檢測192.168.4.0/24網段,列出不線上的主機地址”。
檢測目標是一個網段,其網路部分“192.168.4.”可以作為固定的字首;而主機部分包括從1~254連續的地址,所以可結合while迴圈和自增變數進行控制。
2)根據實現思路編寫指令碼
- [[email protected] ~]# vim chknet.sh
- #!/bin/bash
- i=1
- while [ $i -le 254 ]
- do
- IP="192.168.4.$i"
- ping -c 3 -i 0.2 -W 1 $IP &> /dev/null
- if [ $? -eq 0 ] ; then
- echo "Host $IP is up."
- else
- echo "Host $IP is down."
- fi
- let i++
- done
- [[email protected] ~]# chmod +x chknet.sh
3)測試、驗證指令碼
- [[email protected] ~]# ./chknet.sh
- Host 192.168.4.1 is down.
- Host 192.168.4.2 is down.
- Host 192.168.4.3 is down.
- Host 192.168.4.4 is down.
- Host 192.168.4.5 is up.
- .. ..
- Host 192.168.4.250 is down.
- Host 192.168.4.251 is down.
- Host 192.168.4.252 is down.
- Host 192.168.4.253 is down.
- Host 192.168.4.254 is down.
3 案例3:基於case分支編寫指令碼
3.1 問題
本案例要求編寫test.sh指令碼,相關要求如下:
- 能使用redhat、fedora控制引數
- 控制引數通過位置變數$1傳入
- 當用戶輸入redhat引數,指令碼返回fedora
- 當用戶輸入fedora引數,指令碼返回redhat
- 當用戶輸入其他引數,則提示錯誤資訊
3.2 方案
case分支屬於匹配執行的方式,它針對指定的變數預先設定一個可能的取值,判斷該變數的實際取值是否與預設的某一個值相匹配,如果匹配上了,就執行相應的一組操作,如果沒有任何值能夠匹配,就執行預先設定的預設操作。
case分支的語法結構如下所示:
- case 變數 in
- 模式1)
- 命令序列1 ;;
- 模式2)
- 命令序列2 ;;
- .. ..
- *)
- 預設命令序列
- esac
3.3 步驟
實現此案例需要按照如下步驟進行。
步驟一:編寫指令碼檔案
指令碼編寫參考如下:
- [[email protected] ~]# vim test.sh
- #!/bin/bash
- case $1 in
- redhat)
- echo "fedora";;
- fedora)
- echo "redhat";;
- *) //預設輸出指令碼用法
- echo "用法: $0 {redhat|fedora}"
- esac
- [[email protected] ~]# chmod +x test.sh
步驟三:驗證、測試指令碼
未提供引數,或提供的引數無法識別時,提示正確用法:
- [[email protected] ~]# ./test.sh
- 用法: ./test.sh {redhat|fedora}
確認指令碼可以響應redhat控制引數:
- [[email protected] ~]# ./test.sh redhat
- fedora
確認指令碼可以響應fedora控制引數:
- [[email protected] ~]# ./test.sh fedora
- redhat
4 案例4:使用Shell函式
4.1 問題
本案例要求編寫指令碼mycolor.sh,相關要求如下:
- 將顏色輸出的功能定義為函式
- 呼叫函式,可以自定義輸出內容和顏色
4.2 方案
在Shell指令碼中,將一些需重複使用的操作,定義為公共的語句塊,即可稱為函式。通過使用函式,可以使指令碼程式碼更加簡潔,增強易讀性,提高Shell指令碼的執行效率
1)函式的定義方法
格式1:
- function 函式名 {
- 命令序列
- .. ..
- }
格式2:
- 函式名() {
- 命令序列
- .. ..
- }
2)函式的呼叫
直接使用“函式名”的形式呼叫,如果該函式能夠處理位置引數,則可以使用“函式名 引數1 引數2 .. ..”的形式呼叫。
注意:函式的定義語句必須出現在呼叫之前,否則無法執行。
3) 測試語法格式
- [[email protected] ~]# mycd(){ //定義函式
- > mkdir /test
- > cd /test
- > }
- [[email protected] ~]# mycd //呼叫函式
- [[email protected] ~]# mycd(){ //定義函式
- > mkdir $1
- > cd $1
- > }
- [[email protected] ~]# mycd /abc //呼叫函式
- [[email protected] ~]# mycd /360 //呼叫函式
4.3 步驟
實現此案例需要按照如下步驟進行。
步驟一:編寫mycolor.sh指令碼
1)任務需求及思路分析
使用者在執行時提供2個整數引數,這個可以通過位置變數$1、$2讀入。
呼叫函式時,將使用者提供的兩個引數傳遞給函式處理。
顏色輸出的命令:echo -e "\033[32mOK\033[0m"。
3X為字型顏色,4X為背景顏色。
2)根據實現思路編寫指令碼檔案
- [[email protected] ~]# vim mycolor.sh
- #!/bin/bash
- cecho() {
- echo -e "\033[$1m$2\033[0m"
- }
- cecho 32 OK
- cecho 33 OK
- cecho 34 OK
- cecho 35 OK
- [[email protected] ~]# chmod +x mycolor.sh
3)測試指令碼執行效果
- [[email protected] ~]# ./mycolor.sh
使用函式,優化改進前面的指令碼:
- [[email protected] ~]# vim myping.sh
- #!/bin/bash
- myping(){
- ping -c1 -W1 $1 &>/dev/null
- if [ $? -eq 0 ];then
- echo "$1 is up"
- else
- echo "$1 is down"
- fi
- }
- for i in {1..254}
- do
- myping 192.168.4.$i &
- done
- wait
- #wait命令的作用是等待所有後臺程序都結束才結束指令碼。
Shell版本的fork炸彈
- [[email protected] ~]# vim test.sh
- #!/bin/bash
- .(){
- .|.&
- }
- .
5 案例5:中斷及退出
5.1 問題
本案例要求編寫兩個Shell指令碼,相關要求如下:
- 從鍵盤迴圈取整數(0結束)並求和,輸出最終結果
- 找出1~20以內6的倍數,並輸出她的平方值
5.2 方案
通過break、continue、exit在Shell指令碼中實現中斷與退出的功能。
break可以結束整個迴圈;continue結束本次迴圈,進入下一次迴圈;exit結束整個指令碼,案例如下:
- [[email protected] ~]# vim test.sh
- #!/bin/bash
- for i in {1..5}
- do
- [ $i -eq 3 ]&& break //這裡將break替換為continue,exit分別測試指令碼執行效果 echo $i
- done
- echo "Game Over"
5.3 步驟
實現此案例需要按照如下步驟進行。
步驟一:編寫求和指令碼sum.sh
1)編寫指令碼檔案
- [[email protected] ~]# vim sum.sh
- #!/bin/bash
- SUM=0
- while :
- do
- read -p "請輸入整數(0表示結束):" x
- [ $x -eq 0 ] && break
- SUM=$[SUM+x]
- done
- echo "總和是:$SUM"
- [[email protected] ~]# chmod +x sum.sh
- [[email protected] ~]# ./sum.sh
步驟二:編寫指令碼檔案,找出1-20內6的倍數,並列印她的平方值
1)編寫指令碼檔案
注意:要求列印所有6的倍數的平方值,也就是非6的倍數都跳過!!!
- [[email protected] ~]# vim test.sh
- #!/bin/bash
- for i in {1..20}
- do
- [ $[i%6] -ne 0 ] && continue
- echo $[i*i]
- done
- [[email protected] ~]# chmod +x test.sh
- [[email protected] ~]# ./test.sh