Linux Shell進化簡史

導讀:M.Tim Jones 是 developerWorks 全球網站的一位多產撰稿人,他的文章涉及的主題非常廣泛而有深度。Tim 爲了讓大家全面瞭解 Linux,推出了一系列內核剖析方面的文章,深受大家的欣賞;隨着 Linux 在虛擬化技術方面的日臻成熟,Tim 及時爲我們帶來了相關內容的介紹。在本文中,他爲我們帶來了Linux Shell的進化史。以下爲全文

計算機上的大多數日常工作任務,通過鼠標點擊即可完成,但要想真正發揮Linux本身的威力,還需要Shell和命令行。Shell就如同編輯器一樣,你可以根據個人愛好選擇。雖然不同的Shell可以提供不同的功能,但是它們的核心開發思想都是一致的。

現在讓我們來追尋Shell的發展足跡,並探討幾個現在流行的Shell。

Shell的歷史

Shell也稱命令行解釋器,有着悠久的歷史,我們從第一個UNIX Shell說起。

V6 Shell

1971年,貝爾實驗室的Ken Thompson爲UNIX開發了第一個Shell——V6 Shell。類似於它在Multics上的前身,V6 Shell(/bin/sh)是一個在內核之外執行的獨立的用戶程序。

諸如通配符(模式匹配參數擴展,如*.txt)之類的概念在獨立的glob實用程序中實現,如同if命令評估條件表達式一樣。這種實現保證了Shell的短小精悍,它只有不到900行的C源代碼。

V6 Shell引入了一系列簡潔的語法,用於重定向(< >和>>)和管道(|或^),並一直沿用至今。你也會發現,它提供了對順序調用命令(;)和異步命令(&)的支持。

Thompson Shell(即V6 Shell)的缺陷在於腳本編程能力的不足,它只是一個交互性的命令解釋器。

Bourne Shell

1977年,Stephen Bourne在貝爾實驗室爲V7 UNIX開發了Bourne Shell,並一直沿用至今。很多情況下,它甚至是默認的Shell。Bourne Shell是用C語言開發的,但相比其他Shell,其語法更類似於算法語言(ALGOL)。

Bourne Shell的設計有兩個目標:作爲命令行解釋器交互執行操作系統命令和腳本編程。

爲了取代Thompson Shell,Bourne Shell有着巨大的優勢:

1.在腳本中引入了控制流、循環和變量,提供了更強大的語言與操作系統交互

2.允許使用腳本作爲篩選器,爲處理信號提供集成支持,但缺乏自定義函數機制

3.納入了一系列今天我們仍在使用的功能,包括命令替換、here-document等

Bourne Shell在前進的道路上邁出了至關重要的一步,同時也成了其他派生Shell的基石。Bourne Shell的出現推動了Korn shell (ksh)、Almquist Shell(ash)和流行的Bourne Again Shell(Bash)的開發,在Bourne Shell發佈之際,C Shell也已在開發之中。下圖顯示了Shell之間的血緣關係。

圖一:Shell之間的傳承

Shell的基礎架構

Linux Shell的基礎架構並不複雜,如下圖所示。

圖二:Linux Shell基礎架構示意圖

Linux Shell的架構看起來非常類似於一條管道,對輸入進行語法解析、符號擴展,最後執行。

探索Linux Shell

接下來,讓我們來探討幾個Shell,看看它們爲Linux Shell的發展做出了哪些貢獻。

C Shell

1978年,Bill Joy還在加州大學伯克利分校讀書的時候,就爲BSD UNIX(Berkeley Software Distribution UNIX)開發了C Shell。

五年之後,C Shell引入了Tenex系統中的一些功能,如命令行編輯功能和文件名和命令自動補全功能。Tenex C shell(tcsh)保持了對csh的向後兼容,並且提升了整體的交互性,它是Ken Greer在卡內基-梅隆大學開發出來的。

C Shell的一個主要設計目標就是創建一種語法類似於C語言的腳本語言,因爲C語言在當時非常流行,而且UNIX是用C來開發的。

Bill Joy在C Shell中引入的另一個重要特性是命令歷史記錄。此功能可以保留之前執行的命令的歷史記錄,並允許用戶查看並選擇執行之前的命令。

例如,鍵入history命令可以查看之前執行的命令,使用上下箭頭鍵可以選擇一個命令,使用!!可以執行前一個命令。引用前一個命令的參數也是可以的,比如,!*可以引用前一個命令的所有參數,!$可以引用前一個命令的最後一個參數。

請參看下面的一個Tcsh腳本示例,這個腳本使用了一個參數(目錄名稱),統計該目錄下所有可執行文件的數目。

