1. 程式人生 > 實用技巧 >OSPF 、 傳輸層 、 ACL

OSPF 、 傳輸層 、 ACL

1.1 問題

本案例要求參考PPT上的示例,分別練習以下條件測試操作:

  • 字串匹配
  • 比較整數值的大小
  • 識別檔案/目錄的狀態
  • 多個條件/操作的邏輯組合

1.2 步驟

實現此案例需要按照如下步驟進行。

步驟一:條件測試的基本用法

1)語法格式

使用“test 表示式”或者[ 表示式 ]都可以,表示式兩邊至少要留一個空格。

條件測試操作本身不顯示出任何資訊。測試的條件是否成立主要體現在命令執行後的返回狀態(即 $?),所以可以在測試後檢視變數$?的值來做出判斷,或者結合&&、||等邏輯操作顯示出結果(或作其他操作) 。

步驟二:字串測試

1)== 比較兩個字串是否相同

檢查當前使用者是否為root。

當root使用者執行時:

copytextpop-up
  1. [root@svr5 ~]# [ $USER == "root" ] //測試
  2. [root@svr5 ~]# echo $?//檢視結果0為對,非0為錯
[root@svr5 ~]# [ $USER == "root" ] 		//測試
[root@svr5 ~]# echo $?					//檢視結果0為對,非0為錯

當普通使用者執行時:

copytextpop-up
  1. [zengye@svr5 ~]$ [ $USER == "root" ]
  2. [zengye@svr5 ~]$ echo $? //檢視結果0為對,非0為錯
[zengye@svr5 ~]$ [ $USER == "root" ]
[zengye@svr5 ~]$ echo $?                    //檢視結果0為對,非0為錯

2)!= 比較兩個字串是否不相同

當普通使用者執行時:

copytextpop-up
  1. [zengye@svr5 ~]$ [ $USER != "root" ]
[zengye@svr5 ~]$ [ $USER != "root" ] 

當root使用者執行時:

copytextpop-up
  1. [root@svr5 ~]# [ $USER != "root" ]
[root@svr5 ~]# [ $USER != "root" ]

3)一行執行多條命令的情況

copytextpop-up
  1. # A && B //僅當A命令執行成功,才執行B命令
  2. # A || B//僅當A命令執行失敗,才執行B命令
  3. # A ; B//執行A命令後執行B命令,兩者沒有邏輯關係
  4. # A && B || C //思考?
# A && B    					//僅當A命令執行成功,才執行B命令
# A || B						//僅當A命令執行失敗,才執行B命令
# A ;  B						//執行A命令後執行B命令,兩者沒有邏輯關係
# A && B || C                   //思考?

4) -z 檢查變數的值是否未設定(空值)

copytextpop-up
  1. [root@svr5 ~]# var1="nb" ; var2=""
  2. [root@svr5 ~]# [ -z "$var1" ] && echo "空值" || echo "非空值"
  3. 非空值
  4. [root@svr5 ~]# [ -z $var2 ] && echo "空值" || echo "非空值"
  5. 空值 //變數var2已設定,但無任何值,視為空
  6. [root@svr5 ~]# [ ! -z $var1 ]//測試var1是否為非空
[root@svr5 ~]# var1="nb" ; var2=""
[root@svr5 ~]# [ -z "$var1" ] && echo "空值" || echo "非空值"
非空值
[root@svr5 ~]# [ -z $var2 ] && echo "空值" || echo "非空值"
空值  									//變數var2已設定,但無任何值,視為空
[root@svr5 ~]# [ ! -z $var1 ]				//測試var1是否為非空

還有一個-n可以測試變數是否不為空(相當於! -z)。

步驟三:整數值比較

參與比較的必須是整數(可以呼叫變數),比較非整數值時會出錯:

copytextpop-up
  1. [root@svr5 ~]# A=20.4
  2. [root@svr5 ~]# [ $A -gt 10 ] //不支援小數比較
  3. -bash: [: 20.4: integer expression expected
[root@svr5 ~]# A=20.4
[root@svr5 ~]# [ $A -gt 10 ]  				//不支援小數比較
-bash: [: 20.4: integer expression expected

1)-eq 比較兩個數是否相等。

copytextpop-up
  1. [root@svr5 ~]# X=20 //定義一個測試變數
  2. [root@svr5 ~]# [ $X -eq 20 ] && echo "相等" || echo "不相等"
  3. 相等
  4. [root@svr5 ~]# [ $X -eq 30 ] && echo "相等" || echo "不相等"
  5. 不相等
[root@svr5 ~]# X=20  						//定義一個測試變數
[root@svr5 ~]# [ $X -eq 20 ] && echo "相等" || echo "不相等"
相等
[root@svr5 ~]# [ $X -eq 30 ] && echo "相等" || echo "不相等"
不相等

2)-ne 比較兩個數是否不相等。

