歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux基礎 >> 關於Linux >> linux中的shell腳本管理(二)

linux中的shell腳本管理(二)

日期:2017/3/3 15:56:49   编辑:關於Linux

在Shell腳本中執行使用if語句的好處是:可以根據特定的條件(eg:判斷備份目錄是否存在)來決定是否執行某項操作,當滿足不同的條件時執行不同的操作(eg:備份目錄不存在則創建該目錄,否則跳過操作)。該文將分別從條件測試操作,if語句結構,應用示例這三個方面講解if語句在Shell腳本中的應用。

1、條件測試操作:

需要在Shell腳本中有選擇性地執行任務時,首先面臨的問題就是,如何設置命令執行的條件?

在Shell環境中,可以根據命令執行後返回狀態值來判斷該命令是否成功執行,當返回值為0是表示成功執行,否則(非0值)表示執行失敗。用於特定條件表達式的測試時,可以使用Linux系統中提供的專用工具——test命令、

使用test測試命令時,可以有以下兩種形式。

test 條件表達式

【 條件表達式 】

這兩種方式的作用完全相同,但通常後一種形式更為常用,也更貼近編程習慣。需要注意的是,方括號“[”或者“]”與條件表達式語句之間至少需要有一個空格進行分隔。

根據需要判斷的條件內容不同,條件操作也不同,最常用的條件主要包括文件狀態測試,比較整數值大小,比較字符串,以及同時判斷多個條件時的邏輯關系,下面將分別進行講解。以下主要采用方括號的測試形式。

1.1、測試文件狀態

文件狀態測試是指根據給定的路徑名稱,判斷該名稱對應的是文件還是目錄,或者判斷文件是否可讀,可寫,可執行等。根據判斷的狀態不同,在條件表達式中需要使用不同的操作選項。

-d:測試是否為目錄(Directory)。

-e:測試目錄或文件是否存在(Exist)。

-f:測試是否為文件(File)。

-r:測試當前用戶是否有權限讀取(Read)。

-w:測試當前用戶是否有權限寫入(Write)。

-x:測試當前用戶是否可執行(Excute)該文件。

-L:測試是否為符號連接(Link)文件。

執行條件測試操作以後,通過預定義變量“$?”可以獲得測試命令的返回狀態值,從而能夠判斷該條件是否成立(返回0值表示條件成立,非0值表示條件不成立)。但通過這種方式查看測試結果會比較繁瑣。

例1:測試“/etc/hosts”是否是文件,並通過“$?”變量查看返回狀態值,據此判斷測試結果。

[ -f /etc/hosts ]
echo $?
0   //返回值為0,表示上一步測試的條件成立。

例2:測試“/media/cdrom/Server”及其父目錄是否存在,如果存在則顯示“YES”否則不輸出任何信息。

[ -e /media/cdrom/Server ] && echo "YES"
                                                                        // 無輸出表示該目錄不 存在
[ -e /media/cdrom ] && echo "YES"
YES

1.2、整數值 比較:

整數值比較是指根據給定的兩個整數值,判斷第一個數是否大於、等於、小於。。。。。。第2個數,可以使用的操作選項如下:

-eq:第一個數等於(Equal)第二個數。
-ne:第一個數不等於(Not Equal)第二個數。
-gt:第一個數大於(Greater Than)第二個數。
-lt:第一個數小於(Lesser Than)第二個數。
-le:第一個數小於或等於(Lesser or Equal)第二個數。
-ge:第一個數大於或等於(Greater or Equal)第二個數。

整數值比較的測試操作在Shell腳本編寫中的應用較多,如:用於判斷磁盤使用率、登錄用戶數量是否超標以及用於控制腳本語句的循環次數等。

例1:測試當前登錄到系統中的用戶數量是否小於或等於10,是則輸出”YES“。

who | wc -l
5
[ `who | wc -l` -le 10 ] && echo ”YES"
YES

