shell腳本篇二---shell腳本寫作

一、基本習慣的養成

1、腳本應該放在指定的位置

一般的,放在家目錄的scripts內;執行腳本即需執行sh  sh01.sh即可,因爲sh在bash中即位於/bin下;

使用-n  -x來校驗腳本的語法是否正確;

2、腳本的書寫規範 

一般的,需要在頭部註明Program,Histoty,作者,時間,版本等信息

一般的,特殊的程序加上#進行註釋會對以後查詢很有幫助;

在內部程序,代碼最好能以 [tab] 按鍵的空格向後推, 這樣你的程序代碼會顯的非常的漂亮和有條理,在查閱和debug上也會很輕鬆

在主程序完成後,回傳一個值給系統進行執行結果的告知,如exit 0,執行完後回傳0給系統,此時去$?則顯示爲0,即執行成功;

二、簡單的一些例子

1、讓用戶輸入,和用戶交互

read -p "please input your fist name:" firstname      #讓用戶輸入它的第一個名字,並把該值賦予變量firstname

2、數值運算

+ - * / %(這裏的%是取餘數的意思)

var=$((數值運算式))或者可以delcare -i total=$firstnu*$secnu,建議使用前一種;

3、善於運用判斷式

一般的,可以利用test命令進行測試

(1)關於文件的測試,如test  -e  filename

-e  該『檔名』是否存在?(常用)
-f  該『檔名』是否存在且爲檔案(file)?(常用)
-d  該『文件名』是否存在且爲目錄(directory)?(常用)

(2)關於某文件是否具有某些權限的測試,如test  -r  filename

-r  偵測該檔名是否存在且具有『可讀』的權限?
-w  偵測該檔名是否存在且具有『可寫』的權限?
-x  偵測該檔名是否存在且具有『可執行』的權限?

(3)關於兩個整數之間的判斷

-eq  兩數值相等 (equal)

-ne  兩數值不等 (not equal)
-gt  n1 大亍 n2 (greater than)
-lt  n1 小亍 n2 (less than)
-ge  n1 大亍等亍 n2 (greater than or equal)
-le  n1 小亍等亍 n2 (less than or equal)

(4)關於字符串的判斷

test -z string  刞定字符串是否爲 0 ?若 string 爲穸字符串,則爲 true
test -n string  刞定字符串是否非爲 0 ?若 string 爲穸字符串,則爲 false。注: -n 亦可省略
test str1 = str2 刞定 str1 是否等亍 str2 ,若相等,則回傳 true
test str1 != str2 刞定 str1 是否丌等亍 str2 ,若相等,則回傳 false

(5)多重條件判斷,如test -r filename -a -x filename

-a  (and)兩狀況同時成立!例如 test -r file -a -x file,則 file 同時具有r 不 x 權限時,纔回傳 true。
-o  (or)兩狀況任何一個成立!例如 test -r file -o -x file,則 file 具有 r或者 x 權限時,就可回傳 true。
!  反相狀態,如 test ! -x file ,當 file 丌具有 x 時,回傳 true

示例:讓用戶輸入文件名稱,並判斷是否存在,若不存在則報告信息,若存在則判斷其是否屬於文件or目錄,並判斷其讀寫權限;

[root@www scripts]# vi sh05.sh
#!/bin/bash
# Program:
#  User input a filename, program will check the flowing:
#  1.) exist? 2.) file/directory? 3.) file permissions
# History:
# 2005/08/25  VBird  First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
# 1. 譏使用者輸入檔名,幵且刞斷使用者是否真的有輸入字符串?
echo -e "Please input a filename, I will check the filename's type and \
permission. \n\n"
read -p "Input a filename : " filename
test -z $filename && echo "You MUST input a filename." && exit 0
# 2. 刞斷檔案是否存在?若不存在則顯示訊息並結束腳本
test ! -e $filename && echo "The filename '$filename' DO NOT exist" &&
exit 0
# 3. 開始刞斷文件類型不屬性
test -f $filename && filetype="regulare file"
test -d $filename && filetype="directory"
test -r $filename && perm="readable"
test -w $filename && perm="$perm writable"
test -x $filename && perm="$perm executable"
# 4. 開始輸出信息!
echo "The filename: $filename is a $filetype"
echo "And the permissions are : $perm"

4、利用[]做判斷

[]做條件判斷時一般用在if語句中。不過要注意,因爲[]在bash的特殊字符和正則表達式中均有不同的含義,因此在shell腳本中,要注意,在[]中的每一個字符都要有空格隔開,例如          [□"$HOME"□==□"$MAIL"□]                            

                   ↑                ↑    ↑              ↑                                                              #這些都是空格的意思,否則將報錯說參數(argument)過多;

5、shell腳本的默認參數$0,$1......