copytextpop-up
  1. [root@svr5 ~]# X=20 //定義一個測試變數
  2. [root@svr5 ~]# [ $X -ne 20 ] && echo "不等於" || echo "等於"
  3. 等於
  4. [root@svr5 ~]# [ $X -ne 30 ] && echo "不等於" || echo "等於"
  5. 不等於
[root@svr5 ~]# X=20  						//定義一個測試變數
[root@svr5 ~]# [ $X -ne 20 ] && echo "不等於" || echo "等於"
等於
[root@svr5 ~]# [ $X -ne 30 ] && echo "不等於" || echo "等於"
不等於

3)-gt 比較前面的整數是否大於後面的整數。

copytextpop-up
  1. [root@svr5 ~]# X=20 //定義一個測試變數
  2. [root@svr5 ~]# [ $X -gt 10 ] && echo "大於" || echo "否"
  3. 大於
  4. [root@svr5 ~]# [ $X -gt 20 ] && echo "大於" || echo "否"
  5. [root@svr5 ~]# [ $X -gt 30 ] && echo "大於" || echo "否"
[root@svr5 ~]# X=20  						//定義一個測試變數
[root@svr5 ~]# [ $X -gt 10 ] && echo "大於" || echo "否"
大於
[root@svr5 ~]# [ $X -gt 20 ] && echo "大於" || echo "否"
否
[root@svr5 ~]# [ $X -gt 30 ] && echo "大於" || echo "否"
否

4)-ge 比較前面的整數是否大於或等於後面的整數。

copytextpop-up
  1. [root@svr5 ~]# X=20 //定義一個測試變數
  2. [root@svr5 ~]# [ $X -ge 10 ] && echo "大於或等於" || echo "否"
  3. 大於或等於
  4. [root@svr5 ~]# [ $X -ge 20 ] && echo "大於或等於" || echo "否"
  5. 大於或等於
  6. [root@svr5 ~]# [ $X -ge 30 ] && echo "大於或等於" || echo "否"
[root@svr5 ~]# X=20  						//定義一個測試變數
[root@svr5 ~]# [ $X -ge 10 ] && echo "大於或等於" || echo "否"
大於或等於
[root@svr5 ~]# [ $X -ge 20 ] && echo "大於或等於" || echo "否"
大於或等於
[root@svr5 ~]# [ $X -ge 30 ] && echo "大於或等於" || echo "否"
否

5)-lt 比較前面的整數是否小於後面的整數。

copytextpop-up
  1. [root@svr5 ~]# X=20 //定義一個測試變數
  2. [root@svr5 ~]# [ $X -lt 10 ] && echo "小於" || echo "否"
  3. [root@svr5 ~]# [ $X -lt 20 ] && echo "小於" || echo "否"
  4. [root@svr5 ~]# [ $X -lt 30 ] && echo "小於" || echo "否"
  5. 小於
[root@svr5 ~]# X=20  						//定義一個測試變數
[root@svr5 ~]# [ $X -lt 10 ] && echo "小於" || echo "否"
否
[root@svr5 ~]# [ $X -lt 20 ] && echo "小於" || echo "否"
否
[root@svr5 ~]# [ $X -lt 30 ] && echo "小於" || echo "否"
小於

6)-le 比較前面的整數是否小於或等於後面的整數。

copytextpop-up
  1. [root@svr5 ~]# X=20 //定義一個測試變數
  2. [root@svr5 ~]# [ $X -le 10 ] && echo "小於或等於" || echo "否"
  3. [root@svr5 ~]# [ $X -le 20 ] && echo "小於或等於" || echo "否"
  4. 小於或等於
  5. [root@svr5 ~]# [ $X -le 30 ] && echo "小於或等於" || echo "否"
  6. 小於或等於
[root@svr5 ~]# X=20  						//定義一個測試變數
[root@svr5 ~]# [ $X -le 10 ] && echo "小於或等於" || echo "否"
否
[root@svr5 ~]# [ $X -le 20 ] && echo "小於或等於" || echo "否"
小於或等於
[root@svr5 ~]# [ $X -le 30 ] && echo "小於或等於" || echo "否"
小於或等於

7)提取當前登入的使用者數,比較是否大於等於3。

copytextpop-up
  1. [root@svr5 ~]# who | wc -l //確認已登入的使用者數
  2. 2
  3. [root@svr5 ~]# N=$(who | wc -l) //賦值給變數N
  4. [root@svr5 ~]# [ $N -ge 3 ] && echo "超過了" || echo "沒超過"
  5. 沒超過
[root@svr5 ~]# who | wc -l  								//確認已登入的使用者數
2
[root@svr5 ~]# N=$(who | wc -l)  							//賦值給變數N
[root@svr5 ~]# [ $N -ge 3 ] && echo "超過了" || echo "沒超過"
沒超過

