Linux下Shell基礎知識簡介
Shell是一種具備特殊功能的程式,它是介於使用者和 UNIX/Linux 作業系統之核心程式(kernel)間的一個介面。為什麼我們說 shell 是一種介於系統核心程式與使用者間的中介者呢?讀過作業系統概論的讀者們都知道作業系統是一個系統資源的管理者與分配者,當您有需求時,您得向系統提出;從作業系統的角度來看,它也必須防止使用者因為錯誤的操作而造成系統的傷害?眾所周知,對計算機下命令得透過命令(command)或是程式(program);程式有編譯器(compiler)將程式轉為二進位制程式碼,可是命令呢?其實shell 也是一支程式,它由輸入裝置讀取命令,再將其轉為計算機可以瞭解的機械碼,然後執行它。
各種作業系統都有它自己的Shell,以 DOS 為例,它的 shell 就是 command.com 檔。如同 DOS 下有 NDOS,4DOS,DRDOS 等不同的命令解譯程式可以取代標準的 command.com , UNIX 下除了 Bourne shell(/bin/sh) 外還有 C shell(/bin/csh)、Korn shell (/bin/ksh)、Bourne again shell(/bin/bash)、Tenex C shell(tcsh) … 等其它的 shell。UNIX/Linux 將 shell 獨立於核心程式之外,使得它就如同一般的應用程式,可以在不影響作業系統本身的情況下進行修改、更新版本或是新增新的功能。
Shell 的啟用
在系統起動的時候,核心程式會被載入記憶體,負責管理系統的工作,直到系統關閉為止。它建立並控制著處理程式,管理記憶體、檔案系統、通訊等等。而其它的程式,包括 shell 程式,都存放在磁碟中。核心程式將它們載入記憶體,執行它們,並且在它們中止後清理系統。Shell 是一個公用程式,它在您簽入時起動。藉由解譯使用者輸入的命令(由命令列或命令檔), Shell 提供使用者和核心程式產生交談的功能。
當您簽入(login)時,一個交談式的shell 會跟著起動,並提示您輸入命令。在您鍵入一個命令後,接著就是 shell 的工作了,它會進行:
1. 語法分析命令列
2. 處理萬用字元(wildcards)、轉向(redirection)、管線(pipes)與工作控制(job control)
3. 搜尋並執行命令
當您剛開始學UNIX/Linux系統時,您大部份的時間會花在於提示符號(prompt)下執行命令。
如果您經常會輸入一組相同形式的命令,您可能會想要自動執行那些工作。如此,您可以將一些命令放入一個檔案(稱為命令檔,script),然後執行該檔。一個shell 命令檔很像是 DOS 下的批次檔(如 Autoexec.bat):它把一連串的 UNIX 命令存入一個檔案,然後執行該檔。較成熟的命令檔還支援若干現代程式語言的控制結構,譬如說能做條件判斷、迴圈、檔案測試、傳送引數等。要寫著寫命令檔,不僅要學習程式設計的結構和技巧,而且對 UNIX/Linux 公用程式及如何運作需有深入的瞭解。有些公用程式的功能非常強大(例如 grep、sed 和awk),它們常被用於命令檔來操控命令輸出和檔案。在您對那些工具和程式設計結構變得熟悉之後,您就可以開始寫命令檔。當由命令檔執行命令時,此刻,您就已經把 shell 當做程式語言使用了。
Shell 的發展歷史
第一個有重要意義的,標準的 UNIX shell 是V7(AT&T的第七版)UNIX,在1979 年底被提出,且以它的創造者 Stephen Bourne 來命名。Bourne shell 是以 Algol 這種語言為基礎來設計,主要被用來做自動化系統管理工作。雖然 Bourne shell 以簡單和速度而受歡迎,但它缺少許多交談性使用的特色,例如歷程、別名和工作控制。
C shell 是在加州大學柏克來分校於70年代末期發展而成,而以2BSD UNIX的部分發行。這個 shell 主要是由 Bill Joy 寫成,提供了一些在標準 Bourne shell 所看不到的額外特色。C shell 是以C 程式語言作為基礎,且它被用來當程式語言時,能共享類似的語法。它也提供在交談式運用上的改進,例如命令列歷程、別名和工作控制。因為 C shell 是在大型機器上設計出來,且增加了一些額外功能,所以 C shell 有在小型機器上跑得較慢,即使在大型機器上跟 Bourne shell 比起來也顯得緩慢。
有了 Bourne shell 和 C shell 之後,UNIX 使用者就有了選擇,且爭論那一個 shell 較好。AT&T 的 David Korn 在 80 年代中期發明了 Korn shell,在 1986 年發行且在 1988 年成為正式的部分 SVR4 UNIX。 Korn shell 實際上是 Bourne shell 的超集,且不只可在 UNIX 系統上執行,同時也可在 OS/2、VMS、和 DOS上執行。它提供了和 Bourne shell 向上相容的能力,且增加了許多在 C shell 上受歡迎的特色,更增加了速度和效率。 Korn shell 已歷經許多修正版,要找尋您使用的是那一個版本可在 ksh 提示符號下按 Ctrl-v 鍵。
三種主要的 Shell 與其分支
在大部份的UNIX系統,三種著名且廣被支援的shell 是Bourne shell(AT&T shell,在 Linux 下是BASH)、 C shell(Berkeley shell,在 Linux 下是TCSH)和 Korn shell(Bourne shell的超集)。這三種 shell 在交談(interactive)模式下的表現相當類似,但作為命令檔案語言時,在語法和執行效率上就有些不同了。
Bourne shell 是標準的 UNIX shell,以前常被用來做為管理系統之用。大部份的系統管理命令檔案,例如 rc start、stop 與shutdown 都是Bourne shell 的命令檔,且在單一使用者模式(single user mode)下以 root 簽入時它常被系統管理者使用。Bourne shell 是由 AT&T 發展的,以簡潔、快速著名。 Bourne shell 提示符號的預設值是 $。
C shell 是柏克萊大學(Berkeley)所開發的,且加入了一些新特性,如命令列歷程(history)、別名(alias)、內建算術、檔名完成(filename completion)、和工作控制(job control)。對於常在交談模式下執行 shell 的使用者而言,他們較喜愛使用 C shell;但對於系統管理者而言,則較偏好以 Bourne shell 來做命令檔,因為 Bourne shell 命令檔比 C shell 命令檔來的簡單及快速。C shell 提示符號的預設值是 %。
Korn shell 是 Bourne shell 的超集(superset),由 AT&T 的 David Korn 所開發。它增加了一些特色,比 C shell 更為先進。Korn shell 的特色包括了可編輯的歷程、別名、函式、正規表示式萬用字元(regular expression wildcard)、內建算術、工作控制(job control)、共作處理(coprocessing)、和特殊的除錯功能。Bourne shell 幾乎和 Korn shell 完全向上相容(upward compatible),所以在 Bourne shell 下開發的程式仍能在 Korn shell 上執行。Korn shell 提示符號的預設值也是 $。在 Linux 系統使用的 Korn shell 叫做 pdksh,它是指 Public Domain Korn Shell。
除了執行效率稍差外,Korn shell 在許多方面都比 Bourne shell 為佳;但是,若將 Korn shell 與 C shell 相比就很困難,因為二者在許多方面都各有所長,就效率和容易使用上看,Korn shell 是優於 C shell,相信許多使用者對於 C Shell 的執行效率都有負面的印象。
在shell 的語法方面,Korn shell 是比較接近一般程式語言,而且它具有子程式的功能及提供較多的資料型態。至於 Bourne shell,它所擁有的資料型態是三種 shell 中最少的,僅提供字串變數和布林型態。在整體考量下 Korn shell 是三者中表現最佳者,其次為 C shell,最後才是 Bourne shell,但是在實際使用中仍有其它應列入考慮的因素,如速度是最重要的選擇時,很可能應該採用 Bourne shell,因它是最基本的 shell,執行的速度最快。
果你是習慣於Windows命令提示符的IT人,當你第一次使用Linux命令列時,一定會感到無所適從。你所熟悉的DOS命令再Linux中基本不存在。擺在你面前的是一大堆要記背的命令。
一種替代方案是利用強大的Linux外殼命令編寫shell指令碼,讓你在Linux下也能用DOS命令。下面告訴你怎麼做。
shell指令碼編寫基礎
從定時備份到執行簡單命令,Linux的shell指令碼可以執行各種功能。幾乎所有的程式都可以用shell指令碼來執行。在指令碼中甚至可以包含一些簡單的條件選擇。shell指令碼的基本格式如下:
#!/bin/sh
...
Your commands here
...
注意檔案以#!/bin/sh開始。這條語句告訴作業系統用來解釋指令碼的程式位置。大多數系統會有/bin/sh目錄,因為該目錄包含root使用者的標準shell程式。在大部分系統中你也可以指定/bin/bash目錄。
每種shell的指令碼都有所不同。一些shell,比如bash,支援比標準shell更多的命令。在大多數Linux版本中sh實際上就是bash。
從指令碼執行命令十分簡單,很像在Windows DOS提示符下執行命令。舉個例子,通過下面這段語句可以拷貝檔案:
#!/bin/sh
cp file1 file2
mv file2 file3
echo "complete" > complete.txt
自動執行命令對那些不需人工干預的任務很有用,但對一般使用者來說並不那麼有用。為此,shell指令碼在執行過程中允許使用者輸入命令列引數,然後利用輸入的引數執行命令。指令碼中輸入引數用$1到$9表示。如果你曾寫過DOS批處理檔案,你會發現批處理檔案中也有類似功能,只是它用的是%1、%2等來代表輸入引數。下面舉例來說怎樣使用命令列引數:
#!/bin/sh
cp $1 $2
上段指令碼接受2個命令列引數,第一個是要拷貝的原檔案,第二個是拷貝的目標檔案。執行指令碼的命令格式是:./myscript file1 file2,myscript代表指令碼檔名。命令列選項也可以通過這種方式傳遞,如:
#!/bin/sh
cp $1 $2 $3
鍵入./copy –r sourcedir destdir形式的命令執行上段指令碼,即可遞迴拷貝$2目錄下所有檔案到$3目錄下。選項$1為-r時能讓cp命令遞迴拷貝所有檔案。
含條件選擇的shell指令碼
對於不含變數的任務簡單shell指令碼一般能勝任。但在執行一些決策任務時,就需要包含if/then的條件判斷了。shell指令碼程式設計支援此類運算,包括比較運算、判斷檔案是否存在等。基本的if條件命令選項有:
-eq —比較兩個引數是否相等(例如,if [ 2 –eq 5 ])
-ne —比較兩個引數是否不相等
-lt —引數1是否小於引數2
-le —引數1是否小於等於引數2
-gt —引數1是否大於引數2
-ge —引數1是否大於等於引數2
-f — 檢查某檔案是否存在(例如,if [ -f "filename" ])
-d — 檢查目錄是否存在
幾乎所有的判斷都可以用這些比較運算子實現。指令碼中常用-f命令選項在執行某一檔案之前檢查它是否存在。
(http://www.fanqiang.com)