OSPF 、 傳輸層 、 ACL
1.1 問題
本案例要求參考PPT上的示例,分別練習以下條件測試操作:
- 字串匹配
- 比較整數值的大小
- 識別檔案/目錄的狀態
- 多個條件/操作的邏輯組合
1.2 步驟
實現此案例需要按照如下步驟進行。
步驟一:條件測試的基本用法
1)語法格式
使用“test 表示式”或者[ 表示式 ]都可以,表示式兩邊至少要留一個空格。
條件測試操作本身不顯示出任何資訊。測試的條件是否成立主要體現在命令執行後的返回狀態(即 $?),所以可以在測試後檢視變數$?的值來做出判斷,或者結合&&、||等邏輯操作顯示出結果(或作其他操作) 。
步驟二:字串測試
1)== 比較兩個字串是否相同
檢查當前使用者是否為root。
當root使用者執行時:
copytextpop-up
- [root@svr5 ~]# [ $USER == "root" ] //測試
- [root@svr5 ~]# echo $?//檢視結果0為對,非0為錯
[root@svr5 ~]# [ $USER == "root" ] //測試 [root@svr5 ~]# echo $? //檢視結果0為對,非0為錯
當普通使用者執行時:
copytextpop-up
- [zengye@svr5 ~]$ [ $USER == "root" ]
- [zengye@svr5 ~]$ echo $? //檢視結果0為對,非0為錯
[zengye@svr5 ~]$ [ $USER == "root" ] [zengye@svr5 ~]$ echo $? //檢視結果0為對,非0為錯
2)!= 比較兩個字串是否不相同
當普通使用者執行時:
copytextpop-up
- [zengye@svr5 ~]$ [ $USER != "root" ]
[zengye@svr5 ~]$ [ $USER != "root" ]
當root使用者執行時:
copytextpop-up
- [root@svr5 ~]# [ $USER != "root" ]
[root@svr5 ~]# [ $USER != "root" ]
3)一行執行多條命令的情況
copytextpop-up
- # A && B //僅當A命令執行成功,才執行B命令
- # A || B//僅當A命令執行失敗,才執行B命令
- # A ; B//執行A命令後執行B命令,兩者沒有邏輯關係
- # A && B || C //思考?
# A && B //僅當A命令執行成功,才執行B命令 # A || B //僅當A命令執行失敗,才執行B命令 # A ; B //執行A命令後執行B命令,兩者沒有邏輯關係 # A && B || C //思考?
4) -z 檢查變數的值是否未設定(空值)
copytextpop-up
- [root@svr5 ~]# var1="nb" ; var2=""
- [root@svr5 ~]# [ -z "$var1" ] && echo "空值" || echo "非空值"
- 非空值
- [root@svr5 ~]# [ -z $var2 ] && echo "空值" || echo "非空值"
- 空值 //變數var2已設定,但無任何值,視為空
- [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
- [root@svr5 ~]# A=20.4
- [root@svr5 ~]# [ $A -gt 10 ] //不支援小數比較
- -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
- [root@svr5 ~]# X=20 //定義一個測試變數
- [root@svr5 ~]# [ $X -eq 20 ] && echo "相等" || echo "不相等"
- 相等
- [root@svr5 ~]# [ $X -eq 30 ] && echo "相等" || echo "不相等"
- 不相等
[root@svr5 ~]# X=20 //定義一個測試變數 [root@svr5 ~]# [ $X -eq 20 ] && echo "相等" || echo "不相等" 相等 [root@svr5 ~]# [ $X -eq 30 ] && echo "相等" || echo "不相等" 不相等
2)-ne 比較兩個數是否不相等。
copytextpop-up
- [root@svr5 ~]# X=20 //定義一個測試變數
- [root@svr5 ~]# [ $X -ne 20 ] && echo "不等於" || echo "等於"
- 等於
- [root@svr5 ~]# [ $X -ne 30 ] && echo "不等於" || echo "等於"
- 不等於
[root@svr5 ~]# X=20 //定義一個測試變數 [root@svr5 ~]# [ $X -ne 20 ] && echo "不等於" || echo "等於" 等於 [root@svr5 ~]# [ $X -ne 30 ] && echo "不等於" || echo "等於" 不等於
3)-gt 比較前面的整數是否大於後面的整數。
copytextpop-up
- [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 "否"
- 否
[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
- [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 "否"
- 否
[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
- [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 "否"
- 小於
[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
- [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 "否"
- 小於或等於
[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
- [root@svr5 ~]# who | wc -l //確認已登入的使用者數
- 2
- [root@svr5 ~]# N=$(who | wc -l) //賦值給變數N
- [root@svr5 ~]# [ $N -ge 3 ] && echo "超過了" || echo "沒超過"
- 沒超過
[root@svr5 ~]# who | wc -l //確認已登入的使用者數 2 [root@svr5 ~]# N=$(who | wc -l) //賦值給變數N [root@svr5 ~]# [ $N -ge 3 ] && echo "超過了" || echo "沒超過" 沒超過
上述賦值給變數N及與3比較的操作,可以簡化為如下形式:
copytextpop-up
- [root@svr5 ~]# [ $(who | wc -l) -ge 3 ] && echo "超過了" || echo "沒超過"
- 沒超過
[root@svr5 ~]# [ $(who | wc -l) -ge 3 ] && echo "超過了" || echo "沒超過" 沒超過
步驟四:識別檔案/目錄的狀態
1)-e 判斷物件是否存在(不管是目錄還是檔案)
copytextpop-up
- [root@svr5 ~]# [ -e "/usr/" ] && echo "存在" || echo "不存在"
- 存在
- [root@svr5 ~]# [ -e "/etc/fstab" ] && echo "存在" || echo "不存在"
- 存在
- [root@svr5 ~]# [ -e "/home/nooby" ] && echo "存在" || echo "不存在"
- 不存在
[root@svr5 ~]# [ -e "/usr/" ] && echo "存在" || echo "不存在" 存在 [root@svr5 ~]# [ -e "/etc/fstab" ] && echo "存在" || echo "不存在" 存在 [root@svr5 ~]# [ -e "/home/nooby" ] && echo "存在" || echo "不存在" 不存在
2)-d 判斷物件是否為目錄(存在且是目錄)
copytextpop-up
- [root@svr5 ~]# [ -d "/usr/" ] && echo "是目錄" || echo "不是目錄"
- 是目錄
- [root@svr5 ~]# [ -d "/etc/fstab" ] && echo "是目錄" || echo "不是目錄"
- 不是目錄
- [root@svr5 ~]# [ -d "/home/nooby" ] && echo "是目錄" || echo "不是目錄"
- 不是目錄
[root@svr5 ~]# [ -d "/usr/" ] && echo "是目錄" || echo "不是目錄" 是目錄 [root@svr5 ~]# [ -d "/etc/fstab" ] && echo "是目錄" || echo "不是目錄" 不是目錄 [root@svr5 ~]# [ -d "/home/nooby" ] && echo "是目錄" || echo "不是目錄" 不是目錄
3)-f 判斷物件是否為檔案(存在且是檔案)
copytextpop-up
- [root@svr5 ~]# [ -f "/usr/" ] && echo "是檔案" || echo "不是檔案"
- 不是檔案
- [root@svr5 ~]# [ -f "/etc/fstab" ] && echo "是檔案" || echo "不是檔案"
- 是檔案
- [root@svr5 ~]# [ -f "/home/nooby" ] && echo "是檔案" || echo "不是檔案"
- 不是檔案
[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
- [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測試結果仍然可讀
[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
- [zengye@svr5 ~]$ [ -r "/tmp/test.txt" ] && echo "可讀" || echo "不可讀"
- 不可讀
[zengye@svr5 ~]$ [ -r "/tmp/test.txt" ] && echo "可讀" || echo "不可讀" 不可讀
5)-w 判斷物件是否可寫
此測試同樣對root使用者無效,無論檔案是否設定w許可權,root都可寫:
copytextpop-up
- [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 "不可寫"
- 可寫
[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
- [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 "不可寫"
- 不可寫
[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
- [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 "不可執行"
- 可執行
[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
- [root@svr5 ~]# X=20 //設定X變數的值為20
- [root@svr5 ~]# [ $X -gt 10 ] && [ $X -lt 30 ] && echo "YES"
- YES
[root@svr5 ~]# X=20 //設定X變數的值為20 [root@svr5 ~]# [ $X -gt 10 ] && [ $X -lt 30 ] && echo "YES" YES
2)||,邏輯或
只要其中一個條件成立,則整個測試結果為真。
只要/tmp/、/var/spool/目錄中有一個可寫,則條件成立:
copytextpop-up
- [root@svr5 ~]# [ -w "/tmp/" ] || [ -w "/var/spool/" ] && echo "OK"
- 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
- if 條件測試
- then
- 命令序列
- fi
if 條件測試 then 命令序列 fi
if雙分支的語法組成:
copytextpop-up
- if 條件測試
- then
- 命令序列1
- else
- 命令序列2
- fi
if 條件測試 then 命令序列1 else 命令序列2 fi
if多分支的語法組成:
copytextpop-up
- if 條件測試1 ;then
- 命令序列1
- elif 條件測試2 ;then
- 命令序列2
- else
- 命令序列n
- fi
if 條件測試1 ;then 命令序列1 elif 條件測試2 ;then 命令序列2 else 命令序列n fi
2.3 步驟
實現此案例需要按照如下步驟進行。
步驟一:檢測/media/cdrom目錄,若不存在則建立
1)編寫指令碼如下:
copytextpop-up
- [root@svr5 ~]# vim mountdir.sh
- #!/bin/bash
- dir="/media/cdrom/"
- if [ ! -d $dir ]
- then
- mkdir -p $dir
- fi
- [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
- [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
[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
- [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
- [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
[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
- [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
[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
- [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.
[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
- [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
[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
- [root@svr5 ~]# ./grade.sh
- 請輸入積分(0-100):74
- 74 分,爐火純青
- [root@svr5 ~]# ./grade.sh
- 請輸入分數(0-100):68
- 68 分,略有小成
- [root@svr5 ~]# ./grade.sh
- 請輸入分數(0-100):87
- 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
- for 變數名 in 值列表
- do
- 命令序列
- done
- for 變數名 in {1..5}
- do
- 命令序列
- done
- for 變數名 in `seq 5`
- do
- 命令序列
- done
- for 變數名 in `ls /etc/*.conf`
- do
- 命令序列
- 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
- [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
[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
- [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
[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
- [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
[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
- [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
[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
- … …
- [root@svr5 ~]# ./chkhosts.sh
- Host 192.168.4.5 is up.
- Host 192.168.4.6 is down
- … …
… … [root@svr5 ~]# ./chkhosts.sh Host 192.168.4.5 is up. Host 192.168.4.6 is down … …
步驟三:建立賬戶的案例
建立users.txt,寫入無規律的賬戶名稱,最後使用for迴圈讀取該檔案,批量建立賬戶並設定密碼。
copytextpop-up
- [root@svr5 ~]# vim addfor.sh
- #!/bin/bash
- for i in `cat /root/user.txt`
- do
- useradd $i
- echo 123456 | passwd --stdin $i
- 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
- [root@svr5 ~]# vim cfor.sh
- #!/bin/bash
- for ((i=1;i<=5;i++))
- do
- echo $i
- 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
- while 條件測試
- do
- 命令序列
- done
- while :
- do
- 命令序列
- done
while 條件測試 do 命令序列 done while : do 命令序列 done
4.3 步驟
實現此案例需要按照如下步驟進行。
步驟一:練習while迴圈基本用法
指令碼1,無心的死迴圈指令碼:
copytextpop-up
- [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終止指令碼
[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
- [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
[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
- [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終止指令碼
[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
- [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
[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
- [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
- [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
[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
- [root@svr5 ~]# ./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.