上述賦值給變數N及與3比較的操作,可以簡化為如下形式:

copytextpop-up
  1. [root@svr5 ~]# [ $(who | wc -l) -ge 3 ] && echo "超過了" || echo "沒超過"
  2. 沒超過
[root@svr5 ~]# [ $(who | wc -l) -ge 3 ] && echo "超過了" || echo "沒超過"
沒超過

步驟四:識別檔案/目錄的狀態

1)-e 判斷物件是否存在(不管是目錄還是檔案)

copytextpop-up
  1. [root@svr5 ~]# [ -e "/usr/" ] && echo "存在" || echo "不存在"
  2. 存在
  3. [root@svr5 ~]# [ -e "/etc/fstab" ] && echo "存在" || echo "不存在"
  4. 存在
  5. [root@svr5 ~]# [ -e "/home/nooby" ] && echo "存在" || echo "不存在"
  6. 不存在
[root@svr5 ~]# [ -e "/usr/" ] && echo "存在" || echo "不存在"
存在
[root@svr5 ~]# [ -e "/etc/fstab" ] && echo "存在" || echo "不存在"
存在
[root@svr5 ~]# [ -e "/home/nooby" ] && echo "存在" || echo "不存在"
不存在

2)-d 判斷物件是否為目錄(存在且是目錄)

copytextpop-up
  1. [root@svr5 ~]# [ -d "/usr/" ] && echo "是目錄" || echo "不是目錄"
  2. 是目錄
  3. [root@svr5 ~]# [ -d "/etc/fstab" ] && echo "是目錄" || echo "不是目錄"
  4. 不是目錄
  5. [root@svr5 ~]# [ -d "/home/nooby" ] && echo "是目錄" || echo "不是目錄"
  6. 不是目錄
[root@svr5 ~]# [ -d "/usr/" ] && echo "是目錄" || echo "不是目錄"
是目錄
[root@svr5 ~]# [ -d "/etc/fstab" ] && echo "是目錄" || echo "不是目錄"
不是目錄
[root@svr5 ~]# [ -d "/home/nooby" ] && echo "是目錄" || echo "不是目錄"
不是目錄

3)-f 判斷物件是否為檔案(存在且是檔案)

copytextpop-up
  1. [root@svr5 ~]# [ -f "/usr/" ] && echo "是檔案" || echo "不是檔案"
  2. 不是檔案
  3. [root@svr5 ~]# [ -f "/etc/fstab" ] && echo "是檔案" || echo "不是檔案"
  4. 是檔案
  5. [root@svr5 ~]# [ -f "/home/nooby" ] && echo "是檔案" || echo "不是檔案"
  6. 不是檔案
[root@svr5 ~]# [ -f "/usr/" ] && echo "是檔案" || echo "不是檔案"
不是檔案
[root@svr5 ~]# [ -f "/etc/fstab" ] && echo "是檔案" || echo "不是檔案"
是檔案
[root@svr5 ~]# [ -f "/home/nooby" ] && echo "是檔案" || echo "不是檔案"
不是檔案

4)-r 判斷物件是否可讀

此測試對root使用者無效,無論檔案是否設定r許可權,root都可讀:

copytextpop-up
  1. [root@svr5 ~]# cp /etc/hosts /tmp/test.txt //複製一個檔案做測試
  2. [root@svr5 ~]# chmod -r /tmp/test.txt //去掉所有的r許可權
  3. [root@svr5 ~]# [ -r "/tmp/test.txt" ] && echo "可讀" || echo "不可讀"
  4. 可讀 //root測試結果仍然可讀
[root@svr5 ~]# cp /etc/hosts /tmp/test.txt  		//複製一個檔案做測試
[root@svr5 ~]# chmod -r /tmp/test.txt  			//去掉所有的r許可權
[root@svr5 ~]# [ -r "/tmp/test.txt" ] && echo "可讀" || echo "不可讀"
可讀  											//root測試結果仍然可讀

切換為普通使用者,再執行相同的測試,結果變為“不可讀”:

copytextpop-up
  1. [zengye@svr5 ~]$ [ -r "/tmp/test.txt" ] && echo "可讀" || echo "不可讀"
  2. 不可讀
[zengye@svr5 ~]$ [ -r "/tmp/test.txt" ] && echo "可讀" || echo "不可讀"
不可讀

5)-w 判斷物件是否可寫

此測試同樣對root使用者無效,無論檔案是否設定w許可權,root都可寫:

copytextpop-up
  1. [root@svr5 ~]# chmod -w /tmp/test.txt //去掉所有的w許可權
  2. [root@svr5 ~]# ls -l /tmp/test.txt //確認設定結果
  3. ---------- 1 root root 33139 12-11 10:43 /tmp/test.txt
  4. [root@svr5 ~]# [ -w "/tmp/test.txt" ] && echo "可寫" || echo "不可寫"
  5. 可寫