意思就是,對於shell腳本來說,在執行這個shell腳本(即在sh  scritname)的時候,可以帶上參數$1,$2, $3...(即可以不用像read似得需要在執行的過程中輸入參數), 這樣的話就可以在shell腳本內直接使用$1,意思就是執行的時候輸入的這個變量值;對於shell腳本來說,是支持這樣做的,其默認的格式如下:

/path/to/scriptname   opt1   opt2   opt3   opt4

            $0                   $1      $2      $3      $4             #執行的腳本即爲 $0 這個髮量,第一個接的參數就是 $1 ,所以,只要我們在script 裏面善用 $1 的話,就可以很簡單的                                                                                                 立即下達某些命令功能

除了這些數字的髮量之外, 我們還有一些較爲特殊的變量可以在 script 內使用來呼出這些參數
$# :代表後面接的參數『個數』,以上表爲例這裏顯示爲『 4 』;
$@ :代表『 "$1" "$2" "$3" "$4" 』之意,每個變量是獨立的(用雙引號括起來);
$* :代表『 "$1c$2c$3c$4" 』,其中 c 爲分隔字符,默認爲空格鍵, 所以本例中代表『 "$1 $2 $3 $4" 』之意。

提示: $@ 和 $* 基本上還是有所不同,不過,一般使用情況下可以直接記憶 $@ 即可!

示例:[root@www scripts]# vi sh07.sh
#!/bin/bash
# Program:
#  Program shows the script name, parameters...
# History:
# 2009/02/17  VBird  First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
echo "The script name is ==> $0"
echo "Total parameter number is ==> $#"
[ "$#" -lt 2 ] && echo "The number of parameter is less than 2. Stop here." && exit 0
echo "Your whole parameter is ==> '$@'"
echo "The 1st parameter ==> $1"
echo "The 2nd parameter ==> $2"
執行結果如下:
[root@www scripts]# sh sh07.sh theone haha quot
The script name is ==> sh07.sh      <==腳本名稱
Total parameter number is ==> 3     <==果然有三個參數
Your whole parameter is ==> 'theone haha quot'    <==參數的內容全部
The 1st parameter ==> theone    <==第一個參數
The 2nd parameter ==> haha      <==第二個參數

6、條件判斷式

(1)利用if...then

a、單層,簡單條件判斷式,語法格式如下

if [ 條件刞斷式 ]; then
當條件刞斷式成立時,可以進行的指令工作內容;
fi                                                                                    #將 if 反過來寫,就成爲 fi 啦!結束 if 之意!

PS:除了可以將多個判斷式寫在一個[]之外,還可以寫多個[],之間用&&(表示and)或者||(表示or)鏈接起來,比如[ "$yn" == "Y" -o "$yn" == "y" ]等同於[ "$yn" == "Y" ] || [ "$yn" == "y" ]

b、多重、複雜條件判斷式,語法格式如下

if [ 條件刞斷式一 ]; then
          當條件刞斷式一成立時,可以進行的指令工作內容;
elif [ 條件刞斷式二 ]; then                                                                              # elif 也是個刞斷式,也有條件判斷式,因此出現 elif 後面都要接 then 來處理;
          當條件刞斷式二成立時,可以進行的指令工作內容;
else                                                                                                                # else是最後沒有成立的結果了,所以後面沒有 then 了;
          當條件刞斷式一不二均不成立時,可以進行的指令工作內容;
fi      

(2)利用case...esac判斷

 if是通過比對的方式進行判斷的,而如果變量的數量有限,就可以通過case...esac來判斷,語法如下

case $髮量名稱 in                               #關鍵詞爲 case ,還有變量前有錢字號
"第一個髮量內容")                               #每個髮量內容都建議用雙引號括起來,關鍵詞則爲小括號 )
程序段
;;                                                           #每個類刪結尾使用兩個連續的分號來處理!
"第二個髮量內容")
程序段
;;
*)                                                          #最後一個髮量內容都會用 * 來代表所有其他值,不包含第一個髮量內容與第二個髮量內容的其他程序執行段
exit 1
;;
esac                                                      #最終的 case 結尾!『反過來寫』思考一下!

示例:case $1 in 
"one")
echo "Your choice is ONE"
;;
"two")
echo "Your choice is TWO"
;;
"three")
echo "Your choice is THREE"
;;
*)
echo "Usage $0 {one|two|three}"       #若用戶輸入其他的變量,則提示只能使用這三個變量
;;
esac

(3)利用function功能

 即在腳本中自定義一個功能,後面可以進行調用,如上面的例子,因爲都是同一個動作,則可以定義一個function,語法如下:

 function fname() {                                #這個 fname 就是要定義的function的名稱 ,程序段就是要它執行的功能;注意,一般的要寫在腳本的最前面;

        程序段
}
示例:function printit(){
echo -n "Your choice is "                                    # 加上 -n 可以丌斷行繼續在同一行顯示
}
echo "This program will print your selection !"
case $1 in
"one")
printit; echo $1 | tr 'a-z' 'A-Z'                             # 將參數做大小寫轉換,並注意這裏函數名稱後面有一個;
;;
"two")
printit; echo $1 | tr 'a-z' 'A-Z'
;;
"three")
printit; echo $1 | tr 'a-z' 'A-Z'
;;
*)
echo "Usage $0 {one|two|three}"
;;
esac

