目錄
一. 條件測試操作
1. 文件測試
2. 整數值比較?
3. 字符串比較?
4. 邏輯測試
?二. if 條件語句
1. if 語句的結構
(1) 單分支 if 語句
(2) 雙分支 if 語句?
(3) 多分支 if 語句
2. if 語句應用示例
(1) 單分支 if 語句應用
(2) 雙分支 if 語句應用
(3) 多分支 if 語句應用
三. case 分支語句
1. case 語句的結構?
2. case 語句應用示例
(1) 檢查用戶輸入的字符類型
(2) 編寫系統服務腳本
Shell編程作為 Linux 系統管理的重要組成部分,其強大的腳本處理能力為自動化任務提供了極大便利。在 Shell腳本編寫中,條件語句是不可或缺的邏輯控制結構,它們使得腳本能夠根據不同的條件執行相應的操作,從而實現智能化和高效化。
一. 條件測試操作
要使 shell?腳本程序具備一定的“智能”,面臨的第一個問題就是如何區分不同的情況以確定執行何種操作。
如當磁盤使用率超過 95%時,發送告警信息;當備份目錄不存在時,能夠自動創建;當源碼編譯程序時,若配置失敗則不再繼續安裝等。
Shel1l環境根據命令執行后的返回狀態值($?)來判斷是否執行成功,當返回值為 0 時表示成功,否則(非 0?值)表示失敗或異常。
使用 test 測試命令時,包括以下兩種形式
test? 條件表達式 |
或 |
[條件表達式] |
兩種方式的作用完全相同,但通常后一種形式更為常用,也更貼近編程習慣。需要注意的是,方括號“[”或“]”與條件表達式之間需要至少一個空格進行分隔。
根據需要測試的條件類別不同,條件表達式也不同。比較常用的條件操作包括文件測試、整數值比較、字符串比較,以及針對多個條件的邏輯測試
1. 文件測試
文件測試指的是根據給定的路徑名稱,判斷對應的是文件還是目錄,或者判斷文件是否可讀、可寫、可執行等。文件測試的常見操作選項
-d | 測試是否為目錄(Directory) |
-e | 測試目錄或文件是否存在(Exist) |
-f | 測試是否為文件(File) |
-r | 測試當前用戶是否有權限讀取(Read) |
-w | 測試當前用戶是否有權限寫入(write) |
-x | 測試是否設置有可執行(Excute)權限 |
執行條件測試操作以后,通過預定義變量$?可以獲得測試命令的返回狀態值,從而判斷該條件是否成立?
如果返回值$?為 0,表示存在此目錄,否則表示不存在或者雖然存在但不是目錄。
?若測試的條件不成立,則測試操作的返回值將不為 0(通常為 1)。
?
通過査看變量$?的值可以判斷前一步的條件測試結果,但是操作比較煩瑣,輸出結果也并不是很直觀。為了更直觀地査看測試結果,可以結合命令分隔符“&&”和 echo 命令一起使用,當條件成立時直接輸出“YES”。
“&&”符號表示“而且”的關系,只有當前面的命令執行成功后才會執行后面的命令。否則后面的命令將會被忽略。
無輸出表示該目錄不存在
輸出"YES"表示該目錄存在
2. 整數值比較?
整數值比較指的是根據給定的兩個整數值,判斷第一個數與第二個數的關系,如是否大于、等于、小于第二個數。整數值比較的常用操作選項如下,使用時將操作選項放在要比較的兩個整數之間。
-eq: 第一個數等于(Equal)第二個數。 |
-ne: 第一個數不等于(Not Equal)第二個數。 |
-gt: 第一個數大于(Greater Than)第二個數。 |
-lt: 第一個數小于(Lesser Than)第二個數。 |
-le: 第一個數小于或等于(Lesser or Equal)第二個數。 |
-ge: 第一個數大于或等于(Greater or Equal)第二個數。 |
整數值比較在 shell 腳本編寫中的應用較多。來判斷已登錄用戶數量、開啟進程數、磁盤使用率是否超標,以及軟件版本號是否符合要求等。實際使用時,往往會通過變量引用、命令替換等方式來獲取一個數值。
若要判斷當前已登錄的用戶數,當超過二個時輸出“Too many.”,已登錄用戶數可通過“who | wc -l”命令獲得,可以執行以下操作
已知當前登錄數為5 當當前用戶登錄超過2個時顯示Too many
若要判斷物理內存(Mem)當前的磁盤緩存(buff/cache)大小,當低于 1024MB 時輸出具體數值,“free -m”命令表示以 MB 為單位輸出內存信息,提取的空閑內存數值通過命令替換賦值給變量 FreeCC,可以執行以下操作。
3. 字符串比較?
字符串比較通常用來檢査用戶輸入、系統環境等是否滿足條件,在提供交互式操作的 shell?腳本中,也可用來判斷用戶輸入的位置參數是否符合要求。字符串比較的常用操作選項
=:第一個字符串與第二個字符串相同。 |
!=:第一個字符串與第二個字符串不相同,其中“!”符號表示取反 |
-z:檢查字符串是否為空(Zero),對于未定義或賦予空值的變量將視為空串。 |
若要判斷當前系統的語言環境,當發現不是“en.us”時輸出提示信息“Not en.us”,可以執行以下操作
查看語言環境 測試結果不等于?
在 Shell?腳本應用中,經常需要用戶輸入“yes”或“no”來確認某個任務。以下操作展示了確認交互的簡單過程,當然,實際使用時還會根據變量“ACK”的取值分別執行進一步的操作。
4. 邏輯測試
邏輯測試指的是判斷兩個或多個條件之間的依賴關系。當系統任務取決于多個不同的條件時,根據這些條件是否同時成立或者只要有其中一個成立等情況,需要有一個測試的過程。使用時放在不同的測試語句或命令之間。
&& | 邏輯與,表示“而且”,只有當前后兩個條件都成立時,整個測試命令的返回值才為 0(結果成立)。使用 test 命令測試時,“&&”可改為“-a” |
| | | 邏輯或,表示“或者”,只要前后兩個條件中有一個成立,整個測試命令的返回值即為 0(結果成立)。使用 test 命令測試時,“||”可改為“-o” |
! | 邏輯否,表示“不”,只有當指定的條件不成立時,整個測試命令的返回值才為 0(結果成立) |
“&&”和“||”通常也用于間隔不同的命令操作,其作用是相似的。
若要判斷當前 Linux 系統的內核版本是否大于 3.4,內核版本號通過 uname 和 awk 命令獲得。,可以執行以下操作。
查看內核版本號? 主辦版號? 次版本號? 是否符合要求? ? ? ? 不符合不會給任何信息
?二. if 條件語句
使用專用的 if 條件語句,可以更好地整理腳本結構,使得層次分明,清晰易懂。
1. if 語句的結構
在 shell?腳本應用中,if 語句是最為常用的一種流程控制方式,用來根據特定的條件測試結果,分別執行不同的操作(如果.…那么.…)。根據不同的復雜程度,if 語句的選擇結構可以分為三種基本類型,適用于不同的應用場合。
(1) 單分支 if 語句
if 語句的“分支”指的是不同測試結果所對應的執行語句(一條或多條)。對于單分支的選擇結構,只有在“條件成立”時才會執行相應的代碼,否則不執行任何操作。
語法格式
if 條件測試操作
then命令序列
fi
條件測試操作既可以是“[條件表達式]"語句,也可以是其他可執行的命令語句;命令序列指的是一條或多條可執行的命令行,也包括嵌套使用的 if 語句或其他流程控制語句。
單分支 if 語句的執行流程:首先判斷條件測試操作的結果,如果返回值為 0,表示條件成立,執行then 后面的命令序列,一直到遇見 fi 結束判斷為止,繼續執行其他腳本代碼;如果返回值不為 0,則忽略 then 后面的命令序列,直接跳至 fi 行以后執行其他腳本代碼
(2) 雙分支 if 語句?
對于雙分支的選擇結構,要求針對“條件成立”“條件不成立”兩種情況分別執行不同的操作。
語法格式
if 條件測試操作
then命令序列 1
else命令序列 2
fi
雙分支 if 語句的執行流程:首先判斷條件測試操作的結果,如果條件成立,則執行 then 后面的命令序列 1,忽略 else 及后面的命令序列 2,直到遇見 fi 結束判斷;如果條件不成立,則忽略 then 及后面的命令序列 1,直接跳至 else 后面的命令序列 2 并執行,直到遇見 fi 結束判斷
(3) 多分支 if 語句
由于 if 語句可以根據測試結果的成立、不成立分別執行操作,所以能夠嵌套使用,進行多次判斷。
語法格式
if 條件測試操作 1
then命令序列 1
elif 條件測試操作 2
then命令序列 2
else命令序列 3
fi
語句結構中只嵌套了一個 elif 語句作為示例,實際上可以嵌套多個。if 語句的嵌套在編寫Shel1 腳本時并不常用,因為多重嵌套容易使程序結構變得復雜。當確實需要使用多分支的程序結構時,可以采用 case 語句更加方便
多分支 if 語句的執行流程:首先判斷條件測試操作1 的結果,如果條件 1 成立,則執行命令序列1,然后跳至 fi 結束判斷;如果條件 1 不成立,則繼續判斷條件測試操作 2 的結果,如果條件 2 成立,則執行命令序列 2,然后跳至 fi 結束判斷……如果所有的條件都不滿足,則執行 else 后面的命令序列n,直到遇見 fi 結束判斷
2. if 語句應用示例
(1) 單分支 if 語句應用
多 Linux 用戶習慣上將光盤設備掛載到/media/cdrom 目錄下,但 Linux 系統默認并沒有建立此目錄。若需要在 shel1 腳本中執行掛載光盤的操作,建議先判斷掛載點目錄是否存在,若不存在則新建此目錄。
?
有些特權命令操作要求以 root用戶執行,如果當前用戶不是 root,那么再執行這些命令就沒有必要(肯定會失敗)。針對這種情況,在腳本中可以先判斷當前用戶是不是root,如果不是則報錯并執行“exit 1”命令退出腳本(1 表示退出后的返回狀態值),而不再執行其他代碼。
????????????????
?
?
當 root 用戶執行 chkifroot.sh 腳本時,由于“非 root 用戶”的條件不成立,所以 if 語句不執行任何操作,正常執行 fi 之后的腳本代碼。?
[root@localhost ~l# /opt/aaa.sh
….//省略部分內容
Device Boot Start End Blocks Id System
/dev/sda1 *2048 40894463 20446208 83 Linux
/dev/sda2 40894464 41943039 524288 82 Linux swap / Solaris
(2) 雙分支 if 語句應用
雙分支 if 語句只是在單分支的基礎上針對“條件不成立”的情況執行另一種操作,而不是“坐視不管”地不執行任何操作。
若要編寫一個連通性測試腳本 bbb.sh,通過位置參數$1 提供目標主機地址,然后根據 ping 檢測結果給出相應的提示,可以參考以下操作過程
?
腳本代碼中,為了提高 ping 命令的測試效率,使用了“-c’”“-i”“-w”選項,分別指定只發送三個測試包、間隔 0.2 秒、超時 3 秒。另外,通過“&>/dev/null”屏蔽了 ping 命令執行過程的輸出信息。
通過 she11 腳本檢査 vsftpd 服務是否運行,如果已經運行則列出其監聽地址、PID 號,否則輸出提示“警告:vsftpd 服務不可用!”。其中,pgrep 命令的“-x”選項表示查找時使用精確匹配
?
?
(3) 多分支 if 語句應用
與單分支、雙分支 if 語句相比,多分支 if 語句的結構能夠根據多個互斥的條件分別執行不同的操作,實際上等同于嵌套使用的 if 語句
若要編寫一個成績分檔的腳本 ddd.sh,根據輸入的考試分數不同來區分優秀、合格、不合格三擋,可以參考以下操作過程
?
三. case 分支語句
1. case 語句的結構?
case 語句主要適用于以下情況:某個變量存在多種取值,需要對其中的每一種取值分別執行不同的命令序列。這種情況與多分支的 if 語句非常相似,只不過 if 語句需要判斷多個不同的條件,而 case語句只是判斷一個變量的不同取值。
語法結構
case 變量值 in
模式 1)命令序列 1;;
模式 2)命令序列 2
;;...
* )默認命令序列
esac
在上述語句結構中,關鍵字 case 后面跟的是“變量值”,即“$變量名”。整個分支結構包括在case..esac 之間,中間的模式 1、模式 2、…、*對應為變量的不同取值(程序期望的取值),其中*作為通配符,可匹配任意值。
case語句的執行流程:首先使用“變量值”與模式1進行比較,若取值相同則執行模式1?后的命令序列,直到遇見雙分號“;;”后跳轉至 esac,表示結束分支;若與模式 1 不相匹配,則繼續與模式 2進行比較,若取值相同則執行模式 2后的命令序列,直到遇見雙分號“;;”后跳轉至 esac,表示結束分支.…依此類推,若找不到任何匹配的值,則執行默認模式“*)”后的命令序列,直到遇見 esac 后結束分支
使用 case 分支語句時,有幾個值得注意的特點
case 行尾必須為單詞“in”,每一模式必須以右括號“)”結束。 |
雙分號“;;”表示命令序列的結束。 |
模式字符串中,可以用方括號表示一個連續的范圍,如“[0-9]”;還可以用豎杠符號“|”表示或,如“A|B” |
最后的“*)”表示默認模式,其中的*相當于通配符。 |
2. case 語句應用示例
(1) 檢查用戶輸入的字符類型
提示用戶從鍵盤輸入一個字符,通過 case 語句判斷該字符是否為字母、數字或者其他控制字符,并給出相應的提示信息。
?
(2) 編寫系統服務腳本
編寫一個名為 hhh.sh的系統服務腳本,通過位置變量$1 指定的 start、stop、restart、status控制參數,分別用來啟動、停止、重啟 sleep 進程,以及査看 sleep 進程的狀態。其中,命令 sleep 用來暫停指定秒數的時間,這里僅用做測試,在實際運維工作中應將 sleep 改為相應后臺服務的控制命令序列。
?
在 Linux 系統中,源碼軟件包編譯安裝后提供的服務控制腳本使用了 case 分支語句;也有一些源碼包沒有提供服務控制腳本,編譯安裝后可參照上例自行編寫服務控制腳本。平時控制各種系統服務時,供的 start、stop、restart 等位置參數,正是由 case 語句結構來識別并完成相應操作的。
若要將 hhh.sh?服務交給 systemd 來管理,還需要在/lib/systemd/system 目錄下添加相應的myprog.service 配置文件。