[root@svr5 ~]# chmod -w /tmp/test.txt 			//去掉所有的w許可權
[root@svr5 ~]# ls -l /tmp/test.txt  			//確認設定結果
---------- 1 root root 33139 12-11 10:43 /tmp/test.txt
[root@svr5 ~]# [ -w "/tmp/test.txt" ] && echo "可寫" || echo "不可寫"
可寫

切換為普通使用者,可以正常使用-w測試:

copytextpop-up
  1. [zengye@svr5 ~]$ ls -l /tmp/test.txt
  2. ---------- 1 root root 33139 12-11 10:52 /tmp/test.txt
  3. [zengye@svr5 ~]$ [ -w "/tmp/test.txt" ] && echo "可寫" || echo "不可寫"
  4. 不可寫
[zengye@svr5 ~]$ ls -l /tmp/test.txt
---------- 1 root root 33139 12-11 10:52 /tmp/test.txt
[zengye@svr5 ~]$ [ -w "/tmp/test.txt" ] && echo "可寫" || echo "不可寫"
不可寫

6)-x 判斷物件是否具有可執行許可權

這個取決於檔案本身、檔案系統級的控制,root或普通使用者都適用:

copytextpop-up
  1. [root@svr5 ~]# chmod 644 /tmp/test.txt //重設許可權,無x
  2. [root@svr5 ~]# ls -l /tmp/test.txt //確認設定結果
  3. -rw-r--r-- 1 root root 33139 12-11 10:52 /tmp/test.txt
  4. [root@svr5 ~]# [ -x "/tmp/test.txt" ] && echo "可執行" || echo "不可執行"
  5. 不可執行
  6. [root@svr5 ~]# chmod +x /tmp/test.txt //新增x許可權
  7. [root@svr5 ~]# [ -x "/tmp/test.txt" ] && echo "可執行" || echo "不可執行"
  8. 可執行
[root@svr5 ~]# chmod 644 /tmp/test.txt  		//重設許可權,無x
[root@svr5 ~]# ls -l /tmp/test.txt  			//確認設定結果
-rw-r--r-- 1 root root 33139 12-11 10:52 /tmp/test.txt
[root@svr5 ~]# [ -x "/tmp/test.txt" ] && echo "可執行" || echo "不可執行"
不可執行
[root@svr5 ~]# chmod +x /tmp/test.txt  		//新增x許可權
[root@svr5 ~]# [ -x "/tmp/test.txt" ] && echo "可執行" || echo "不可執行"
可執行

步驟五:多個條件/操作的邏輯組合

1)&&,邏輯與

給定條件必須都成立,整個測試結果才為真。

檢查變數X的值是否大於10,且小於30:

copytextpop-up
  1. [root@svr5 ~]# X=20 //設定X變數的值為20
  2. [root@svr5 ~]# [ $X -gt 10 ] && [ $X -lt 30 ] && echo "YES"
  3. YES
[root@svr5 ~]# X=20  					//設定X變數的值為20
[root@svr5 ~]# [ $X -gt 10 ] && [ $X -lt 30 ] && echo "YES"
YES

2)||,邏輯或

只要其中一個條件成立,則整個測試結果為真。

只要/tmp/、/var/spool/目錄中有一個可寫,則條件成立:

copytextpop-up
  1. [root@svr5 ~]# [ -w "/tmp/" ] || [ -w "/var/spool/" ] && echo "OK"
  2. OK
[root@svr5 ~]# [ -w "/tmp/" ] || [ -w "/var/spool/" ] && echo "OK"
OK

2 案例2:使用if選擇結構

2.1 問題

本案例要求編寫3個Shell指令碼,分別實現以下目標:

  • 檢測/media/cdrom目錄,若不存在則建立
  • 檢測並判斷指定的主機是否可ping通
  • 從鍵盤讀取一個論壇積分,判斷論壇使用者等級,等級分類如下:

大於等於90 神功絕世

大於等於80,小於90 登峰造極

大於等於70,小於80 爐火純青

大於等於60,小於70 略有小成

小於60 初學乍練

2.2 方案

if單分支的語法組成:

copytextpop-up
  1. if 條件測試
  2. then
  3. 命令序列
  4. fi
if  條件測試
then  
命令序列
fi

if雙分支的語法組成:

copytextpop-up
  1. if 條件測試
  2. then
  3. 命令序列1
  4. else
  5. 命令序列2
  6. fi
if  條件測試
then
命令序列1
else  
命令序列2
fi

if多分支的語法組成:

copytextpop-up
  1. if 條件測試1 ;then
  2. 命令序列1
  3. elif 條件測試2 ;then
  4. 命令序列2
  5. else
  6. 命令序列n
  7. fi