說明:unction 也是擁有內建變量的,他的內建變量和 shell script 很類似, 函數名稱代表示 $0 ,而後續接的變量也是以 $1, $2... 來定義的。 這裏很容易搞錯,因爲『 function fname() { 程序段 } 』內的 $0, $1... 等等與 shell script 的 $0 是不同的。以上面 sh12-2.sh 來說,假如我下達:『 sh  sh12-2.sh one 』 這表示在 shell script 內的 $1 爲 "one" 這個字符串。但是在 printit() 內的 $1 則與這個 one 無關

(4)循環語句

循環可以不斷的執行某個程序段,直到用戶定義的條件達成位爲止,所以重點是哪個程序的達成條件是什麼。除了這種依靠判斷式是否達成的不定循環之外,還有一種已經固定要跑多少次的循環狀態。
a、while do done語句,意思是當 condition 條件成立時,就進行循環,直到condition 的條件不成立才停止

while [ condition ]                      #中括號內的狀態就是刞斷式
do                                             #do 是循環的開始!
程序段落
done                                         #done 是循環的結束       

b、unitl do done語句,意思恰恰和while 相反,它說的是『當 condition 條件成立時,就終止循環, 否則就持續進行循環程序段(可知,until爲真時,就直接跳過程序段)。

until [ condition ]
do
程序段落
done

c、for do done語句,for 這種語法,則是『 已經知道要進行幾次循環』的狀態!語法爲

for var in con1 con2 con3 ...     

do      

程序段

done

說明:以上面的例子來說,這個 $var 的髮量內容在循環工作時:1. 第一次循環時, $var 的內容爲 con1 ; 2. 第二次循環時, $var 的內容爲 con2 ;3. 第三次循環時, $var 的內容爲 con3 ;  4. .... 

示例1:network="192.168.1"                                                            # 先定義一個網域的前面部分!
for sitenu in $(seq 1 100)                                                                # seq 爲 sequence(連續) 的縮寫之意
do
                                                                                                        # 底下的程序在叏得 ping 的回傳值是正確的還是失敗的!
ping -c 1 -w 1 ${network}.${sitenu} &> /dev/null && result=0 ||  result=1
                                                                                                        # 開始顯示結果是正確的吪勱 (UP) 還是錯誤的沒有連通 (DOWN)
if [ "$result" == 0 ]; then
echo "Server ${network}.${sitenu} is UP."
else
echo "Server ${network}.${sitenu} is DOWN."
fi
done

示例2:read -p "Please input a directory: " dir
if [ "$dir" == "" -o ! -d "$dir" ]; then
echo "The $dir is NOT exist in your system."
exit 1
fi
                                                                                 #  開始測試檔案囉~
filelist=$(ls $dir)                                                       # 列出所有在該目錄下的文件名
for filename in $filelist
do
perm=""
test -r "$dir/$filename" && perm="$perm readable"
test -w "$dir/$filename" && perm="$perm writable"
test -x "$dir/$filename" && perm="$perm executable"
echo "The file $dir/$filename's permission is $perm "
done
d、for do done的數值處理

除了上述之外,for done的另外一種寫法爲

for (( 初始值; 限制值; 執行步階 ))
do
程序段
done
說明:這種語法適合於數值方式的運算當中,在 for 後面的括號內的三串內容意爲:
  初始值:某個變量在循環當中的起始值,直接以類似 i=1 設定好;
  限制值:當變量的值在這個限制值的範圍內,就繼續進行循環。例如 i<=100;
  執行步階:每作一次循環時,變量的發化量。例如 i=i+1(如果每次增加 1 ,則可以使用類似『i++』)

示例:read -p "Please input a number, I will count for 1+2+...+your_input: " nu
s=0
for (( i=1; i<=$nu; i=i+1 ))
do
s=$(($s+$i))
done
echo "The result of '1+2+3+...+$nu' is ==> $s"

三、腳本的測試及debug

 sh  [-nvx]  scripts.sh
參數說明:
-n :不要執行 script,僅查詢語法的問題;
-v :再執行 sccript 前,先將 scripts 的內容輸出到屏幕上;
-x :將使用到的 script 內容顯示到屏幕上,這是很有用的參數,因爲顯示的都是指令,可以知道是哪個指令發生錯誤了。


腳本的學習,多看、多模仿、幵加以修改成自己的樣式!』 是最塊的學習手段了!網上有相當多的有用的 scripts ,可以將對方的 scripts 拿來,幵且改成適合自己主機的樣子!另外,我們 Linux 系統本來就有很多的服務啓動腳本, 可以直接以 vim 進入該 script 去查閱一下,通常立刻就知道該 script 的目的。



















發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章