在Shell腳本中執行使用if語句的好處是:能夠根據特定的條件(eg:判斷備份目錄是否存在)來決定是否執行某項操做,當知足不一樣的條件時執行 不一樣的操做(eg:備份目錄不存在則建立該目錄,不然跳過操做)。該文將分別從條件測試操做,if語句結構,應用示例這三個方面講解if語句在Shell 腳本中的應用。mysql
一、條件測試操做:sql
須要在Shell腳本中有選擇性地執行任務時,首先面臨的問題就是,如何設置命令執行的條件?編程
在Shell環境中,能夠根據命令執行後返回狀態值來判斷該命令是否成功執行,當返回值爲0是表示成功執行,不然(非0值)表示執行失敗。用於特定條件表達式的測試時,可使用Linux系統中提供的專用工具——test命令、vim
使用test測試命令時,能夠有如下兩種形式。bash
test 條件表達式工具
【 條件表達式 】測試
這兩種方式的做用徹底相同,但一般後一種形式更爲經常使用,也更貼近編程習慣。須要注意的是,方括號「[」或者「]」與條件表達式語句之間至少須要有一個空格進行分隔。spa
根據須要判斷的條件內容不一樣,條件操做也不一樣,最經常使用的條件主要包括文件狀態測試,比較整數值大小,比較字符串,以及同時判斷多個條件時的邏輯關係,下面將分別進行講解。如下主要採用方括號的測試形式。.net
1.一、測試文件狀態命令行
文件狀態測試是指根據給定的路徑名稱,判斷該名稱對應的是文件仍是目錄,或者判斷文件是否可讀,可寫,可執行等。根據判斷的狀態不一樣,在條件表達式中須要使用不一樣的操做選項。
-d:測試是否爲目錄(Directory)。
-e:測試目錄或文件是否存在(Exist)。
-f:測試是否爲文件(File)。
-r:測試當前用戶是否有權限讀取(Read)。
-w:測試當前用戶是否有權限寫入(Write)。
-x:測試當前用戶是否可執行(Excute)該文件。
-L:測試是否爲符號鏈接(Link)文件。
執行條件測試操做之後,經過預約義變量「$?」能夠得到測試命令的返回狀態值,從而可以判斷該條件是否成立(返回0值表示條件成立,非0值表示條件不成立)。但經過這種方式查看測試結果會比較繁瑣。
例1:測試「/etc/hosts」是不是文件,並經過「$?」變量查看返回狀態值,據此判斷測試結果。
1
2
3
|
[ -f /etc/hosts ]
echo $?
0
//返回值爲0,表示上一步測試的條件成立。
|
例2:測試「/media/cdrom/Server」及其父目錄是否存在,若是存在則顯示「YES」不然不輸出任何信息。
1
2
3
4
|
[ -e /media/cdrom/Server ] && echo
"YES"
// 無輸出表示該目錄不 存在
[ -e /media/cdrom ] && echo
"YES"
YES
|
1.二、整數值 比較:
整數值比較是指根據給定的兩個整數值,判斷第一個數是否大於、等於、小於。。。。。。第2個數,可使用的操做選項以下:
1
2
3
4
5
6
|
-eq:第一個數等於(Equal)第二個數。
-ne:第一個數不等於(Not Equal)第二個數。
-gt:第一個數大於(Greater Than)第二個數。
-lt:第一個數小於(Lesser Than)第二個數。
-le:第一個數小於或等於(Lesser or Equal)第二個數。
-ge:第一個數大於或等於(Greater or Equal)第二個數。
|
整數值比較的測試操做在Shell腳本編寫中的應用較多,如:用於判斷磁盤使用率、登陸用戶數量是否超標以及用於控制腳本語句的循環次數等。
例1:測試當前登陸到系統中的用戶數量是否小於或等於10,是則輸出」YES「。
1
2
3
4
|
who | wc -l
5
[ `who | wc -l` -le
10
] && echo 」YES"
YES
|
例2:提取出"/boot「分區的磁盤使用率,並判斷是否超過95%(爲了便於理解,操做步驟適當進行分解)
1
2
3
4
5
6
|
df -hT | grep 」/boot「 | awk
'{print $6}'
12
%
BootUsage=`df -hT | grep 」/boot
" | awk '{print $6}' | cut -d "
%" -f
1
`
echo $BootUsage
12
[ $BootUsage -gt
95
] && echo
"YES"
//無輸出表示未超標
|
1.3:字符串比較:
字符串比較能夠用於檢查用戶輸入,如:在提供交互式操做時,判斷用戶輸入的選項是否與指定的變量內容相匹配。「=」、「!=」操做選項分別表示匹配、不匹配。「-z」操做選項用於檢查字符串是否爲空。其中,「!」符號用於取反,表示相反的意思。
eg:提示用戶輸入一個文件路徑,並判斷是不是「/etc/inittab」,若是是則顯示「YES」.
1
2
3
4
|
read -p
"Location: "
FilePath
Location: /etc/inittab
[ $FilePath =
"/etc/inittab"
] && echo
"YES"
YES
|
eg: 若當前環境變量LANG的內容不是「en.US」,則輸出LANG變量的值,不然無輸出。
1
2
|
[ $LANG !=
"en.US"
] && echo $LANG
zh_CN.UTF-
8
|
eg: 使用touch命令創建一個新文件,測試其內容是否爲空,向文件中寫入內容後,再次進行測試。
1
2
3
4
5
6
|
touch zero.file
[ -z `cat zero.file` ] && echo
"yes"
yes
echo
"something"
> zero.file
[ -z `cat zero.file` ] && echo yes
//無輸出
|
1.4:邏輯測試:
邏輯測試是指同時使用的兩個(或多個)條件表達式之間的關係。用戶能夠同時測試多個條件,根據這些條件是否同時成立或者只要有其中一個條件成立等狀況,來決定採起何種操做。邏輯測試可使用的操做選項以下。
> &&:邏輯與,表示先後兩個表達式都成立時整個測試結果才爲真,不然結果爲假。在使用test命令形式進程測試時,此選項能夠改成" -a"。
> ||:邏輯或,表示先後兩個條件至少有一個成立時整個測試結果即爲真,不然結果爲假。在使用test命令形式進行測試時,此選項能夠改成"-o「。
> !:邏輯否,表示當指定的條件表達式不成立時,整個測試命令的結果爲真。
在上述邏輯測試的操做選項中,」&&「和」||「一般也用於間隔不一樣的命令操做,其做用是類似的。同時使用多個邏輯運算操做時,通常安裝從左到右的順序進行測試。
eg:測試當前的用戶是不是teacher,若不是則提示」Not teacher「。
1
2
3
4
|
echo $USER
root
[ $USER = 「teacher」 ] || echo
"Not teacher"
Not teacher
|
eg:只要"/etc/rc.d/rc.local"或者"/etc/init.d/local'中有一個是文件,則顯示"YES",不然無任何輸出。
1
2
|
[ -f /etc/rc.d/rc.local ] || [ -f /etc/init.d/rc.local ] && echo "yes「
yes
|
eg:測試」/etc/profile「文件是否有可執行權限,若確實沒有可執行權限,則提示」No x mode.「的信息。
1
2
|
[ ! -x 」/etc/profile
" ] && echo "
No x mode."
No x mode.
|
eg:若當前的用戶是root且使用的Shell程序是"/bin/bash",則顯示"YES「,不然無任何輸出。
1
2
3
4
|
echo $USER $SHELL
root /bin/bash
[ $USER = 」root
" ] && [ $SHELL = "
/bin/bash
" ] && echo "
yes"
yes
|
2:if語句的結構:
前 面內容知道了一下條件測試操做,實際上使用"&&「和」||「邏輯測試能夠完成簡單的判斷並執行相應的操做,可是當須要選擇執行的命令語 句較多時,再使用這種方式將使命令行語句顯得很複雜,難以閱讀。而使用if語句,則能夠更好地體現有選擇性執行的程序結構,使得井井有條,清晰易懂。
if語句的選擇結構由易到難能夠分爲三種類型,分別適用於不一樣的應用場合。
2.一、單分支的if語句。
單分支的if語句是最簡單的選擇結構,這種結果只判斷指定的條件,當」條件成立「時執行相應的操做,不然不作任何操做。單分支使用的語句格式以下。
if 條件測試命令
then
命令序列
fi
在上述語句中,首先經過判斷條件測試命令的返回狀態值是否爲0(條件成立),若是是,則執行then後面的一條或多臺可執行語句(命令序列),一直到fi爲止表示結束,若是條件測試命令的返回值不爲0(條件不成立),則直接去執行fi後面的語句。
2.二、雙分支的if語句。
雙分支的if語句使用了兩路命令操做,在」條件成立‘、「條件不成立時分別執行不一樣的命令序列」。雙分支使用的語句格式以下:
if 條件測試命令
then
命令序列1;
else
命令序列2;
fi
在 上述語句中,首先經過if判斷條件測試命令的返回狀態值是否爲0(條件成立),若是是,則執行then後面的一條或多條可執行語句(命令序列1),而後跳 轉至fi結束判斷,若是條件測試命令的返回狀態值不爲0(條件不成立),則執行else後面的語句,一直到fi表示結束。
2.三、多分支的if語句。
因爲if語句能夠根據條件測試命令的兩種狀態分別進行操做,因此可以嵌套使用,進行屢次判斷(如:首先判斷某學生的得分是否及格,如及格則再次判斷是否高於90分。。。)多重分支使用的語句格式以下。
if 條件測試命令1
then
命令序列1
elif 條件測試命令2
then
命令序列2
else
命令序列3
fi
上面的語法格式中只嵌套了一個elif語句,實際上if語句中能夠嵌套多個elif語句。if語句的嵌套在編寫Shell腳本時並不經常使用,由於多重嵌套容易使程序結構變得複雜。須要使用多重分支程序結構時,更多的是使用case語句來實現。
eg:檢查"/var/log/messages'文件是否存在,若存在則統計文件內容的行數並輸出,不然不作任何操做。
1
2
3
4
5
6
7
|
vi chklog.sh
#!/bin/bash
LogFile=
"/var/log/messages"
if
[ -f $LogFile ] ; then
wc -l $LogFile
fi
sh chklog.sh
//sh是bash的符號連接
|
eg:提示用戶指定備份目錄的路徑,若目錄已存在則顯示提示信息後跳過,不然顯示相應提示信息後建立該目錄。
1
2
3
4
5
6
7
8
9
|
[root@master ~]# vi mkbak.sh
#!/bin/bash
read -p
"What is your directory:"
Bakdir
if
[ -d $Bakdir ] ; then
echo
"$Bakdir already exist."
else
echo
"Bakdir is not exist,will make it."
mkdir $Bakdir
fi
|
eg:統計當前登陸到系統中的用戶數量,並判斷是否超過三個,如果則顯示實際數量並給出警告信息,不然列出登陸的用戶帳號成名及所在終端。
1
2
3
4
5
6
7
8
9
|
[root@localhost ~]# vim chkuser.sh
#!/bin/bash
UserNum=`who |wc -l`
if
[ $UserNum -gt
3
] ; then
echo
"Alert , too many login users ( Total: $UserNum )."
else
echo
"Login users:"
who | awk
'{print $1,$2}'
fi
|
eg:檢 查portmap進程是否已經存在,若已經存在則輸出「portmap service is running」;不然檢查是否存在「/etc/rc.d/init.d/portmap」可執行腳本,存在則啓動portmap服務,不然提示「no portmap script file.」。
1
2
3
4
5
6
7
8
9
10
11
|
[root@localhost ~]# vim chkportmap.sh
#!/bin/bash
pgrep portmap &> /dev/
null
if
[ $? -eq
0
]; then
echo
"protmap service is running."
elif
[ -x
"/etc/rc.d/init.d/portmap"
]; then
service portmap start
else
echo
"no portmap script file."
fi
|
eg:每隔五分鐘監測一次mysqld服務程序的運行狀態,若發現mysqld進程已終止,則在「/var/log/messages」文件中追加寫入日誌信息(包括當時時間),並重啓mysqld服務,不然不進程任何操做。
1
2
3
4
5
6
7
8
9
10
|
vi chkmysql.sh
#!/bin/bash
service mysqld status &> /dev/
null
if
[ $? -ne
0
]; then
echo
"At time:`date`:Mysql Server is down."
>> /
var
/log/messages
service mysqld restart
fi
chmod u+x chkmysql.sh
crontab -e
*/
5
* * * * /root/chkmysql.sh
|
三、使用for魂環語句
在Shell腳本中使用for循環語句時,能夠爲變量設置一個取值列表,每次讀取列表中不一樣的變量值並執行相關命令操做,變量值用完之後則退出循環。Shell中的for語句不須要執行條件判斷,其使用變量的取值來自於預先設置的值列表。
for語句結構:
for 變量名 in 取值列表
do
命令序列
done
在 上述語句中,使用in關鍵字爲用戶自定義變量設置了一個取值列表(以空格分隔的多個值),for語句第一次執行時首先將列表中的第一個取值賦給該變量。然 後執行do後邊的命令序列;而後再將列表中的第二個取值賦給該變量,而後執行do後邊的命令序列......如此循環,直到取值列表中的全部值都已經用 完,最後將跳至done語句,表示結束循環。
for語句示例:
eg:依次輸出三條文件信息,包括一天中的"Morning"、"Noon"、"Evening"字串。
1
2
3
4
5
6
|
vi showday.sh
#!/bin/bash
for
TM
in
"Morning"
"Noon"
"Evening"
do
echo
"The $TM of the day."
done
|
eg:對於使用「/bin/bash」登陸Shell的系統用戶,檢查他們在"/opt"目錄中擁有的子目錄或文件數量,若是超過100個,則列出具體數量及對應的用戶帳號。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
vi chkfileown.sh
#!/bin/bash
DIR=
"/opt"
//設置檢查的目標目錄
LMT=
100
//設置文件數量的限制值
ValidUsers=`grep
"/bin/bash"
/etc/passwd | cut -d
":"
-f
1
`
//找出使用bash的系統用戶列表
for
UserName
in
$ValidUsers
do
Num=`find $DIR -user $UserName | wc -l`
//統計每一個用戶擁有的文件數
if
[ $Num -gt $LMT ] ; then
echo
"$UserName have $Num files."
fi
done
sh chkfileown.sh
root have
20998
files
|
四、使用while循環語句
在 Shell腳本中使用while循環語句時,將能夠根據 特定的條件重複執行一個命令列表,直到該條件再也不知足時爲至。除非有特別須要,不然在腳本程序中應該是避免出現無限循環執行命令的狀況,由於若沒法跳出循 環的話,後邊的某些操做將沒法執行。爲了控制循環次數,一般會在執行的命令序列中包含修改測試條件的語句,當循環達到必定次數後,測試將再也不成立,從而可 以結束循環。
while語句的結構:
while 條件測試命令
do
命令序列
done
在 上述語句中,首先經過while判斷條件測試命令的返回狀態值是否爲0(條件成立),若是是,則執行do後邊的命令序列,而後返回到while再次進行條 件測試並判斷返回狀態值,若是條件仍然成立,則繼續執行do後邊的命令序列,而後返回到while重複條件測試......如此循環,直到所測試的條件不 成立時,跳轉到done語句,表示結束循環。
使用while循環語句時,有兩個特殊的條件測試返回值,即「true」 (真)、"false"(假)。使用「true」做爲測試條件時,條件將永遠成立,循環體內的語句將無限次執行下去,反之使用「false」則條件永遠不 成立,循環體內的語句將不會被執行,這兩個特殊值也能夠用在if語句的條件測試中。
while語句應用示例:
while語句能夠用於須要重複操做的循環系統管理任務,並可以經過設置循環條件來靈活的實現各類管理任務。
eg:由用戶從鍵盤輸入一個大於1的整數(如50),並計算從1到該數之間各整數的和。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
[root@localhost ~]# vim sumint.sh
#!/bin/bash
read -p
"Input a number (>1):"
UP
i=
1
Sum=
0
while
[ $i -le $UP ]
do
Sum=`expr $Sum + $i`
i=`expr $i +
1
`
done
echo
"The sum of 1-$UP is : $Sum"
[root@localhost ~]# sh sumint.sh
Input a number (>
1
):
50
The sum of
1
-
50
is
:
1275
|
eg:批量添加20個系統用戶帳號,用戶名稱依次爲「stu1」、"stu2"、「stu3」、.......「stu20」,各用戶的初始密碼均設置爲「123456」。
1
2
3
4
5
6
7
8
9
|
[root@localhost ~]# vim add20users.sh
#!/bin/bash
i=
1
while
[ $i -le
20
]
do
useradd stu$i
echo
"123456"
| passwd --stdin stu$i &> /dev/
null
i=`expr $i +
1
`
done
|
sh add20users.sh
eg:編寫一個批量刪除用戶的腳本程序,將上面添加的20個用戶刪除。
1
2
3
4
5
6
7
8
|
[root@localhost ~]# vim del20users.sh
#!/bin/bash
i=
1
while
[ $i -le
20
]
do
userdel -r stu$i
i=`expr $i +
1
`
done
|
再次查看: cat /etc/passwd 就會發現那些用戶再也不存在。
說了if、for 、while、語句後,就能夠編寫通常的系統管理任務腳本了,記得多多練習!其實除了這些Shell腳本語句外,還有好多好多,如:
case分支語句,until循環、shift移位,以及break和continue循環中斷語句。你們能夠查詢!後續有時間我也會推出~