if    條件測試1 ;then  
命令序列1
elif  條件測試2 ;then  
命令序列2
else
命令序列n
fi

2.3 步驟

實現此案例需要按照如下步驟進行。

步驟一:檢測/media/cdrom目錄,若不存在則建立

1)編寫指令碼如下:

copytextpop-up
  1. [root@svr5 ~]# vim mountdir.sh
  2. #!/bin/bash
  3. dir="/media/cdrom/"
  4. if [ ! -d $dir ]
  5. then
  6. mkdir -p $dir
  7. fi
  8. [root@svr5 ~]# chmod +x mountdir.sh //新增可執行許可權
[root@svr5 ~]# vim mountdir.sh 
#!/bin/bash
dir="/media/cdrom/"
if [ ! -d $dir ]
then
    mkdir -p $dir
fi 

[root@svr5 ~]# chmod +x mountdir.sh  				//新增可執行許可權

2)測試、驗證指令碼功能

copytextpop-up
  1. [root@svr5 ~]# ls -ld /media/cdrom //本來沒有/media/cdrom目錄
  2. ls: /media/cdrom: 沒有那個檔案或目錄
  3. [root@svr5 ~]# ./mountdir.sh //執行指令碼
  4. [root@svr5 ~]# ls -ld /media/cdrom //再檢查已經有了
  5. drwxr-xr-x 2 root root 4096 12-11 15:16 /media/cdrom
[root@svr5 ~]# ls -ld /media/cdrom  				//本來沒有/media/cdrom目錄
ls: /media/cdrom: 沒有那個檔案或目錄
[root@svr5 ~]# ./mountdir.sh  						//執行指令碼
[root@svr5 ~]# ls -ld /media/cdrom  				//再檢查已經有了
drwxr-xr-x 2 root root 4096 12-11 15:16 /media/cdrom

有了/media/cdrom資料夾以後,再次執行上述指令碼,實際上不做任何有效操作:

copytextpop-up
  1. [root@svr5 ~]# ./mountdir.sh
[root@svr5 ~]# ./mountdir.sh

步驟二:檢測並判斷指定的主機是否可ping通

1)分析任務需求

使用ping命令檢測目標主機時,人工可直接判斷反饋結果,而指令碼卻不方便。但是當ping測試成功時,執行狀態$?的值為0;而ping測試失敗時,$?的值不為0。因此在Shell指令碼中可以利用這一點來判斷ping目標主機的成敗。

為了節省ping測試時間,可以只發送3個測試包(-c 3)、縮短髮送測試包的間隔秒數(-i 0.2)、等待反饋的超時秒數(-W 1)。比如,檢查可ping通的主機:

copytextpop-up
  1. [root@svr5 ~]# ping -c 3 -i 0.2 -W 1 192.168.4.5
  2. PING 192.168.4.5 (192.168.4.5) 56(84) bytes of data.
  3. 64 bytes from 192.168.4.5: icmp_seq=1 ttl=64 time=0.131 ms
  4. 64 bytes from 192.168.4.5: icmp_seq=2 ttl=64 time=0.076 ms
  5. 64 bytes from 192.168.4.5: icmp_seq=3 ttl=64 time=0.073 ms
  6. --- 192.168.4.5 ping statistics ---
  7. 3 packets transmitted, 3 received, 0% packet loss, time 402ms
  8. rtt min/avg/max/mdev = 0.073/0.093/0.131/0.027 ms
  9. [root@svr5 ~]# echo $? //執行狀態表示成功
  10. 0
[root@svr5 ~]# ping -c 3 -i 0.2 -W 1 192.168.4.5
PING 192.168.4.5 (192.168.4.5) 56(84) bytes of data.
64 bytes from 192.168.4.5: icmp_seq=1 ttl=64 time=0.131 ms
64 bytes from 192.168.4.5: icmp_seq=2 ttl=64 time=0.076 ms
64 bytes from 192.168.4.5: icmp_seq=3 ttl=64 time=0.073 ms

--- 192.168.4.5 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 402ms
rtt min/avg/max/mdev = 0.073/0.093/0.131/0.027 ms

[root@svr5 ~]# echo $?  								//執行狀態表示成功
0

2)指令碼編寫參考如下:

copytextpop-up
  1. [root@svr5 ~]# vim pinghost.sh
  2. #!/bin/bash
  3. ping -c 3 -i 0.2 -W 1 $1 &> /dev/null
  4. if [ $? -eq 0 ] ; then
  5. echo "Host $1 is up."
  6. else
  7. echo "Host $1 is down."
  8. fi
  9. [root@svr5 ~]# chmod +x pinghost.sh
[root@svr5 ~]# vim pinghost.sh 
#!/bin/bash
ping -c 3 -i 0.2 -W 1 $1 &> /dev/null
if [ $? -eq 0 ] ; then
    echo "Host $1 is up."