代碼1:在tcsh中統計可執行文件的數目

  1. #!/bin/tcsh 
  2. # find all executables 
  3.  
  4. set count=0 
  5.  
  6. # Test arguments 
  7. if ($#argv != 1) then 
  8. echo "Usage is $0 <dir>" 
  9.   exit 1 
  10. endif 
  11.  
  12. # Ensure argument is a directory 
  13. if (! -d  $1) then 
  14.   echo "$1 is not a directory." 
  15.   exit 1 
  16. endif 
  17.  
  18. # Iterate the directory, emit executable files 
  19. foreach filename ($1/*) 
  20.   if (-x $filename) then 
  21.     echo $filename 
  22.     @ count = $count + 1 
  23.   endif 
  24. end 
  25.  
  26. echo 
  27. echo "$count executable files found." 
  28.  
  29. exit 0 

Korn Shell

Korn Shell是由David Korn設計的,差不多跟Tenex C Shell同時發佈。除了向後兼容Bourne Shell,Korn Shell最引人矚目的特性就是支持腳本編程。

Korn Shell原來是專有軟件,直到2000年,它才(遵照通用公共許可協議)作爲開源軟件發佈。除了對Bourne提供很好的兼容性,Korn Shell還包含了一些來自其他Shell的功能,如csh的歷史記錄功能。它還提供了一些更先進的功能,這些功能可以在諸如Ruby和Python之類的現代腳本語言中找到——例如,關聯數組和浮點運算。

Korn Shell在許多操作系統上都是可用的,這些系統包括IBM AIX and HP-UX。Korn Shell努力支持Portable Operating System Interface for UNIX(POSIX)Shell語言的標準。

我們來看一下在Korn Shell中統計可執行文件數目腳本的例子:

代碼2:在Korn Shell中統計可執行文件的數目

  1. #!/usr/bin/ksh 
  2. # find all executables 
  3.  
  4. count=0 
  5.  
  6. # Test arguments 
  7. if [ $# -ne 1 ] ; then 
  8.   echo "Usage is $0 <dir>" 
  9.   exit 1 
  10. fi 
  11.  
  12. # Ensure argument is a directory 
  13. if [ ! -d  "$1" ] ; then 
  14.   echo "$1 is not a directory." 
  15.   exit 1 
  16. fi 
  17.  
  18. # Iterate the directory, emit executable files 
  19. for filename in "$1"/* 
  20. do 
  21.   if [ -x "$filename" ] ; then 
  22.     echo $filename 
  23.     count=$((count+1)) 
  24.   fi 
  25. done 
  26.  
  27. echo 
  28. echo "$count executable files found." 
  29.  
  30. exit 0 

Bourne-Again Shell

Bourne-Again Shell,即bash,是一個開源的GNU項目,旨在替換Bourne Shell。Bourne-Again Shell由Brian Fox開發,現在已經成爲最流行的Shell之一,被廣泛應用在Linux、Darwin、Windows和Cygwin之上。

除了支持腳本的向後兼容性,bash還吸收了Korn Shell和C Shell的一些特性。例如,命令歷史記錄,命令行編輯,目錄堆棧,很多實用的環境變量,命令行自動完成,等等。

Bash繼續發展了一些新的特性,如支持正則表達式和關聯數組。

雖然一些特性是bash獨有的,但我們仍然可以編寫與其他腳本語言相兼容的腳本。下面是在bash中統計可執行文件數目的腳本示例。

代碼3:在Bourne-Again Shell中統計可執行文件的數目

  1. #!/bin/bash 
  2. # find all executables 
  3.  
  4. count=0 
  5.  
  6. # Test arguments 
  7. if [ $# -ne 1 ] ; then 
  8.   echo "Usage is $0 <dir>" 
  9.   exit 1 
  10. fi 
  11.  
  12. # Ensure argument is a directory 
  13. if [ ! -d  "$1" ] ; then 
  14.   echo "$1 is not a directory." 
  15.   exit 1 
  16. fi 
  17.  
  18. # Iterate the directory, emit executable files 
  19. for filename in "$1"/* 
  20. do 
  21.   if [ -x "$filename" ] ; then 
  22.     echo $filename 
  23.     count=$((count+1)) 
  24.   fi 
  25. done 
  26.  
  27. echo 
  28. echo "$count executable files found." 
  29.  
  30. exit 0 

這些Shell之間的一個關鍵區別是它們使用了不同的授權。Bash是一個GNU項目,遵循GPL授權,而C Shell則遵循了BSD許可,Korn Shell則遵循了通用公共許可證。

早期Shell的許多理念和接口在35年之後依然保持不變,這對其作者是一個巨大的肯定。任何一個行業都在不斷重塑自我,Shell也在發生着歷史的變遷。儘管許多新的Shell被開發出來,但Bourne Shell及其後繼者依然是現在的首選。(張志平/譯)

關於作者

M.Tim Jones

M. Tim Jones 是一名嵌入式軟件工程師,他是 Artificial Intelligence: A Systems Approach, GNU/Linux Application Programming(現在已經是第 2 版)、AI Application Programming(第 2 版)和 BSD Sockets Programming from a Multilanguage Perspective 等書的作者。他的工程背景非常廣泛,從同步宇宙飛船的內核開發到嵌入式系統架構設計,再到網絡協議的開發。Tim 是位於科羅拉多州 Longmont 的 Emulex Corp. 的一名顧問工程師。

發佈了105 篇原創文章 · 獲贊 20 · 訪問量 57萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章