分类: LINUX
2010-06-30 14:17:57
當我們對 shell 變數和命令行有一定認識之後﹐那麼﹐我們就可以嘗試寫自己的 shell script 囉~~ 這可是非常好玩而又有成就感的事情呢﹗^_^
在 linux 裡面的 shell script 可真是無處不在﹕我們開機執行的 run level 基本上都是一些 script ﹔登錄之後的環境設定﹐也是些 script ﹔甚至工作排程和記錄維護也都是 script 。您不妨隨便到 /etc/rc.d/init.d 裡面抓兩個程式回來看看﹐不難發現它們都有一個共同的之處﹕第一行一定是如下這樣的﹕
#!/bin/sh 或﹕ #!/bin/bash |
其實﹐這裡的 #! 後面要定義的就是命令的解釋器(command interpreter)﹐如果是 /bin/bash 的話﹐那下面的句子就都用 bash 來解釋﹔如果是 /usr/bin/perl 的話﹐那就用 perl 來解釋。不同的解釋器所使用的句子語法都不一樣﹐非常嚴格﹐就算同是用 shell 來解釋﹐不同的 shell 之間的格式也不僅相同。所以﹐如果您看到 script 的解釋器是 /bin/sh 的話﹐那就要小心了﹕如果您仔細看這個檔案﹐事實上它僅是一個 link 而已﹐有些系統或許會將它 link 到其它 shell 去。假如您的 script 句子使用的語法是 bash 的話﹐而這個 sh 卻 link 到 csh ﹐那執行起來可能會有問題。所以﹐最好還是直接指定 shell 的路徑比較安全一些﹕在這裡的範例都使用 /bin/bash 來作為 script 的解釋器。
在真正開始寫 script 之前﹐先讓我們認識 script 的一些基本概念﹕
簡單來說﹐shell script 裡面就是一連串命令行而已﹐再加上條件判斷﹑流程控制﹑迴圈﹑等技巧﹐聰明地執行正確的命令和使用正確的參數選項。和我們在 shell 裡面輸入命令一樣﹐shell script 也有這樣的特性﹕
一個良好的 script 作者﹐在程式開頭的時候﹐都會用註解說明 script 的名稱﹑用途﹑作者﹑日期﹑版本﹑等信息。如果您有這個機會寫自己的 script﹐也應該有這個良好習慣。
shell script 檔的命名沒一定規則﹐可以使用任何檔案名稱(參考檔案系統)﹐但如果您喜歡的話﹐可以用 .sh 來做它的副檔名﹐不過這不是硬性規定的。不過﹐要執行一個 shell script﹐使用者必須對它有執行權限( x )﹐用文件編輯器新建立的檔案都是沒有 x permission 的﹐請用 chmod 命令加上。執行的時候﹐除非該 script 已經至於 PATH 環境變數之內的路徑內﹐否則您必須指定路徑。例如﹐您寫了一個叫 test.sh 的 shell script﹐放在家目錄內﹐假設這也是您的當前工作目錄﹐您必須加上路徑才能執行﹕./test.sh 或 ~/test.sh 。所以﹐建議您在 script 測試無誤之後﹐放在 ~/bin 目錄裡面﹐那就可以在任何地方執行自己的 script 了﹐當然﹐您要確定 ~/bin 已經出現在您的 PATH 變數裡面。
script 之所以聰明﹐在於它能夠對一些條件進行測試( test )。您可以直接用 test 命令﹐也可以用 if 敘述﹐例如﹕test -f ~/test.sh 。它的意思是測試一下 ~/test.sh 這個檔案是否存在﹐這個 -f 通常用在檔案上面的測試﹐除了它﹐還有很多﹕
標籤 | 代表意思 |
-G | 存在﹐並且由 GID 所執行的行程所擁有。 |
-L | 存在﹐並且是 symbolic link 。 |
-O | 存在﹐並且由 UID 所執行的行程所擁有。 |
-S | 存在﹐並且是一個 socke 。 |
-b | 存在﹐並且是 block 檔案﹐例如磁碟等。 |
-c | 存在﹐並且是 character 檔案﹐例如終端或磁帶機。 |
-d | 存在﹐並且是一個目錄。 |
-e | 存在。 |
-f | 存在﹐並且是一個檔案。 |
-g | 存在﹐並且有 SGID 屬性。 |
-k | 存在﹐並且有 sticky bit 屬性。 |
-p | 存在﹐並且是用於行程間傳送資訊的 name pipe 或是 FIFO。 |
-r | 存在﹐並且是可讀的。 |
-s | 存在﹐並且體積大於 0 (非空檔)。 |
-u | 存在﹐並且有 SUID 屬性。 |
-w | 存在﹐並且可寫入。 |
-x | 存在﹐並且可執行。 |
事實上﹐關於這些測試項目還有很多很多﹐您可以 man bash 然後參考 CONDITIONAL EXPRESSIONS 那部份。另外﹐我們還可以同時對兩個檔案進行測試﹐例如﹕test file1 -nt file2 就是測試 file1 是否比 file2 要新。這種測試使用的標籤是﹕
標籤 | 代表意思 |
-nt | Newer Than﹕第一個檔案比第二個檔案要新。 |
-ot | Older Than﹕第一個檔案比第二個檔案要舊。 |
-ef | Equal File﹕第一個檔案和第二個檔案其實都是同一個檔案 (如 link)。 |
我們這裡所說的這些測試﹐不單只用來測試檔案﹐而且還常會用來比對‘字串 (string)’或數字(整數)。那什麼是字串呢﹖字面來介紹就是一串文字嘛。在一個測試中﹐~/test.sh 本身是一個檔案﹔但 '~/test.sh' ﹐則是在引號裡面(單引號或雙引號)﹐那就是字串了。
在數字和字串上面的比對(或測試)﹐所使用的標籤大約有﹕
標籤 | 代表意思 |
= | 等於 |
!= | 不等於 |
< | 小於 |
> | 大於 |
-eq | 等於 |
-ne | 不等於 |
-lt | 小於 |
-gt | 大於 |
-le | 小於或等於 |
-ge | 大於或等於 |
-a | 雙方都成立 |
-o | 單方成立 |
-z | 空字串 |
-n | 非空字串 |
在上面提到的比對中﹐雖然有些意思一樣﹐但使用場合卻不盡相同。例如 = 和 -eq 都是‘等於’的意思﹐但 = 只能比對字串﹐而 -eq 則可以用來比對字串﹐也能用來比對表示色樣(我們在 regular expression 會碰到)。
我們之所以要進行測試或比對﹐主要是用來做判斷的﹕假如測試或比對成立﹐那就返回一個‘真實 (true)’否則返回‘虛假 (false)’。也就是說﹕如果條件成立那麼就會如何如何﹔如果條件不成立又會如何如何﹐從而讓 script 有所‘智慧’。基本上﹐我們的程式之所以那麼聰明﹐都是從這些簡單到複雜的判斷開始的。
比方說﹐上面的 -a (AND) 和 -o (OR) 是用來測試兩個條件﹕A 和 B 。如果使用 test A -a B ﹐那麼 A 和 B 都必須成立那條件才成立﹔如果使用 test A -o B ﹐那麼只要 A 或 B 成立那條件就成立。至於其它的比對和測試﹐應該更好理解吧﹖
另外﹐還有一個特殊符號﹕“ !”您可不能不會運用。它是‘否’的意思﹐例如﹕"! -f"是非檔案﹔ "-ne" 和 "! -eq" 都是‘不等於’的意思。
我們在命令行上面已經知道如何定義和改變一個變數﹐那在 shell script 裡面就更是司空見慣了。而且﹐越會利用變數﹐您的 script 能力就越高。在 shell script 中所定義的變數有更嚴格的定義﹕
標籤 | 代表意思 |
-a | 定義為陣列 (array) 變數 |
-f | 僅定義功 (function) 能名稱。 |
-i | 定義為整數。 |
-r | 定義為唯獨變數。 |
-x | 透過環境輸出變數。 |
我們除了用 “ = ”來定義變數之外﹐還可以用 declare 命令來明確定義變數。例如﹕
# A=3 B="-2" # RESULT=$A*$B # echo $RESULT 3*-2 # declare -i A=3 B="-2" # declare -i RESULT=$A*$B # echo $RESULT -6 |
您這裡會發現﹕如果沒有使用 declare 命令將變數定義為整數的話﹐那麼 A 和 B 的變數值都只是字串而已。