else
    echo "Host $1 is down."
fi

[root@svr5 ~]# chmod +x pinghost.sh 

3)測試、驗證指令碼功能

copytextpop-up
  1. [root@svr5 ~]# ./pinghost.sh 192.168.4.5
  2. Host 192.168.4.5 is up.
  3. [root@svr5 ~]# ./pinghost.sh 192.168.4.50
  4. Host 192.168.4.50 is down.
[root@svr5 ~]# ./pinghost.sh 192.168.4.5
Host 192.168.4.5 is up.
[root@svr5 ~]# ./pinghost.sh 192.168.4.50
Host 192.168.4.50 is down.

步驟三:從鍵盤讀取一個論壇積分,判斷論壇使用者等級

1)指令碼編寫參考如下:

大於等於90 神功絕世

大於等於80,小於90 登峰造極

大於等於70,小於80 爐火純青

大於等於60,小於70 略有小成

小於60 初學乍練

copytextpop-up
  1. [root@svr5 ~]# vim grade.sh
  2. #!/bin/bash
  3. read -p "請輸入積分(0-100):" JF
  4. if [ $JF -ge 90 ] ; then
  5. echo "$JF 分,神功絕世"
  6. elif [ $JF -ge 80 ] ; then
  7. echo "$JF 分,登峰造極"
  8. elif [ $JF -ge 70 ] ; then
  9. echo "$JF 分,爐火純青"
  10. elif [ $JF -ge 60 ] ; then
  11. echo "$JF 分,略有小成"
  12. else
  13. echo "$JF 分,初學乍練"
  14. fi
  15. [root@svr5 ~]# chmod +x grade.sh
[root@svr5 ~]# vim grade.sh 
#!/bin/bash
read -p "請輸入積分(0-100):" JF
if [ $JF -ge 90 ] ; then
    echo "$JF 分,神功絕世"
elif [ $JF -ge 80 ] ; then
    echo "$JF 分,登峰造極"
elif [ $JF -ge 70 ] ; then
    echo "$JF 分,爐火純青"
elif [ $JF -ge 60 ] ; then
    echo "$JF 分,略有小成"
else
    echo "$JF 分,初學乍練"
fi

[root@svr5 ~]# chmod +x grade.sh

3)測試、驗證指令碼

copytextpop-up
  1. [root@svr5 ~]# ./grade.sh
  2. 請輸入積分(0-100):74
  3. 74 分,爐火純青
  4. [root@svr5 ~]# ./grade.sh
  5. 請輸入分數(0-100):68
  6. 68 分,略有小成
  7. [root@svr5 ~]# ./grade.sh
  8. 請輸入分數(0-100):87
  9. 87 分,登峰造極
[root@svr5 ~]# ./grade.sh 
請輸入積分(0-100):74
74 分,爐火純青
[root@svr5 ~]# ./grade.sh 
請輸入分數(0-100):68
68 分,略有小成
[root@svr5 ~]# ./grade.sh 
請輸入分數(0-100):87
87 分,登峰造極

3 案例3:使用for迴圈結構

3.1 問題

本案例要求編寫一個Shell指令碼chkhosts.sh,利用for迴圈來檢測多個主機的存活狀態,相關要求及說明如下:

  • 對192.168.4.0/24網段執行ping檢測
  • 指令碼能遍歷ping各主機,並反饋存活狀態

執行檢測指令碼以後,反饋結果如圖-1所示。

圖-1

3.2 方案

在Shell指令碼應用中,常見的for迴圈採用遍歷式、列表式的執行流程,通過指定變數從值列表中迴圈賦值,每次複製後執行固定的一組操作。

for迴圈的語法結構如下所示:

copytextpop-up
  1. for 變數名 in 值列表
  2. do
  3. 命令序列
  4. done
  5. for 變數名 in {1..5}
  6. do
  7. 命令序列
  8. done
  9. for 變數名 in `seq 5`
  10. do
  11. 命令序列
  12. done
  13. for 變數名 in `ls /etc/*.conf`
  14. do
  15. 命令序列
  16. done
for  變數名  in  值列表
do
    命令序列
done

for  變數名  in  {1..5}
do
    命令序列
done
for  變數名  in  `seq 5`
do
    命令序列
done

for  變數名  in  `ls /etc/*.conf`
do
    命令序列
done

3.3 步驟

實現此案例需要按照如下步驟進行。

步驟一:練習for迴圈基本用法

指令碼1,通過迴圈批量顯示5個hello world:

copytextpop-up
  1. [root@svr5 ~]# vim for01.sh
  2. #!/bin/bash
  3. for i in 1 2 3 4 5
  4. do
  5. echo "hello world"
  6. done
  7. [root@svr5 ~]# chmod +x for01.sh
  8. [root@svr5 ~]# ./for01.sh
