前 言
一門不能改變思維方式的語言是不值得掌握的。
—Larry Wall(Perl的發明者),Randal
Schwartz
早在開始講授本課程之前,我就決定寫一本關於UNIX的書。我對當時市面上的相關書籍都不滿意,也幾乎沒有任何專家可以尋求幫助。在費盡千辛萬苦學完本課程之後,我決定寫本書,向大家介紹自己的經驗,但當時並沒有想清楚它應當面向什麼樣的讀者對像。多年之後,在我開始講授這門課程時卻發現,學生們提出的一些問題都已經在我的書中做了解答。這時,我纔知道自己做對了,這實際上是一本教科書。
UNIX經受住了時間的考驗,而且在今後一段時間內應當仍然如此。但在說起UNIX時,還是有很多人會說它“不夠友好”、“讓人撓頭”。初學者還是會因為它顯而易見的復雜性而備感打擊。即便是經驗豐富的計算機專業人士,也很難再樂於接受它的工作方式,不願意觸踫它的命令行、無數的選項和復雜的語法。今天的所有UNIX和Linux繫統都提供了圖形用戶界面,但命令行仍然是UNIX繫統的主干。
UNIX令人激動之處在於它的許多功能都是隱藏的。UNIX並沒有把一切都擺在明面上;它鼓勵用戶去創造、去革新。對於UNIX愛好者來說,如何找出能夠完成一項復雜任務的命令組合或腳本,都是真正的挑戰。這就是UNIX,而且它好繼續保持這種風格。如果你欣賞這樣一句話——“任何瘋狂背後皆有章法可循”,那你也就上道了,這本書就是為你準備的。
與眾不同
我早接觸的計算機就是UNIX機,在UNIX繫統中摸爬滾打很長一段時間後,我認識到,妨礙理解UNIX的絆腳石並不是人們認為的那些。UNIX之所以不容易理解,並不是因為它太難了,而是因為作者們缺乏足夠的想像力,沒有為它換一種表現方式。例如,書中經常會給出一條命令的20個選項,而其中可能隻有一兩項是真正有用的。我在飽受挫折之後,決定自行編寫一本“真正”的UNIX書籍——一本知道用戶真正需要什麼的UNIX書籍,一本用戶願意隨身攜帶的UNIX書籍。
現實示例 UNIX的概念很簡單,但也很抽像,為什麼要采用某一特定方式來處理某一特定功能,其原因往往不是那麼明顯。要掌握這一操作繫統,就需要全面理解這些概念。我確信已經足夠清晰地解釋了它的關鍵特性,既揭示了在設計時的考慮因素,也揭示了它們與現實世界的相關性。你會發現,本書中的許多例子都源於現實生活中的情景。
用戶指南與程序員指南 UNIX用戶主要有兩類,一類用戶使用UNIX的原生工具;另一類用戶則使用shell腳本和UNIX繫統調用庫來開發工具。本書足夠詳細地討論了這兩方面的內容,又使篇幅保持在便於閱讀、攜帶的範圍內(在同類書籍中,可能隻有本書能做到這一點)。
前11章為“用戶”服務,對於導論性的UNIX課程來說,這些內容就足夠了。“開發人員”是shell或繫統程序員,他們還得知道工作機理,例如在創建或鏈接一個文件時,目錄會受到什麼樣的影響。為他們著想,前面幾章包括了一些用於探究關鍵概念的特殊加框文字。這種安排應當不會對初學者造成影響,他們可以悄悄地忽略這些部分。第16~18章體現了UNIX的精華,要求繫統程序員必須閱讀這些章節。
醒目的學習提示 教學提示是本書的一個突出特征。它們有各種不同的名稱,例如“注意”、“警告”和“提示”。我認為Linux是UNIX家庭中的一個重要成員,所以特別采用企鵝標記來突出顯示Linux特性。
許多作者都是在單獨一章中討論每種shell,我不太贊同這種做法。我主要使用Bash
shell來討論關鍵概念,然後再分別討論C shell、Korn shell、Bourne shell的不同之處。
大量習題與練習 本書給出了大量問題,用來測驗讀者掌握的知識。其中有超過1/3是自測問題,其答案在附錄I中給出。這些問題都是面向初學者的,在繼續學習下一章之前,應當首先出色地回答這些問題。
難度更大、範圍更廣的問題留在“習題”部分。其中有一部分的難度很大,可能需要花費一些時間進行求解。這些習題會鞏固(往往還會豐富)你的UNIX知識,所以不要忽視它們。這些問題的答案在本書網站上提供:http://www.mhhe.com/das。
新增內容
一些評論者似乎對本書第2版非常滿意,他們警告說,再做改進可能不會有“太大收效”。我在牢記這一點的同時,在這一版中進行了以下修改:
● vi/vim一章得以保留,而emacs一章則被壓縮,轉為附錄。為使初學者更輕松地過渡到vi,第3章介紹了pico編輯器。
● bc計算器實用程序在這一版中又回歸了,但隻是作為shell程序員的一個高效計算工具。
● 專門為討論C語言程序設計的基礎知識而增加了一章。盡管有些簡略,但有了這一章,就足以理解後面兩章的繫統程序設計內容了。
● 現在的第15章包括了流行的並發版本繫統(CVS),所有Linux繫統中都可以找到它。SCCS和RCS在這一版中繼續保有一席之地,但在下一版,至少會刪除它們中的一項。
● 由於GNU調試程序(gdb)優於dbx,所以這一版中已經將gdb收納在內,不過後者依然得以保留。
這些變化使本書的篇幅稍有增加。盡管增加了對Linux和GNU工具的介紹,但本書的通用特性仍然保留下來;它沒有專門關注UNIX的任何具體分發版本,而是突出介紹了Solaris和Linux中的各種變型。
組織結構
這一版在邏輯上劃分為用戶部分和程序設計部分。UNIX基礎知識僅限於前11章,這部分內容在討論聯網工具時達到高潮。接下來的7章涵蓋了程序設計的相關資料,包括awk、shell程序設計、繫統程序設計和perl。
UNIX簡介 第1章通過一個簡單的實踐練習揭示了UNIX的核心概念。接下來是UNIX的發展簡史及功能展示。這一章還向讀者介紹了kernel和shell,它們共同處理繫統的工作負載。在為開發可移植應用程序而構建框架的過程中,一些標準機構(例如POSIX和The
Open Group)扮演著重要角色,學習本章之後將會了解這些機構發揮的作用。
第2章介紹了UNIX命令行的結構。它還討論了使用man命令查詢聯機文檔的技巧。我們將學習使用電子郵件程序,改變密碼,並了解繫統中發生了什麼。我們可能會出錯,而且遲早會出錯,所以還要知道如何使用鍵盤進行糾正。
文件 文件是UNIX的兩大支柱之一,接下來的三章將討論文件。第3章討論了繫統中各種類型的文件,以及處理這些文件的命令。我們將學習如何創建目錄、在目錄結構中導航定位、復制和刪除目錄中的文件。還將學習如何使用pico編輯器來編輯文件。UNIX還提供了許多壓縮實用工具,可以用來磁盤空間。
文件擁有屬性(特性),第4章介紹了文件的主要屬性,特別是用ls
-l命令顯示的屬性。要知道,文件和目錄面對攻擊都是大門洞開的,所以要學會如何通過管理它們的權限來提供保護。利用鏈接,以多個名稱來訪問同一文件。我們可能還會忘記文件的存放位置,所以需要熟悉find命令。
一個人的工作效率還取決於他對編輯器功能的熟悉程度。第5章介紹了vi,它在任何工作環境下都是功能強大的文本編輯器之一。程序員使用這一編輯器的次數可能比其他任何人都多,所以本章中的大多數例子都采用程序代碼段。附錄D中對vi的功能進行了總結。
shell和進程 現在需要理解一個非常重要的程序,我們總是和它打交道的,那就是shell。第6章介紹了shell的解釋功能,包括它字符。我們將學習使用通配符,用單個模式來匹配一組類似的文件名。使用重定向和管道來操控命令的輸入和輸出。shell也是一門編程語言,所以必須要等到第13章纔能完全理解它。
第7章介紹了進程,它是UNIX繫統的另一支柱。進程與文件類似,也擁有屬性。這一章將幫助讀者理解如何用fork-exec機制來創建進程,學習控制進程,在前臺和後臺之間移動它們,還將學習如何通過發送信號來終止進程。
UNIX
shell為定制環境提供了很好的機會(第8章)。要理解和使用shell變量、創建命令別名。選擇一種提供所有這些功能的合適shell,並學習使用初始化腳本來保存對環境的修改。
過濾器 接下來的兩章討論過濾器——這是UNIX工具包中的一些特殊命令,負責所有文本處理任務。第9章介紹了一些簡單的過濾器,並說明它們在相互連接時,如何為有效。專門有一個示例小節,其中給出了現實生活中的三個應用,它們都是在管道中使用這些過濾器加以解決的。
第10章討論了兩種功能強大的過濾器——grep和sed,它們共同處理所有的模式查找、編輯和替換操作。這裡將介紹正則表達式,它是一種精心設計的模式匹配機制,通常會大幅簡化查找與替換任務。過濾器內容之後有一章討論聯網工具(第11章),本書部分到此結束。
程序設計 後面的7章討論了UNIX的大多數程序設計功能。在第12章中,awk命令表現得像是一個過濾器和一門程序設計語言。掌握了awk及其標準程序設計構造(例如if、for和while構造),應當就為shell程序設計、perl和C語言程序設計打好了基礎。
後,我們會將所有命令和管道放到shell腳本中。利用第13章討論的shell程序設計功能,開發交互式與非交互式腳本。學習設計一種腳本,在以不同名字調用這種腳本時,其行為會發生相應變化。對shell程序員來說,本章給出的三個示例腳本是內容。
下面4章與C程序設計有著直接或間接的關繫。第14章介紹了C語言程序設計的入門知識,這是這一版新增的一章。接下來是程序開發工具(第15章)。利用make實用工具和一種功能強大的調試程序(gdb)來管理和調試程序。另外,還要學習使用SCCS、RCS和CVS來維護一個程序的多個版本。
本書有兩章介紹了繫統調用在C語言程序設計環境中的應用,第16章是其中的章,這一章討論了與文件和I/O相關的繫統調用。編寫一些程序,執行面向目錄的功能,例如列出文件等,還要學習如何提取和處理存儲在inode中的文件屬性。
第17章討論了與進程有關的繫統調用。學習使用繫統調用中的fork和exec繫列來創建進程。一旦理解了內核如何在內存中為已打開文數據,就能實現重定向和管道,以及如何在程序中處理信號。
我們在第18章遇到了perl,它是UNIX世界中功能強大的過濾器和腳本設計語言。大多數UNIX概念都內嵌在perl的設計中,許多UNIX用戶離開它就什麼也做不了,原因就在於此。盡管我們無法在單獨一章中充分欣賞perl,但第18章作為一個開端,應當是很有用的。
後,每個用戶都必須了解與繫統管理有關的例程任務,第19章討論了這一領域的基本問題。理解繫統提供的重要安全功能。熟悉與繫統啟動與關閉相關的活動,以及如何加載文件繫統,並檢查一致性。還要學習如何進行基本的備份操作。
致謝
本書的每一版都使我有機會與新的團隊進行合作。本項目的主要推動者是Raghu Srinivasan(全球出版商),同他和Melissa Leick(項目經理)的合作非常愉快。他們在McGraw-Hill指導團隊的方式給我留下了深刻印像。我還必須感謝Brenda
Rolwes(設計協調者)和Curt Reynolds(他負責營銷安排)。還要特別感謝Melinda Bilecki(策劃編輯),她一如既往地機敏。她是一位從本書構思階段就一直參與的人,這種連續性使我受益良多。
還必須感謝審稿者,他們對於本版形式、內容的調整發揮了重要作用:
Ivan Bajic,聖地亞哥州立大學
Bruce Elenbogen,密西根大學迪爾本分校
Ziad Kobti,加拿大溫莎大學
Galina Piatnitskaia,密蘇裡大學聖路易斯分校
Paul Piwowarski,肯塔基大學
Darren Provine,羅文大學
Quazi M. Rahman,加拿大西安大略大學
我要向Deepti Narwat表示誠摯的謝意,他是負責Cenveo
Publisher