本欄目更多精彩內容:http://www.bianceng.cn/OS/Linux/

例2:提取出"/boot“分區的磁盤使用率,並判斷是否超過95%(為了便於理解,操作步驟適當進行分解)

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”.

read -p "Location: " FilePath
Location: /etc/inittab           
[ $FilePath = "/etc/inittab" ] && echo "YES"
YES

eg: 若當前環境變量LANG的內容不是“en.US”,則輸出LANG變量的值,否則無輸出。

[ $LANG != "en.US" ] && echo $LANG
zh_CN.UTF-8

eg: 使用touch命令建立一個新文件,測試其內容是否為空,向文件中寫入內容後,再次進行測試。

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“。

echo $USER
root
[ $USER = “teacher” ] || echo "Not teacher"
Not teacher

eg:只要"/etc/rc.d/rc.local"或者"/etc/init.d/local'中有一個是文件,則顯示"YES",否則無任何輸出。

[ -f /etc/rc.d/rc.local ] || [ -f /etc/init.d/rc.local ] && echo "yes“
yes

eg:測試”/etc/profile“文件是否有可執行權限,若確實沒有可執行權限,則提示”No x mode.“的信息。

[ ! -x ”/etc/profile" ] && echo "No x mode."
No x mode.

eg:若當前的用戶是root且使用的Shell程序是"/bin/bash",則顯示"YES“,否則無任何輸出。

echo $USER $SHELL
root /bin/bash
[ $USER = ”root" ] && [ $SHELL = "/bin/bash" ] && echo "yes"
yes

2:if語句的結構:

前面內容知道了一下條件測試操作,實際上使用"&&“和”||“邏輯測試可以完成簡單的判斷並執行相應的操作,但是當需要選擇執行的命令語句較多時,再使用這種方式將使命令行語句顯得很復雜,難以閱讀。而使用if語句,則可以更好地體現有選擇性執行的程序結構,使得層次分明,清晰易懂。

if語句的選擇結構由易到難可以分為三種類型,分別適用於不同的應用場合。

本欄目更多精彩內容:http://www.bianceng.cn/OS/Linux/

2.1、單分支的if語句。

單分支的if語句是最簡單的選擇結構,這種結果只判斷指定的條件,當”條件成立“時執行相應的操作,否則不做任何操作。單分支使用的語句格式如下。

if 條件測試命令

then

命令序列

fi

在上述語句中,首先通過判斷條件測試命令的返回狀態值是否為0(條件成立),如果是,則執行then後面的一條或多台可執行語句(命令序列),一直到fi為止表示結束,如果條件測試命令的返回值不為0(條件不成立),則直接去執行fi後面的語句。

2.2、雙分支的if語句。

雙分支的if語句使用了兩路命令操作,在”條件成立‘、“條件不成立時分別執行不同的命令序列”。雙分支使用的語句格式如下:

if 條件測試命令

then

命令序列1;

else

命令序列2;

fi

在上述語句中,首先通過if判斷條件測試命令的返回狀態值是否為0(條件成立),如果是,則執行then後面的一條或多條可執行語句(命令序列1),然後跳轉至fi結束判斷,如果條件測試命令的返回狀態值不為0(條件不成立),則執行else後面的語句,一直到fi表示結束。

2.3、多分支的if語句。

由於if語句可以根據條件測試命令的兩種狀態分別進行操作,所以能夠嵌套使用,進行多次判斷(如:首先判斷某學生的得分是否及格,如及格則再次判斷是否高於90分。。。)多重分支使用的語句格式如下。

if 條件測試命令1

then

命令序列1

elif 條件測試命令2

then

命令序列2

else

命令序列3

fi

上面的語法格式中只嵌套了一個elif語句,實際上if語句中可以嵌套多個elif語句。if語句的嵌套在編寫Shell腳本時並不常用,因為多重嵌套容易使程序結構變得復雜。需要使用多重分支程序結構時,更多的是使用case語句來實現。

eg:檢查"/var/log/messages'文件是否存在,若存在則統計文件內容的行數並輸出,否則不做任何操作。

vi  chklog.sh
#!/bin/bash
LogFile="/var/log/messages"
if [ -f $LogFile ] ; then
wc -l $LogFile
fi
sh chklog.sh                //sh是bash的符號鏈接

eg:提示用戶指定備份目錄的路徑,若目錄已存在則顯示提示信息後跳過,否則顯示相應提示信息後創建該目錄。

[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:統計當前登錄到系統中的用戶數量,並判斷是否超過三個,若是則顯示實際數量並給出警告信息,否則列出登錄的用戶賬號成名及所在終端。

[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

本欄目更多精彩內容:http://www.bianceng.cn/OS/Linux/

eg:檢查portmap進程是否已經存在,若已經存在則輸出“portmap service is running”;否則檢查是否存在“/etc/rc.d/init.d/portmap”可執行腳本,存在則啟動portmap服務,否則提示“no portmap script file.”。

[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服務,否則不進程任何操作。

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

3、使用for魂環語句

在Shell腳本中使用for循環語句時,可以為變量設置一個取值列表,每次讀取列表中不同的變量值並執行相關命令操作,變量值用完以後則退出循環。Shell中的for語句不需要執行條件判斷,其使用變量的取值來自於預先設置的值列表。

for語句結構:

for 變量名 in 取值列表

do

命令序列

done

在上述語句中,使用in關鍵字為用戶自定義變量設置了一個取值列表(以空格分隔的多個值),for語句第一次執行時首先將列表中的第一個取值賦給該變量。然後執行do後邊的命令序列;然後再將列表中的第二個取值賦給該變量,然後執行do後邊的命令序列......如此循環,直到取值列表中的所有值都已經用完,最後將跳至done語句,表示結束循環。

for語句示例:

eg:依次輸出三條文件信息,包括一天中的"Morning"、"Noon"、"Evening"字串。

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個,則列出具體數量及對應的用戶賬號。

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

4、使用while循環語句

在Shell腳本中使用while循環語句時,將可以根據 特定的條件重復執行一個命令列表,直到該條件不再滿足時為至。除非有特別需要,否則在腳本程序中應該是避免出現無限循環執行命令的情況,因為若無法跳出循環的話,後邊的某些操作將無法執行。為了控制循環次數,通常會在執行的命令序列中包含修改測試條件的語句,當循環達到一定次數後,測試將不再成立,從而可以結束循環。

while語句的結構:

while 條件測試命令

do

命令序列

done

在上述語句中,首先通過while判斷條件測試命令的返回狀態值是否為0(條件成立),如果是,則執行do後邊的命令序列,然後返回到while再次進行條件測試並判斷返回狀態值,如果條件仍然成立,則繼續執行do後邊的命令序列,然後返回到while重復條件測試......如此循環,直到所測試的條件不成立時,跳轉到done語句,表示結束循環。

使用while循環語句時,有兩個特殊的條件測試返回值,即“true”(真)、"false"(假)。使用“true”作為測試條件時,條件將永遠成立,循環體內的語句將無限次執行下去,反之使用“false”則條件永遠不成立,循環體內的語句將不會被執行,這兩個特殊值也可以用在if語句的條件測試中。

本欄目更多精彩內容:http://www.bianceng.cn/OS/Linux/

while語句應用示例:

while語句可以用於需要重復操作的循環系統管理任務,並能夠通過設置循環條件來靈活的實現各種管理任務。

eg:由用戶從鍵盤輸入一個大於1的整數(如50),並計算從1到該數之間各整數的和。

[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”。

[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個用戶刪除。

[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循環中斷語句。大家可以查詢!後續有時間我也會推出~

本文出自 “Coffee_藍山” 博客,請務必保留此出處http://lansgg.blog.51cto.com/5675165/1245713

Copyright © Linux教程網 All Rights Reserved