[root@svr5 ~]# vim for01.sh
#!/bin/bash
for i in 1 2 3 4 5
do
		echo "hello world"
done
[root@svr5 ~]# chmod +x for01.sh
[root@svr5 ~]# ./for01.sh

指令碼2,通過迴圈批量顯示10個hello world:

copytextpop-up
  1. [root@svr5 ~]# vim for02.sh
  2. #!/bin/bash
  3. for i in {1..10}
  4. do
  5. echo "hello world"
  6. done
  7. [root@svr5 ~]# chmod +x for02.sh
  8. [root@svr5 ~]# ./for02.sh
[root@svr5 ~]# vim for02.sh
#!/bin/bash
for i in {1..10}
do
		echo "hello world"
done
[root@svr5 ~]# chmod +x for02.sh
[root@svr5 ~]# ./for02.sh

指令碼3,通過迴圈批量顯示10個數字:

copytextpop-up
  1. [root@svr5 ~]# vim for03.sh
  2. #!/bin/bash
  3. for i in {1..10}
  4. do
  5. echo "$i"
  6. done
  7. [root@svr5 ~]# chmod +x for03.sh
  8. [root@svr5 ~]# ./for03.sh
[root@svr5 ~]# vim for03.sh
#!/bin/bash
for i in {1..10}
do
		echo "$i"
done
[root@svr5 ~]# chmod +x for03.sh
[root@svr5 ~]# ./for03.sh

步驟二:批量檢測多個主機的存活狀態

1)編寫指令碼如下:

命令備註:ping命令可以測試某臺主機的連通性,

使用-c選項可以設定ping的次數,

使用-i選項可以設定多次ping之間的間隔時間(單位秒),

使用-W選項可以設定ping不通時的超時時間(單位秒)。

copytextpop-up
  1. [root@svr5 ~]# vim chkhosts.sh
  2. #!/bin/bash
  3. for i in {1..254}
  4. do
  5. ping -c 3 -i 0.2 -W 1 192.168.4.$i &> /dev/null
  6. if [ $? -eq 0 ] ; then
  7. echo "Host 192.168.4.$i is up."
  8. else
  9. echo "Host 192.168.4.$i is down."
  10. fi
  11. done
  12. [root@svr5 ~]# chmod +x chkhosts.sh
[root@svr5 ~]# 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
[root@svr5 ~]# chmod +x chkhosts.sh

4)測試、驗證指令碼

copytextpop-up
  1. … …
  2. [root@svr5 ~]# ./chkhosts.sh
  3. Host 192.168.4.5 is up.
  4. Host 192.168.4.6 is down
  5. … …
… …
[root@svr5 ~]# ./chkhosts.sh
Host 192.168.4.5 is up.
Host 192.168.4.6 is down
… …

步驟三:建立賬戶的案例

建立users.txt,寫入無規律的賬戶名稱,最後使用for迴圈讀取該檔案,批量建立賬戶並設定密碼。

copytextpop-up
  1. [root@svr5 ~]# vim addfor.sh
  2. #!/bin/bash
  3. for i in `cat /root/user.txt`
  4. do
  5. useradd $i
  6. echo 123456 | passwd --stdin $i
  7. done
[root@svr5 ~]# vim addfor.sh
#!/bin/bash
for i in `cat /root/user.txt`
do
     useradd $i
     echo 123456 | passwd --stdin $i
done

附加擴充套件知識(C語言風格的for迴圈語法格式)

copytextpop-up
  1. [root@svr5 ~]# vim cfor.sh
  2. #!/bin/bash
  3. for ((i=1;i<=5;i++))
  4. do
  5. echo $i
  6. done
[root@svr5 ~]# vim cfor.sh
#!/bin/bash
for ((i=1;i<=5;i++))
do
   echo $i
done

4 案例4:使用while迴圈結構

4.1 問題

本案例要求編寫2個使用while迴圈的指令碼程式,分別實現以下目標:

  • 提示使用者猜測一個隨機數,直到才對為止
  • 檢測192.168.4.0/24網段,列出不線上的主機地址

4.2 方案

while迴圈屬於條件式的執行流程,會反覆判斷指定的測試條件,只要條件成立即執行固定的一組操作,直到條件變化為不成立為止。所以while迴圈的條件一般通過變數來進行控制,在迴圈體內對變數值做相應改變,以便在適當的時候退出,避免陷入死迴圈。

while迴圈的語法結構如下所示:

copytextpop-up
  1. while 條件測試
  2. do
  3. 命令序列
  4. done
  5. while :
  6. do
  7. 命令序列
  8. done
while  條件測試
do
    命令序列
done


while :
do
    命令序列
done

4.3 步驟

實現此案例需要按照如下步驟進行。

步驟一:練習while迴圈基本用法

指令碼1,無心的死迴圈指令碼:

copytextpop-up
  1. [root@svr5 ~]# vim while01.sh
  2. #!/bin/bash
  3. i=1
  4. while [ $i -le 5 ]
  5. do
  6. echo "$i"
  7. done
  8. [root@svr5 ~]# chmod +x while01.sh
  9. [root@svr5 ~]# ./while01.sh//死迴圈,需要使用Ctrl+C終止指令碼
[root@svr5 ~]# vim while01.sh
#!/bin/bash
i=1
while [ $i -le 5 ]
do
		echo "$i"
done
[root@svr5 ~]# chmod +x while01.sh
[root@svr5 ~]# ./while01.sh				//死迴圈,需要使用Ctrl+C終止指令碼

指令碼2,有效迴圈指令碼:

copytextpop-up
  1. [root@svr5 ~]# vim while02.sh
  2. #!/bin/bash
  3. i=1
  4. while [ $i -le 5 ]
  5. do
  6. echo "$i"
  7. let i++
  8. done
  9. [root@svr5 ~]# chmod +x while02.sh
  10. [root@svr5 ~]# ./while02.sh
[root@svr5 ~]# vim while02.sh
#!/bin/bash
i=1
while [ $i -le 5 ]
do
		echo "$i"
		let i++
done
[root@svr5 ~]# chmod +x while02.sh
[root@svr5 ~]# ./while02.sh

指令碼3,死迴圈的一般格式:

copytextpop-up
  1. [root@svr5 ~]# vim while03.sh
  2. #!/bin/bash
  3. while :
  4. do
  5. echo "hello world"
  6. done
  7. [root@svr5 ~]# chmod +x while03.sh
  8. [root@svr5 ~]# ./while03.sh//死迴圈,需要使用Ctrl+C終止指令碼
[root@svr5 ~]# vim while03.sh
#!/bin/bash
while :
do
		echo "hello world"
done
[root@svr5 ~]# chmod +x while03.sh
[root@svr5 ~]# ./while03.sh				//死迴圈,需要使用Ctrl+C終止指令碼

步驟二:提示使用者猜測一個隨機數,直到才對為止

使用系統自帶變數RANDOM提取隨機數(1-100),使用while :製作死迴圈。

指令碼編寫參考如下:

copytextpop-up
  1. [root@svr5 ~]# vim guess.sh
  2. #!/bin/bash
  3. num=$[RANDOM%100+1]
  4. i=0
  5. while :
  6. do
  7. read -p "隨機數1-100,你猜:" guess
  8. let i++//猜一次,計數器加1,統計猜的次數
  9. if [ $guess -eq $num ];then
  10. echo "恭喜,猜對了"
  11. echo "你猜了$i次"
  12. exit
  13. elif [ $guess -gt $num ];then
  14. echo "猜大了"
  15. else
  16. echo "猜小了"
  17. fi
  18. [root@svr5 ~]# chmod +x guess.sh
[root@svr5 ~]# 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 
[root@svr5 ~]# chmod +x guess.sh

執行指令碼並驗證結果:

copytextpop-up
  1. [root@svr5 ~]# ./guess.sh
[root@svr5 ~]# ./guess.sh

步驟三:檢測192.168.4.0/24網段,列出不線上的主機地址

1)任務需求及思路分析

要求的是“檢測192.168.4.0/24網段,列出不線上的主機地址”。

檢測目標是一個網段,其網路部分“192.168.4.”可以作為固定的字首;而主機部分包括從1~254連續的地址,所以可結合while迴圈和自增變數進行控制。

2)根據實現思路編寫指令碼

copytextpop-up
  1. [root@svr5 ~]# vim chknet.sh
  2. #!/bin/bash
  3. i=1
  4. while [ $i -le 254 ]
  5. do
  6. IP="192.168.4.$i"
  7. ping -c 3 -i 0.2 -W 1 $IP &> /dev/null
  8. if [ $? -eq 0 ] ; then
  9. echo "Host $IP is up."
  10. else
  11. echo "Host $IP is down."
  12. fi
  13. let i++
  14. done
  15. [root@svr5 ~]# chmod +x chknet.sh
[root@svr5 ~]# 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
[root@svr5 ~]# chmod +x chknet.sh 

3)測試、驗證指令碼

copytextpop-up
  1. [root@svr5 ~]# ./chknet.sh
  2. Host 192.168.4.1 is down.
  3. Host 192.168.4.2 is down.
  4. Host 192.168.4.3 is down.
  5. Host 192.168.4.4 is down.
  6. Host 192.168.4.5 is up.
  7. .. ..
  8. Host 192.168.4.250 is down.
  9. Host 192.168.4.251 is down.
  10. Host 192.168.4.252 is down.
  11. Host 192.168.4.253 is down.
  12. Host 192.168.4.254 is down.