1. 程式人生 > 實用技巧 >精通Linux(第2版) 第2章 基礎命令和目錄結構

精通Linux(第2版) 第2章 基礎命令和目錄結構

精通Linux(第2版)

第2章 基礎命令和目錄結構

本章我們將介紹Unix系統的命令和工具,它們在本書中會經常被用到。你可能已經對這些基本知識有所瞭解,不過我還是建議你花些時間再閱讀一遍,特別是2.19節關於目錄結構的闡述。

你也許會問,為什麼要介紹Unix命令?這本書不是關於Linux的嗎?沒錯,Linux其實是Unix的一個變種,它的本質還是Unix。Unix這個詞在本章中出現的頻率甚至高於Linux,並且你可以將本章的知識直接應用到其他基於Unix的作業系統,如Solaris和BSD。我們儘量避免介紹太多Linux特有的內容,一方面可以讓你多瞭解一點其他的作業系統,另一方面也因為那些只對Linux適用的擴充套件功能往往不太穩定可靠。掌握核心命令能夠讓你很快上手任何新的基於Linux的作業系統。

註解:Unix初學者若想了解更多細節,可以參考這幾本書:The Linux Command Line(No Starch Press,2012)、UNIX for the Impatient(Addison-Wesley Professional,1995)和Learning the UNIX Operating System, 5th edition(O'Reilly,2001)。

2.1 Bourne shell: /bin/sh

shell意思為命令列介面,是Unix作業系統中最為重要的部分之一。shell是執行命令列的應用程式,而命令列就是使用者輸入的那些命令。同時它為Unix程式設計師提供了一個小的程式設計環境,在這裡Unix程式設計師可以將通用的任務分解為一些小的元件,然後使用shell來管理和組織它們。

Unix作業系統中很多重要的部分其實都是shell指令碼,它們是包含一系列shell命令的文字檔案。如果你用過MS-DOS,你可以將shell指令碼理解為功能強大的.bat批處理檔案。我們將在第11章詳細介紹shell指令碼。

通過本書的閱讀和練習,你將會逐漸熟練地使用shell來執行各種命令。它的一個好處是一旦出現了誤操作,你可以清楚地看到你的輸入錯誤,然後進行修正。

Unix的shell有很多種,它們都是基於Bourne shell(/bin/sh)這個貝爾實驗室開發的標準shell,在早期的Unix系統上執行。所有基於Unix的作業系統都需要Bourne shell才能正常工作。

Linux使用了一個增強版本的Bourne shell,我們稱之為bash

或者“Bourne-again” shell。大部分Linux系統的預設shell是bash,其通常有一個符號連結/bin/sh。你需要使用bash來執行本書中的例子。

註解:你的Unix系統管理員為你設定的預設shell可能不是bash,你可以使用chsh命令來更改,或者請管理員為你更改。

2.2 shell的使用

安裝Linux時,除了預設的root賬號外,你還需要為自己建立至少一個普通使用者賬號,這些賬號將會是你的個人賬號。本章中你需要使用普通使用者賬號。

2.2.1 shell視窗

登入系統後,開啟一個shell視窗(也叫作終端視窗)。開啟shell視窗最簡單的方法是,在Gnome或者Ubuntu Unity這樣的圖形使用者介面(Graphical User Interface,以下簡稱GUI)中執行終端程式,這樣就可以在新的視窗中啟動shell。通常在視窗的頂端你能看到一個$提示符。在Ubuntu上,提示符是這樣:name@host:path$(使用者名稱@主機名:路徑$)。在Fedora上,提示符是這樣:[name@host path]$。shell視窗類似Windows上的DOS,OS X系統上的終端程式本質上和Linux中的shell視窗一樣。

本書中的很多命令都可以在shell上執行,例如你可以輸入以下命令列(不用輸入前面的$),然後按回車鍵:

$ echo Hello there.

註解:本書中許多shell命令都以#開頭,需要以root身份來執行,執行時需要格外小心。

現在試試下面這個命令:

$ cat /etc/passwd

這個命令是將檔案/etc/passwd中的內容顯示到shell視窗中。有關這個檔案的內容我們會在第7章詳細介紹。

2.2.2cat命令

cat命令很簡單,它顯示一個或者多個檔案的內容,命令語法如下:

$ catfile1 file2 ...

上面這個cat命令會顯示file1和file2等檔案的內容,然後退出。之所以叫cat是因為如果有多個檔案的話,它會把這些檔案的內容拼接起來顯示。

2.2.3 標準輸入輸出

我們將使用cat命令來學習Unix的輸入和輸出(以下簡稱I/O)。Unix程序使用I/O流來讀寫資料。程序從輸入流中讀取資料,向輸出流寫出資料。資料流非常靈活,比如輸入流可以是檔案、裝置、終端,甚至還可以是來自其他程序的輸出流。

想知道輸入流的工作原理,只需要輸入cat命令並回車,這時候你會看到螢幕上沒有顯示任何結果,因為cat命令仍在執行中。現在你輸入幾個字元然後回車,你會看到cat命令會在螢幕上顯示出你剛剛輸入的字元。最後你可以在任意空白行按CTRL-D終止cat命令的執行並回到shell提示符。

你剛剛和cat命令進行的一系列互動就是通過資料流機制來實現的。因為你沒有指定輸入檔名,cat命令就從Linux核心提供的預設標準輸入流中獲得輸入資料,這時執行cat命令的終端就成為標準輸入。

註解:按CTRL-D終止當前終端的標準輸入並終止命令(通常會終止一個程式)。這和CTRL-C不一樣。CTRL-C是終止當前程序的執行,無論是否有輸入和輸出。

標準輸出也與之類似。核心為每個程序提供一個標準輸出流供它們輸出資料。cat命令在終端執行的時候,標準輸出就和該終端建立連線,cat命令將資料輸出到標準輸出,就是你在螢幕上看到的結果。

標準輸入和標準輸出通常簡寫為stdin和stdout。很多命令和cat一樣,如果你不為它們指定輸入檔案,他們就從標準輸入獲得資料。輸出則有點不同,一部分命令(如cat)將資料輸出到標準輸出,另一部分命令可以將資料直接輸出到檔案。

除了標準輸入和輸出外,還有標準錯誤資訊流,我們將在2.14.1節介紹。

標準流的一個優點是你可以隨心所欲地指定資料的輸入輸出來源,在2.14節中我們會介紹如何將流連線到檔案和其他程序。

2.3 基礎命令

本節將介紹更多的Unix命令。它們大都需要輸入引數,同時支援可選項和格式(由於數量太多,在此不一一列出)。下面是一些基礎命令的簡單介紹,我們暫不深入講解。

2.3.1ls命令

ls命令顯示指定目錄的內容,預設引數為當前目錄。ls -l顯示詳細的列表,ls -F顯示檔案型別資訊(檔案型別和許可權將在2.17節介紹)。下面是檔案詳細列表的一個示例,其中第三列是檔案的所有者,第四列是使用者組,第五列是檔案大小,後面是檔案更改的時間、日期以及檔名。

$ ls -l
total 3616 
-rw-r--r--  1 juser   users     3804 Apr 30  2011 abusive.c
-rw-r--r--  1 juser   users     4165 May 26  2010 battery.zip
-rw-r--r--  1 juser   users   131219 Oct 26  2012 beav_1.40-13.tar.gz
-rw-r--r--  1 juser   users     6255 May 30  2010 country.c
drwxr-xr-x  2 juser   users     4096 Jul 17 20:00 cs335
-rwxr-xr-x  1 juser   users     7108 Feb  2  2011 dhry
-rw-r--r--  1 juser   users    11309 Oct 20  2010 dhry.c
-rw-r--r--  1 juser   users       56 Oct  6  2012 doit
drwxr-xr-x  6 juser   users     4096 Feb 20 13:51 dw
drwxr-xr-x  3 juser   users     4096 May  2  2011 hough-stuff

第一列中的d我們將在2.17節詳細介紹。

2.3.2cp命令

cp命令用來複制檔案。下面的命令將檔案file1複製到檔案file2:

$ cp file1 file2

下面的命令將多個檔案(file1 ... fileN)複製到目錄dir:

$ cp file1 ... fileN dir

2.3.3mv命令

mv命令有點類似cp,用來移動和重新命名檔案。下面的命令將檔名從file1重新命名為file2:

$ mv file1 file2

你也可以使用mv將多個檔案移動到某個目錄:

$ mv file1 ... fileN dir

2.3.4touch命令

touch命令用來建立檔案。如果檔案已經存在,則該命令會更新檔案的時間戳,就是我們在ls -l命令的執行結果中看到的檔案更新時間和日期。下面的命令建立一個新的檔案,內容為空:

$ touch file

如果我們對檔案執行ls -l,你將會看到下面的顯示結果,其中➊就是檔案被建立的時間和日期:

$ ls -l file
-rw-r--r-- 1 juser users 0 May 21 18:32 file

2.3.5rm命令

rm命令用來刪除檔案,檔案一旦被刪除通常無法恢復:

$ rm file

2.3.6echo命令

echo命令將它的引數顯示到標準輸出,例如:

$ echo Hello again.
Hello again.

我們在檢視shell萬用字元展開(如*這樣的萬用字元)和環境變數(如$HOME)的時候經常使用echo命令,本章稍後會詳細介紹。

2.4 瀏覽目錄

Unix的目錄結構是從/開始,有時候也叫作root目錄。目錄之間使用斜槓/分隔,而不是Windows中的反斜槓\。root目錄/下有子目錄,如/usr,詳見2.19節。

我們通過路徑或路徑名來訪問檔案。以/開頭的路徑(如/usr/lib)叫絕對路徑。

兩個點(..)代表一個目錄的上層目錄。如果你當前在目錄/usr/lib中,那..就代表/usr目錄,../bin則代表/usr/bin。

一個點(.)代表當前目錄。如果你當前在/usr/lib目錄中,.就代表/usr/lib,./X11則代表/usr/lib/X11。通常我們不需要使用.,而是直接使用目錄名來訪問當前目錄下的子目錄,如X11效果和./X11一樣。

不以/開頭的路徑叫相對路徑,我們大部分時候都基於當前所在目錄使用相對路徑。下面介紹一些和目錄操作相關的命令。

2.4.1cd命令

cd命令用來設定當前工作目錄。當前工作目錄是指你的程序和shell當前所在的目錄。

$ cd dir

如果不帶dir引數,cd命令會返回你的個人主目錄,指的是你登入系統後進入的目錄。

2.4.2mkdir命令

mkdir命令用來建立新目錄,例如,下面的命令建立一個名為dir的新目錄:

$ mkdir dir

2.4.3rmdir命令

rmdir命令用來刪除目錄:

$ rmdir dir

如果要刪除的目錄裡面有內容(檔案和其他目錄),上面的命令會執行失敗。因為rmdir只能刪除空目錄,你可以使用rm -rf來刪除一個目錄以及其中的所有內容。使用這個命令的時候要非常小心,尤其是當你是超級使用者(root或superuser)的時候。因為-r選項會依次刪除dir中的所有檔案和子目錄,-f選項代表強制刪除。所以使用-rf時儘量不要在引數裡使用萬用字元(如*),並且執行命令前最好檢查引數是否正確。

2.4.4 shell萬用字元

shell可以使用萬用字元來匹配檔名和目錄名。其他的作業系統也有萬用字元這個概念。比如*代表任意字元和數字。下面的命令列出當前目錄中的所有檔案:

$ echo *

shell根據引數中的萬用字元來匹配檔名。shell將命令中的引數替換為實際的檔名,這個過程我們稱為展開。比如:

  • at*展開為所有以at開頭的檔名;
  • *at展開為所有以at結尾的檔名;
  • *at*展開為所有包含at的檔名。

如果萬用字元沒有匹配的檔名,shell就不進行任何的展開,引數按照原樣來執行,比如:echo *dfkdsafh

註解:如果你慣於使用MS-DOS,你可能會下意識地使用*.*來匹配所有檔案。在Linux系統和其他Unix系統中,*.*只匹配那些包含.的檔名和目錄名,而Unix系統中很多檔名是沒有.的。

另外一個shell萬用字元問號(?)幫助shell確切匹配任意一個字元,如b?atboatbrat相匹配。

如果不想讓shell展開萬用字元,你可以使用單引號('')。例如執行echo '*'將會顯示一個*。在一些命令如grepfind中,這樣做非常有用(這一內容將在11.2節詳細介紹)。

註解:需要注意的是,shell是先展開萬用字元,然後執行命令列。如果*傳遞到命令列的時候仍然未能展開,shell則對此無能為力,一切都取決於命令本身如何處理。

現代shell的模式匹配能力並不僅限於此,但*?這兩種是你必須要掌握的。

2.5 中間命令

下面我們介紹一些基本的Unix中間命令。

2.5.1grep命令

grep命令顯示檔案和輸入流中和引數匹配的行。如下面的命令顯示檔案/etc/passwd中包含文字root的所有行:

$ grep root /etc/passwd

在對多個檔案進行批量操作的時候,grep命令非常好用,因為它顯示檔名和匹配的內容。如果你想檢視目錄/etc中所有包含root的檔案,可以執行以下命令:

$ grep root /etc/*

grep命令有兩個比較重要的選項,一個是-i(不區分大小寫),一個是-v(反轉匹配,就是顯示所有不匹配的行)。grep還有一個功能強大的變種叫作egrep(實際上就是grep -E)。

grep命令能夠識別正則表示式。正則表示式比萬用字元功能更強大,下面是兩個例子:

  • .*匹配任意多個字元(類似*萬用字元);
  • .匹配任意一個字元。

註解:幫助手冊grep(1)中有關於正則表示式的詳細說明,不過對於讀者來說可能比較不方便理解。你可以參考這兩本書:Mastering Regular Expression,3rd edition(O'Reilly,2006)或者Programming Perl,4th edition(O'Reilly,2012)中的“the regular expression”一章。如果你對數學和正則表示式的歷史感興趣,可以參閱Introduction to Automata Theory , Language, and Computation,3rd edition(Prentice Hall,2006)。

2.5.2less命令

當要檢視的檔案過大或者內容多得需要滾動螢幕的時候,可以使用less命令。如要檢視像/usr/share/dict/words這樣的大檔案,可以使用less /usr/share/dict/words命令。less命令可以將內容分屏顯示,按空格鍵可檢視下一屏,B鍵檢視上一屏,Q鍵退出。

註解:less命令實際上是more命令的增強版本。絕大多數Linux系統中都有這個命令,但是一些Unix系統和嵌入式系統中沒有這個命令,這時你可以使用more命令。

你可以在less命令的輸出結果中進行搜尋。例如:使用/word從當前位置向前搜尋word這個詞,使用?word從當前位置向後搜尋。當找到一個匹配的時候,按N鍵可以跳到下一個匹配。

你可以將幾乎所有程序的輸出作為另一個程序的輸入,我們將在2.14節詳細介紹。當你執行的命令涉及很多輸出,或者你想使用less來檢視輸出結果的時候,這個方法非常管用,比如下例所示:

$ grep ie /usr/share/dict/words | less

你可以自己親身實踐一下這個命令。類似這樣的less程式碼你會常用到。

2.5.3pwd命令

pwd命令僅輸出當前的工作目錄名。這個命令看上去不是那麼有用,其實不然,它有以下兩個用處。

首先,並不是所有的提示符都顯示當前目錄名,甚至有時候你需要擺脫它,因為它佔用很大空間,這時候就需要使用pwd來解決。

其次,使用符號連結(我們將在2.17.2節介紹)的時候通常很難獲知當前目錄資訊,這時我們可以使用pwd -P來檢視。

2.5.4diff命令

diff命令用來檢視兩個檔案之間的不同,例如:

$ diff file1 file2

該命令有幾個選項可以讓你設定輸出結果的格式,不過預設的格式對於我們來說已經足夠清晰易讀了。很多開發人員喜歡用diff -u格式,因為這個格式能被許多自動化工具很好地識別。

2.5.5file命令

如果你想知道一個檔案的格式資訊,可以執行file命令:

$ file file

這個看似平淡無奇的命令會給你提供很多有用的資訊。

2.5.6findlocate命令

我們有時候會碰到一種讓人抓狂的情況,就是明明知道有那麼一個檔案,但就是不知道它在哪個目錄。別急,使用find命令可以幫你在目錄中尋找檔案:

$ find dir -name file -print

find命令能做很多事情,但是在你確定你瞭解-name-print選項之前,不要嘗試諸如-exec這樣的選項。find命令可以使用模式匹配引數(如*),但是必須加引號('*'),以免shell自動將它們展開。(回想2.4.4節講的,shell在執行命令前會展開萬用字元。)

另外一個查詢檔案的命令是locate。和find不同的是,locate在系統建立的檔案索引中查詢檔案。這個索引由作業系統週期性地進行更新,查詢速度比find更快。但是locate對於查詢新建立的檔案可能會無能為力,因為它們有可能還沒有被加入到索引中。

2.5.7headtail命令

head命令顯示檔案的前10行內容(例如head /etc/passwd)。tail命令顯示檔案的最後10行內容(如tail /etc/passwd)。

你可以使用-n選項來設定顯示的行數(例如:head -5 /etc/passwd)。如果要從第n行開始顯示所有內容,使用tail +n

2.5.8sort命令

sort命令將檔案內的所有行按照字母順序快速排序。你可以使用-n選項按照數字順序排序那些以數字開頭的行。使用-r選項反向排序。

2.6 更改密碼和shell

你可以使用passwd命令來更改密碼,你需要輸入一遍你的舊密碼和兩遍新密碼。密碼最好複雜一些,不要使用簡單的詞句,最好是數字、大小寫字母和特殊字元混合。

設定密碼的一個好方法是選擇一個你能記住的短句,將其中的某些字元替換為數字和標點,然後將這個密碼記牢。

你可以用chsh命令更改shell(如改為kshtcsh)。本書預設使用的shell是bash

2.7 dot檔案

現在跳轉到你的home目錄,分別執行lsls -a兩個命令,你應該能夠注意到一些區別。如果沒有-a選項,你無法看到那些叫作dot檔案的配置檔案,這些檔案以.開頭。常見的dot檔案有.bashrc和.login,還有以.開頭的dot目錄,如.ssh。

這些dot檔案沒有什麼特別之處。有些命令不顯示它們是為了讓你的個人主目錄顯得更簡潔。例如,除非使用-a選項,否則ls命令不顯示dot檔案。此外,shell萬用字元不匹配dot檔案,除非明確指定.*

註解:在萬用字元中使用.*可能會導致一些問題,因為.*匹配...(當前目錄和上級目錄)。你可以使用正則表示式.[^.]*.??*來排除這兩個目錄。

2.8 環境變數和shell變數

shell中可以儲存一些臨時變數,稱作shell變數,它們是一些字元值。shell變數可以儲存指令碼執行過程中的資料,一些shell變數用來控制shell的執行方式(例如,bashshell在顯示提示符前會讀取變數PS1的值,如果PS1變數中有內容,則將它看作提示符)。

我們使用等號=為shell變數賦值,例如:

$ STUFF=blah

以上命令將blah賦值給變數STUFF。我們使用$STUFF來獲得該變數的值(例如,嘗試一下echo $STUFF這個命令)。我們將在第11章介紹更多的shell變數。

環境變數和shell變數類似,但其不僅僅針對shell。Unix系統中所有的程序都能夠訪問環境變數。兩者最大的區別是shell變數只能被當前的shell訪問,在shell中執行的命令則無法訪問。而環境變數能夠被shell中執行的所有程序訪問。

環境變數可以通過export命令來設定。例如,如果想將shell變數$STUFF變成環境變數,可以執行如下命令:

$ STUFF=blah
$ export STUFF

許多程式使用環境變數作為配置和選項資訊。例如,你可以使用LESS這個環境變數來配置less命令的引數(許多命令的幫助手冊裡都有ENVIRONMENT這一節,教你如何使用環境變數來設定該命令的引數和選項)。

2.9 命令路徑

PATH是一個特殊的環境變數,它定義了命令路徑,或簡稱為路徑。命令路徑是一個系統目錄列表,shell在執行一個命令的時候,會去這些目錄中查詢這個命令。比如:執行ls命令時,shell會在PATH中定義的所有目錄裡查詢ls,如果ls出現在多個目錄中,shell會執行第一個匹配的程式。

如果你執行echo $PATH,你會看到所有的路徑元件,它們之間以冒號(:)分隔。例如:

$ echo $PATH
/usr/local/bin:/usr/bin:/bin

你可以設定PATH變數,為shell查詢命令加入更多的路徑。例如,使用以下命令可以將路徑dir加入到PATH的最前面,這樣shell會先查詢dir路徑,然後再查詢其他路徑:

$ PATH=dir:$PATH

你也可以將路徑加入到PATH變數的最後面,這樣shell會最後查詢dir路徑:

$ PATH=$PATH:dir

註解:在更改PATH時需要特別小心,因為你有可能會不小心將PATH中所有的路徑刪除掉。不過也不用太擔心,你只需要啟動一個新的shell就可以找回原來的PATH。最簡單的解決辦法是關閉當前的終端視窗並啟動一個新的視窗。

2.10 特殊字元

在談論Linux的時候,我們需要了解一些術語。如果你有興趣瞭解,可參考“Jargon File”(http://www.catb.org/jargon/html/)或者它的印刷版本The New Hacker’s Dictionary(MIT Press,1996)。

表2-1列出了一些特殊字元,其中很多本章已經介紹過。一些工具,比如Perl程式語言,用到幾乎所有這些特殊字元!(請注意這裡使用的字元名稱是美國英語名稱。)

表2-1 特殊字元

字元

名稱

用途

*

星號

正則表示式,通用字元

.

句點

當前目錄,檔案/主機名的分隔符

!

感嘆號

邏輯非運算子,命令歷史

|

管道

命令管道

/

斜線

目錄分隔符,搜尋命令

\

反斜線

常量,巨集(非目錄)

$

美元符號

變數符號,行尾

'

單引號

字串常量

`

反引號

命令替換

"

雙引號

半字串常量

^

脫字元

邏輯非運算子,行頭

~

波浪字元

邏輯非運算子,目錄快捷方式

#

井號

註釋,預處理,替換

[ ]

方括號

範圍

{ }

大括號

宣告塊,範圍

_

下劃線

空格的簡易替代

註解:控制鍵我們通常用^來表示,如^C代表CTRL-C。

2.11 命令列編輯

在使用shell時,你應該能注意到可以使用左右箭頭來編輯命令列,並且通過上下箭頭來檢視之前的命令。這是Linux系統的標準操作。

但使用ctrl鍵來代替箭頭鍵會更加方便。表2-2中的命令是Unix系統的文字編輯標準命令,掌握了這些,你就可以很方便地在任何Unix系統中編輯文字。

表2-2 命令列按鍵

按鍵

操作

CTRL-B

左移游標

CTRL-F

右移游標

CTRL-P

檢視上一條命令(或上移游標)

CTRL-N

檢視下一條命令(或下移游標)

CTRL-A

移動游標至行首

CTRL-E

移動游標至行尾

CTRL-W

刪除前一個詞

CTRL-U

刪除從游標至行首的內容

CTRL-K

刪除從游標至行尾的內容

CTRL-Y

貼上已刪除的文字(例如貼上CTRL-U所刪除的內容)

2.12 文字編輯器

說到文字編輯,不得不提文字編輯器。要用好Unix,你必須能夠編輯文字檔案並且不對其造成損壞。Unix系統使用純文字檔案來儲存配置資訊(如目錄/etc中的檔案)。編輯檔案並不是難事,但由於要經常性地編輯這些檔案,因此你需要一個強大的文字編輯器。

在眾多文字編輯器中,你需要掌握vi和Emacs二者之一,它們是Unix系統中約定俗成所用的標準編輯器。很多Unix的大拿們對編輯器的選擇很挑剔,但是沒關係,你可以自己選擇,選擇標準就是它對你而言合不合適。

  • 如果你想要一個萬能的編輯器,功能強大,有線上幫助,你可以試試Emacs。不過它需要你進行一些額外的手動編輯。
  • 如果想要高效快速,那麼vi比較適合你。

有關vi的詳細知識可以參考這本書:Learning the vi and Vim Editors: Unix Text Processing, 7th edition(O'Reilly,2008)。關於Emacs你可以參考線上文件Start Emacs:開啟Emacs,按CTRL-H,然後按T, 或者參考GNU Emacs Manual(Free Software Foundation,2011)。

其他的編輯器如Pico和myriad GUI editor可能介面會更加友好一些,但是你一旦習慣了vi和Emacs以後,也許就再也不想使用它們了。

註解:你在進行文字編輯的時候,可能第一次注意到了終端介面和GUI的區別。vi這樣的編輯器執行在終端視窗中,使用標準輸入輸出介面。GUI編輯器啟動自己的視窗並有自己的視窗介面,與終端視窗是相互獨立的。Emacs既有終端介面也有圖形介面。

2.13 獲取線上幫助

Linux系統的幫助文件非常豐富。幫助手冊提供命令的使用說明。比如你若是想了解ls命令的用法,只需執行:

$ man ls

幫助手冊旨在提供基礎知識和參考資訊,有時會有一些例項和交叉索引,但是基本沒有那種教程式的文件。

幫助手冊會按系統排序方式(如按照字母順序)列出命令的所有選項,但是不會突出重點(比如那些經常被使用的選項)。如果你有足夠的耐性,可以逐個嘗試,或者可以問別人。

下面的命令可以幫你藉助關鍵字來查詢相關幫助手冊:

$ man -k keyword

如果你只知道某個功能,但是不知道命令名,你可以很方便地通過關鍵字來查詢。比如你若想使用排序功能,就可以執行下面的命令來列出所有和排序有關的命令:

$ man -k sort
--snip-- 
comm (1)  - compare two sorted files line by line
qsort (3) - sorts an array
sort (1)  - sort lines of text files
sortm (1) - sort messages
tsort (1) - perform topological sort
--snip--

輸出結果包括幫助手冊的名稱、所屬的章節以及內容的簡要描述。

註解:如果你對本書目前介紹的命令有疑問,可以使用man命令查閱它們的幫助手冊。

幫助手冊按照命令型別被組織為很多個章節,章節編號出現在章節名後面的括號中,例如ping(8)。表2-3中列出了各章節和它們的編號。

表2-3 線上幫助手冊章節列表

章節

簡介

1

使用者命令

2

系統呼叫

3

Unix高階程式設計庫文件

4

裝置介面和裝置驅動程式資訊

5

檔案描述符(系統配置檔案)

6

遊戲

7

檔案格式、規範和編碼(ASCII編碼和檔案字尾等等)

8

系統命令和伺服器

章節1、5、7和8對本書的內容是很好的補充參考。章節4用到的不多,章節6的內容稍微有些單薄。章節3主要是供開發人員參考。在閱讀完本書有關係統呼叫的部分後,你能對章節2的內容有更好的理解。

你可以按序號來選擇章節,這會讓搜尋結果更加精確,因為一旦匹配了搜尋關鍵字,幫助手冊會定位到該關鍵字查詢結果的第一頁。比如你要搜尋有關passwd的資訊,可以使用如下命令:

$ man 5 passwd

幫助手冊涵蓋的是基本內容,你還可以使用--help或者-h選項來獲得幫助資訊。如ls --help

GNU專案因為不喜歡幫助手冊這種方式,引入了info(或者texinfo)。info文件的內容更加豐富,同時也更復雜一些。可以使用info命令檢視info檔案內容:

$ info command

有一些程式將它們的文件放到目錄/usr/share/doc中,而不是maninfo裡。你可以在這裡搜尋需要的文件,當然別忘了還有網際網路。

2.14 shell輸入輸出

至此你已經瞭解了Unix的基本命令,檔案和目錄,現在我們可以介紹標準輸入輸出的重定向了。讓我們從標準輸出開始。

如果想將命令的執行結果輸出到檔案(預設是終端螢幕),可以使用重定向字元>

$ command > file

如果檔案file不存在,shell會建立一個新檔案file。如果file檔案已經存在,shell會先清空檔案的內容。(一些shell可以通過設定引數來防止檔案被清空,如:bash中的set -C命令。)

如果不想把原檔案覆蓋,你可以使用>>將命令的輸出結果加入到檔案末尾:

$ command >> file

這個方法在收集多個命令的執行結果時非常有用。

你還可以使用管道字元(|)將一個命令的執行結果輸出到另一個命令。例如:

$ head /proc/cpuinfo
$ head /proc/cpuinfo | tr a-z A-Z

你可以使用任意多個管道字元,只需要在每個額外的命令前各加一個管道符即可。

2.14.1 標準錯誤輸出

有的時候你會發現,即使重定向了標準輸出,終端螢幕上還是會顯示一些資訊,其實這是標準錯誤輸出,是用來顯示系統錯誤和除錯資訊的一種額外的輸出流。比如,執行下面的命令後,會發生錯誤:

$ ls /fffffffff > f

輸出完成後,f應該是空的,但你會在終端螢幕上看到以下錯誤資訊,即標準錯誤輸出:

ls: cannot access /fffffffff: No such file or directory

如果有必要,你可以使用2>重定向標準錯誤輸出,例如,使用2>向f傳送標準輸出,向e傳送標準錯誤輸出:

$ ls /fffffffff > f 2> e

這裡的2是由shell修改的流ID,1是標準輸出,2是標準錯誤輸出。

你也可以使用>&將標準輸出和標準錯誤輸出重定向到同一個地方,例如,把標準輸出和標準錯誤輸出重定向到檔案f中,可執行以下命令:

$ ls /fffffffff > f 2>&1

2.14.2 標準輸入重定向

使用<操作符將檔案內容重定向為命令的標準輸入:

$ head < /proc/cpuinfo

你偶爾會遇見要求這種型別的重定向的程式,但因為很多Unix命令可以使用檔名作為引數,所以不太常需要使用<來重定向檔案。例如,上述命令也可以寫成head /proc/cpuinfo

2.15 理解錯誤資訊

在Linux這樣的基於Unix的作業系統中,程式執行出錯時你要做的第一件事情必須是檢視錯誤資訊,因為大多數情況下,出錯的具體原因都能在錯誤資訊裡找到。這一點Unix系統做得比其他有些作業系統要好。

2.15.1 解析Unix的錯誤資訊

絕大部分Unix上的應用程式都使用相同的方式處理錯誤資訊,但在任意兩個程式的輸出結果之間可能會存在些微的差別。例如,你可能會經常遇到這種情況:

$ ls /dsafsda
ls: cannot access /dsafsda: No such file or directory

該資訊分為以下三部分。

  • 命令檔名:ls。一些程式不顯示命令檔名,這對於指令碼除錯來說很不方便。但這也不是問題的關鍵。
  • 檔案路徑:/dsafsda。這是一條更為具體的資訊,而問題就出在這個檔案路徑上。
  • 錯誤資訊:No such file or directory。這一資訊告訴我們錯誤出在檔案路徑名上。

將以上的資訊綜合起來看,你就能得出結論:ls想要訪問檔案/dsafsda,但是檔案不存在。在這個例子裡,錯誤資訊很易懂,但是如果你執行的是執行很多命令的指令碼,出錯資訊會變得複雜難懂。

在排錯時,務必從第一個錯誤開始入手。程式報告錯誤時總是先告訴你它無法完成某一個操作,接下來告訴你一些其他的相關問題。例如我們虛構這樣一個場景:

scumd: cannot access /etc/scumd/config: No such file or directory

後面跟著一大串的錯誤資訊,看起來問題很嚴重。首先不要受它們的影響,專注於第一個錯誤資訊你就知道,要解決的問題只不過是建立一個檔案/etc/scumd/config而已。

註解:不要把錯誤資訊和警告資訊混為一談。警告資訊看起來像是錯誤資訊,但是它只是告訴我們程式出了問題,但是還能夠繼續執行。要解決警告資訊裡面的問題,你可能需要終止當前程序。(有關檢視和終止程序的內容,我們將在2.16節介紹。)

2.15.2 常見錯誤

Unix程式的很多錯誤與檔案和程序有關。下面我們列舉一些常見的錯誤。

No such file or directory

這可能是我們最常遇到的錯誤:訪問一個不存在的檔案或目錄。由於Unix的I/O系統對檔案和目錄不做區分,所以當你試圖訪問一個不存在的檔案,進入一個不存在的目錄,或將檔案寫入一個不存在的目錄時,都會出現這個錯誤。

File exists

如果新建檔案的名稱和現有的檔案或者目錄重名,就會出現這個錯誤。

Not a directory, Is a directory

這個錯誤出現在當你把檔案當作目錄或者反之,把目錄當作檔案。例如:

$ touch a
$ touch a/b
touch: a/b: Not a directory

錯誤出在第二個命令這裡,將檔案a當作了目錄,很多時候你可能需要花點時間來檢查檔案路徑。

No space left on device

說明硬碟空間不足。

Permission denied

當你試圖讀或寫一個沒有訪問許可權的檔案或目錄時,會遇到這個錯誤。當你試圖執行一個你無權執行(即使你有讀的許可權)的檔案時也會出現這個錯誤。我們會在2.17節詳細介紹。

Operation not permitted

當你試圖終止一個你無權終止的程序時,會出現這個錯誤。

Segmentation fault, Bus error

分段故障,匯流排錯誤。分段故障這個錯誤通常是告訴你,你執行的程式出了問題。可能你的程式試圖訪問它無權訪問的記憶體空間,這時作業系統就會將其終止。匯流排錯誤說明你的程式訪問記憶體的方式有問題。遇到這類錯誤通常是因為程式的輸入資料有問題。

2.16 檢視和操縱程序

我們在第1章介紹過,程序就是執行在記憶體中的程式。每個程序都有一個數字ID,叫程序ID(Process ID,以下簡稱PID)。可以使用ps命令列出所有正在執行的程序:

$ ps
  PID   TTY  STAT TIME  COMMAND 
  520    p0  S    0:00  -bash 
  545     ?  S    3:59  /usr/X11R6/bin/ctwm -W 
  548     ?  S    0:10  xclock -geometry -0-0 
 2159    pd  SW   0:00  /usr/bin/vi lib/addresses 
31956    p3  R    0:00  ps

每行的欄位依次代表以下內容。

  • PID:程序ID。

  • TTY:程序所在的終端裝置,稍後詳述。

  • STAT:程序狀態,就是程序在記憶體中的狀態。例如,S表示程序正在休眠,R表示程序正在執行。(完整的狀態列表請參閱幫助手冊ps(1)。)

  • TIME:程序目前為止所用CPU時長(格式:mm:ss),就是程序佔用CPU的總時長。

  • COMMAND:命令名,請注意程序有可能將其由初始值改為其他。

2.16.1 命令選項

ps命令有很多選項,你可以使用三種方式來設定選項:Unix方式、BSD方式和GNU方式。BSD方式被認為是比較好的一種,因為它相對簡單一些。本書也將使用BSD這種方式。下面是一些比較實用的選項組合。

** `ps x` ** 顯示當前使用者執行的所有程序。
**`ps ax` ** 顯示系統當前執行的所有程序,包括其他使用者的程序。
** `ps u`** 顯示更詳細的程序資訊。
**`ps w` ** 顯示命令的全名,而非僅顯示一行以內的內容。

和對其他程式一樣,你可以對ps使用選項組合,如ps auxps auxw。你可以將PID作為ps命令的一個引數,用來檢視該特定程序的資訊,如ps u $$,其中$$是一個shell變數,表示當前的shell程序。(在第8章我們將會介紹toplsof管理員命令,它們能夠幫助我們找到程序所在的位置。)

2.16.2 終止程序

要終止一個程序,可以使用kill命令向其傳送一個訊號,訊號是核心發給程序的一條訊息。當kill命令執行時,它請求核心傳送一個訊號給程序。大多數情況下,你可以執行下面的命令:

$ kill pid

訊號的種類有很多,預設是TERM(或者terminate)。你可以設定選項來發送不同型別的訊號。例如,傳送STOP訊號可以讓程序暫停,而不是終止:

$ kill -STOP pid

被暫停的程序仍然駐留在記憶體,等待被繼續執行。使用CONT訊號可以繼續執行程序:

$ kill -CONT pid

註解:你可以使用CTRL-C來終止當前執行的程序,效果和kill -INT命令一樣。

終止程序最粗魯的一種方式是使用KILL訊號。和其他訊號不同,KILL會強行終止程序,並將其移出記憶體,不會給程序清理和收尾的機會。不到萬不得已最好不要使用該訊號。

不要隨便終止一個你不知道的程序,不然很有可能遇到麻煩。

你還可以使用數字來代替訊號名,例如:kill -9等同於kill -KILL。因為核心使用數字來代表不同的訊號。如果你知道你想要傳送的訊號的數字號,可以使用這種方式。

2.16.3 任務控制

Shell也支援任務控制(Job Control),是通過不同的按鍵和命令向程序傳送TSTP(類似STOP)和CONT訊號的一種方式。例如,你可以使用CTRL-Z傳送TSTP訊號來停止程序,然後鍵入fg(將程序置於前臺)或者bg(將程序移入後臺,見下一小節)繼續執行程序。對初學者來說這些可能不太好理解,不過對於很多高階使用者來說它們是很好用的命令。如果使用CTRL-Z而不是CTRL-C,然後置之不理,最終會形成大量處於暫停狀態的程序。

提示:你可以使用jobs命令來檢視你暫停了哪些程序。

如果你想要執行多個shell,可以單獨在每個終端視窗中執行一個程式,將非互動性質的程式置於後臺執行(後面將會介紹),或者瞭解一下screen程式的使用方法。

2.16.4 後臺程序

當你在shell上執行命令時,命令列提示符會暫時消失,命令結束時又重新顯示。你可以使用&操作符將程序設定為後臺執行,這樣提示符會一直顯示,你在程序執行過程中可以繼續其他操作。例如,如果你要解壓縮一個很大的檔案(我們將在2.18節介紹),同時又不想幹等執行結果,你就可以使用下面的命令:

$ gunzip file.gz &

Shell會顯示後臺新程序的PID,然後直接將命令列提示符顯示回來,以便你繼續進行其他操作。後臺程序在你退出系統後仍會一直執行,這比較適用於那些耗時很長的程序。(你可以設定shell讓程序在結束時傳送通知。)

後臺程序的一個缺點是沒法和使用者互動(甚至會直接從終端獲得輸入)。它們可以暫停(用fg恢復執行)或終止以便從標準輸入獲得資料,也可以將資料輸出到標準輸出和標準錯誤,這些資料顯示在終端螢幕上,有時會和其他正在執行的程序的輸出資料混在一起顯示,讓人難以辨別。

最好的方式是將輸出重定向(輸入也可以),比如重定向到檔案或別的地方(我們已經在2.14節介紹過),這樣螢幕上就不會出現雜亂無章的輸出資料。

如果後臺程序的輸出結果雜亂無章,你需要知道如何整理你的終端視窗內容。bashshell和大多數有全屏互動的程式支援CTRL-L命令,它會清空你的螢幕。程序在從標準輸入讀取資料之前,經常先使用CTRL-R清空當前行,在錯誤的時間按了錯誤的鍵會讓情況更糟。如果不小心在bash提示符下按了CTRL-R,你會被切換到一個讓人不知所云的反轉搜尋模式,這時你可以按ESC退出。

2.17 檔案模式和許可權

Unix系統中的每一個檔案都有一組許可權值,用來控制你是否能讀、寫和執行檔案。可以使用命令ls -l來檢視這些資訊。例如:

-rw-r--r--➊ 1 juser  somegroup    7041 Mar 26 19:34 endnotes.html

➊是檔案模式,顯示許可權及其他附加資訊。檔案模式由四部分組成,如圖2-1。

圖2-1 檔案模式資訊

本例中第一個字元-是檔案型別,-代表常規檔案,常規檔案是最常見的一種檔案型別,另一種常見型別是目錄,用d代表。(3.1節中會介紹其餘的檔案型別。)

本例中的其餘部分是檔案許可權資訊,由三部分組成:使用者、使用者組和其他。例如,rw-是使用者許可權,後面的r--是使用者組許可權,最後的r--是其他許可權。

許可權資訊由四個字元組成:

   
**` r`** 檔案可讀
** `w` ** 檔案可寫
**`x`** 檔案可執行
**`-` **

使用者許可權部分(第一組)是針對檔案的擁有者,上例中是juser。使用者組許可權部分是針對somegroup這個使用者組中的所有使用者。(命令groups可以顯示你所在的使用者組,詳細內容在7.3.5節介紹。)

其他許可權部分是針對系統中的所有其他使用者,又稱為全域性許可權。

註解:許可權資訊中代表讀、寫和執行的這三個部分我們稱為許可權位,如:讀位指的是所有三個代表讀的部分。

有些可執行檔案的執行位是s(setuid)而不是x,表示你將以檔案擁有者的身份執行該檔案,而不是你自己。很多程式使用s,如passwd命令,因為該命令需要更新/etc/passwd檔案,所以必須以檔案擁有者(即root使用者)的身份執行。

2.17.1 更改檔案許可權

使用chmod命令更改檔案許可權。例如,對檔案file,要為使用者組g和其他使用者o加上可讀許可權r,執行以下命令:

$ chmod g+r file
$ chmod o+r file

也可以使用一行命令:

$ chmod go+r file

如果要取消許可權,則使用go-r

註解:不要將全域性許可權設定為可寫,因為這樣任何人都能夠修改檔案。但是這樣會讓網際網路上的人更改你的檔案嗎?恐怕不能,除非你的系統有網路安全漏洞。果真是這樣的話,檔案許可權也無能為力。

有時你會看到下面這樣的命令,使用數字來代表權限:

$ chmod 644 file

這個命令會設定所有的許可權位,我們稱為絕對許可權設定。要知道每一個數字(八進位制)代表的許可權,可以參考該命令的使用手冊。請參考下面的表格。

表2-4 絕對許可權模式

模式

詳情

用途

644

使用者:讀/寫;使用者組,其他:讀

檔案

600

使用者:讀/寫;使用者組,其他:無

檔案

755

使用者:讀/寫/執行;使用者組,其他:讀/執行

目錄,程式

700

使用者:讀/寫/執行;使用者組,其他:無

目錄,程式

711

使用者:讀/寫/執行;使用者組,其他:執行

目錄

和檔案一樣,目錄也有許可權。如果你對目錄有讀的許可權,你就可以列出目錄中的內容,但是如果要訪問目錄中的某個檔案,你就必須對目錄有可執行的許可權(使用絕對值設定許可權的時候,目錄的可執行許可權常常會被不小心取消)。

你還可以使用umask命令來為檔案設定預定義的預設許可權。例如,如果你想讓任何人對檔案和目錄有讀的許可權,使用umask 022,反之,如果不想讓你的檔案和目錄可讀,使用umask 077(在第13章中我們將詳細介紹如何在啟動檔案中使用umask命令)。

2.17.2 符號連結

符號連結是指向檔案或者目錄的檔案,相當於檔案的別名(類似Windows中的快捷方式)。符號連結為複雜的目錄提供了便捷快速的訪問方式。

在一個長目錄列表裡,符號連結如下例所示(請注意檔案型別是l):

lrwxrwxrwx 1 ruser users 11 Feb 27 13:52 somedir -> /home/origdir

如果你訪問somedir,實際訪問的是home/origdir目錄,符號連結僅僅是指向另一個名字的名字,所以/home/origdir這個目錄即使不存在也沒有關係。

如果/home/origdir不存在的話,訪問somedir的時候系統會報錯稱somedir不存在。

符號連結不提供其目標路徑的詳細資訊,你只能自己開啟這個連結,看看它指向的究竟是檔案還是目錄。有時候一個符號連結還可以指向另一個符號連結,我們稱為鏈式符號連結。

2.17.3 建立符號連結

使用ln -s命令建立符號連結:

$ ln -s target linkname

linkname引數是符號連結名稱,target引數是要指向的目標路徑,-s選項表示這是一個符號連結(請見稍後的警告部分)。

執行這個命令之前請反覆確認,如果你不小心調換了targetlinkname這兩個引數的位置,命令變成了:ln -s linkname target,如果linkname這個路徑已經存在,一些有趣的事情就會發生。ln會在linkname目錄中建立一個名為target的符號連結,如果linkname不是絕對路徑,target就會指向它自己。當你使用ln命令遇到問題的時候,請注意檢查此類情況。

如果不知道符號連結已經存在的話,就會帶來很多麻煩。例如,你有可能無意中會將符號連結檔案當作目標檔案的副本進行編輯。

警告:建立符號連結的時候,請注意不要忘記-s選項。沒有此選項的話,ln命令會建立一個硬連結,為檔案建立一個新的名字。新檔案擁有老檔案的所有狀態資訊,和符號連結一樣,開啟這個新檔案會直接開啟檔案內容。除非你掌握了4.5節的內容,否則不要使用符號連結。

符號連結能方便我們管理、組織、共享檔案,所以即使有這麼多“缺點”,我們還是會用到它。

2.18 歸檔和壓縮檔案

瞭解了檔案、許可權和相關錯誤資訊之後,讓我們來了解一下gziptar

2.18.1gzip命令

gzip(GNU Zip)命令是Unix上眾多標準壓縮程式中的一個。GNU Zip生成的壓縮檔案帶有後綴名.gz。解壓縮.gz檔案使用gunzip file.gz命令,壓縮檔案使用gzip file命令。

2.18.2tar命令

gzip命令只壓縮單個檔案,要壓縮和歸檔多個檔案和目錄,可以使用tar命令:

$ tar cvf archive.tar file1 file2 ...

tar命令生成的檔案帶有後綴名.tar,<archive>.tar是生成的歸檔檔名,file1、file2等是要歸檔的檔案和目錄列表。選項c代表建立檔案。選項rf的作用則更加具體。

選項v用來顯示詳細的命令執行資訊(比如正在歸檔的檔案和目錄名),再加一個v選項可以顯示檔案大小和許可權等資訊。如果你不想看到這些資訊,可以不用加v選項。

選項f代表檔案,後面需要指定一個歸檔檔名(如<archive>.tar)。如果不指定歸檔檔名,則歸檔到磁帶裝置,如果檔名為-,則是歸檔到標準輸入或者輸出。

解壓縮tar檔案

使用tar命令解壓縮.tar檔案:

$ tar xvf archive.tar

選項x代表解壓模式。你還可以只解壓歸檔檔案中的某幾個檔案,只需要在命令後面加上這些檔案的檔名即可。

註解:tar命令解壓後並不會刪除歸檔檔案。

內容預覽表模式

在解壓一個歸檔檔案之前,通常建議使用選項t來檢視歸檔檔案中的內容,t代表內容預覽表模式,它會顯示歸檔的檔案列表,並且驗證歸檔資訊的完整性。如果你不做檢查直接解壓歸檔檔案,有時會解壓出一些很難清理的垃圾內容。

你需要檢查壓縮包中的檔案是否在同一目錄下,你可以建立一個臨時目錄,在其中試著解壓一下看看(只要不產生一堆檔案,使用mv命令移動一個目錄總是容易的)。

解壓縮時,你可以使用選項p來保留被歸檔檔案的許可權資訊。當你使用超級使用者執行解壓命令時,選項p預設開啟。如果你在執行過程中遇到這樣那樣的問題,請確保你等到tar命令執行完畢並顯示提示符。tar命令每次都處理整個歸檔檔案,無論你是解壓整個檔案或者只是檔案中的某部分,所以命令執行過程中請不要中斷,因為有些操作是在檔案檢查之後才開始的,比如許可權設定。

2.18.3 壓縮歸檔檔案(.tar.gz)

許多初學者對被壓縮後的歸檔檔案(字尾為.tar.gz)比較費解。我們可以按照從右到左的順序來解壓和開啟此類檔案。例如,使用以下命令首先解壓縮,然後校驗及釋放歸檔檔案包:

$ gunzip file.tar.gz
$ tar xvf file.tar

如果需要歸檔並壓縮,則按照相反順序,先執行tar命令歸檔,然後執行gzip命令壓縮。你可能會逐漸覺得這兩個步驟很麻煩,下面我們介紹一些更簡便的方法。

2.18.4zcat命令

上面的命令缺點是執行效率不高,並且會佔用很多硬碟空間。管道命令是一個更好的選擇,例如:

$ zcat file.tar.gz | tar xvf -

zcat命令等同於gunzip -dc命令。選項d代表解壓縮,選項c代表將執行結果輸出到標準輸出(本例中是輸出到tar命令)。

tar命令很常用,它的Linux版本有這樣幾個選項值得注意:選項z對歸檔檔案自動執行gzip,對建立歸檔包和釋放歸檔包均適用。例如使用以下命令來驗證壓縮檔案:

$ tar ztvf file.tar.gz

然而,在走捷徑以前,最好還是先掌握基本方法。

註解:.tgz檔案和.tar.gz檔案沒有區別,字尾.tgz主要是針對MS-DOS的FAT檔案系統。

2.18.5 其他的壓縮命令

Unix中的另一個壓縮命令是bzip2,生成字尾名為.bz2的檔案。該命令執行效率比gzip稍慢,主要用來壓縮文字檔案,因而在壓縮原始碼檔案的時候比較常用。相應的解壓縮命令是bunzip2,可用選項和gzip幾乎相同,其中選項j是針對tar命令的壓縮和解壓縮。

此外xz是另外一個漸受歡迎的壓縮命令,對應的解壓縮命令是unxz,可用選項和gzip也十分類似。

Linux上的zipunzip與Windows上的.zip檔案格式大部分是相容的,包括.zip和.exe自解壓檔案。有一個很古老的Unix命令compress支援.Z格式,gunzip命令能夠解壓縮.Z檔案,但是gzip不支援此格式檔案的建立。

2.19 Linux目錄結構基礎

我們前面介紹了檔案、目錄和幫助手冊,現在來看看系統檔案。Linux目錄結構的詳解可以參考檔案系統標準結構(FHS,http://www.pathname.com/fhs/)。圖2-2為我們展示了Linux的基本目錄結構,包括目錄/、/usr和/var下的子目錄。請注意/usr下的子目錄有些和/下的子目錄一樣。

圖2-2 Linux目錄結構

下面這些目錄需要重點介紹。

  • /bin目錄中存放的是可執行檔案,包括大部分基礎的Unix命令(如lscp)。該目錄中的大部分是由C編譯器建立的二進位制檔案,還有一些現代系統的shell指令碼檔案。
  • /dev目錄中是裝置檔案,將在第3章詳細介紹。
  • /etc目錄(讀作EHT-see)存放重要的系統配置檔案,如使用者密碼檔案、啟動檔案、裝置、網路和其他配置檔案。許多都是硬體系統的配置檔案。例如,/etc/X11目錄中是顯示卡和視窗系統的配置檔案。
  • /home目錄中是使用者的個人目錄。大多數Unix系統都遵循這個規範。
  • /lib目錄中是供可執行程式使用的各種程式碼庫。程式碼庫分為兩種:靜態庫和共享庫。/lib目錄中一般只有共享庫。其他程式碼庫目錄,如:/usr/lib中會有靜態庫和動態庫,以及其他的輔助檔案(將在第15章詳細介紹)。
  • /proc目錄中通過一個可瀏覽的目錄與檔案介面來存放系統相關資訊,比如當前執行的程序和核心的資訊。Linux上這個目錄的一大部分子目錄結構相比其他Unix系統要特別一些,但其他Unix系統大多也有類似的特性。/proc目錄中包含了當前正在執行的程序的資訊以及一些核心引數。
  • /sys目錄類似/proc目錄,裡面是裝置和系統的資訊(將在第3章介紹)。
  • /sbin目錄中是可執行的系統檔案,這些可執行檔案用來管理系統。普通使用者一般不需要使用,許多命令只能由root使用者執行。
  • /tmp目錄存放無關緊要的臨時檔案。所有使用者對該目錄都有讀和寫的許可權,不過可能對別人的檔案沒有許可權。許多程式會使用這個目錄作為儲存資料的地方,但如果資料很重要的話請不要存放在/tmp目錄中,因為很多系統會在啟動時清空/tmp目錄,甚至是經常性地清理這個目錄裡的舊檔案。也注意不要讓/tmp目錄裡的垃圾檔案佔用太多的硬碟空間。
  • /usr目錄雖然讀作user,但裡面並沒有使用者檔案,而是存放著許多Linux系統檔案。/usr目錄中的很多目錄名和root目錄上的相同(如/usr/bin和/usr/lib),裡面存放的檔案型別也相同。(為了讓root檔案系統佔用儘可能少的空間,許多系統檔案並沒有存放在系統root目錄下。)
  • /var目錄是程式存放執行時資訊的地方,如系統日誌、使用者資訊、快取和其他資訊。(你可能會注意到這裡有一個子目錄/var/tmp,和/tmp不同的是,系統不會在啟動時清空它。)

2.19.1 root目錄下的其他目錄

root目錄下還有以下這些子目錄。

  • /boot目錄存放核心載入檔案。這些檔案中存放Linux在第一次啟動時的資訊,之後的資訊並不儲存在這裡。詳見第5章。
  • /media目錄是載入可移除裝置的地方,比如可行動硬碟。
  • /opt目錄一般存放第三方軟體,許多系統並沒有這個目錄。

2.19.2 /usr目錄

/usr目錄中內容比它的名字多得多,你看一看/usr/bin和/usr/lib的內容就會知道,/usr目錄存放那些執行在使用者空間中的程序和資料。除了/usr/bin、/usr/sbin1和/usr/lib外,還包括以下內容。

  • /include目錄存放C編譯器需要使用的標頭檔案。
  • /info目錄存放GNU幫助手冊(參考2.13節)。
  • /local目錄是管理員安裝軟體的地方,它的結構和/以及/usr類似。
  • /man存放使用者手冊。
  • /share目錄存放Unix系統間的共享檔案。過去這個目錄通常在網路中被共享,現在使用得越來越少,因為硬碟空間不再是一個大問題,且維護/share目錄也讓人頭疼。/share目錄中經常包括/man、/info和其他子目錄。

2.19.3 核心位置

Linux系統的核心通常在/vmlinuz或者/boot/vmlinuz中。系統啟動時,引導裝載程式將這個檔案載入到記憶體並執行(我們將在第5章詳細介紹)。

引導裝載程式執行完畢後,系統就不再需要核心檔案了。不過,系統在執行過程中會根據需要載入和解除安裝許多模組,我們稱之為可載入核心模組,它們在/lib/modules目錄下可以找到。

2.20 以超級使用者的身份執行命令

繼續新內容之前,你需要了解如何以超級使用者的身份執行命令。你可能已經知道使用su命令然後輸入root使用者密碼就可以啟動root命令列,不過這個方法有以下幾個缺點:

  • 對更改系統的命令沒有記錄資訊;
  • 對執行上述命令的使用者身份沒有記錄資訊;
  • 無法訪問普通Shell環境;
  • 必須輸入root密碼。

2.20.1sudo命令

大部分Linux系統中,管理員可以使用自己的使用者賬號登入,然後使用sudo來以root使用者身份執行命令。例如,在第7章中,我們會介紹如何使用vipw命令編輯/etc/passwd檔案。例如:

$ sudo vipw

執行sudo命令時,它會使用local2中的系統日誌服務將操作寫入日誌。我們將在第7章詳細介紹。

2.20.2 /etc/sudoers

系統當然不會允許任何使用者都能夠以超級使用者的身份執行命令,你需要在/etc/sudoers檔案中加入指定的使用者。sudo命令有很多選項,使用起來比較複雜。例如,下面的設定允許使用者user1和user2不用輸入密碼即可以超級使用者身份執行命令:

User_Alias ADMINS = user1, user2 

ADMINS ALL = NOPASSWD: ALL

root ALL=(ALL) ALL

第一行為user1user2指定一個ADMINS別名,第二行賦予它們許可權。ALL = NOPASSWD: ALL表示有ADMINS別名的使用者可以執行sudo命令。該行中第二個ALL代表允許執行任何命令,第一個ALL表示允許在任何主機執行命令(如果你有多個主機,你可以針對某個主機或者某一組主機設定,這個我們在這裡不詳細介紹)。

root ALL=(ALL) ALL表示root使用者能夠在任何主機上執行任何命令。(ALL)表示root使用者可以以任何使用者的身份執行命令。你可以通過以下方式將(ALL)許可權賦予有ADMINS別名的使用者,將(ALL)加入到/etc/sudoers行,如➊所示:

ADMINS ALL = (ALL)➊ NOPASSWD: ALL

註解:可以使用visudo命令編輯/etc/sudoers檔案,該命令在儲存檔案時會做語法檢查。

sudo命令我們現在就介紹到這裡,詳細的使用方法請參考sudoers(5)和sudo(8)幫助手冊。(使用者切換的詳細內容我們將在第7章介紹。)

2.21 前瞻

目前為止你對以下這些命令已經有所瞭解:執行程式、重定向輸出、檔案和目錄操作、檢視程序、檢視幫助手冊以及使用者空間。你應該也學會了以超級使用者身份執行命令。關於使用者空間元件和核心的詳細內容,你可能還不甚瞭解,但掌握了檔案和程序的基礎知識後,這些也不再是難事。在下面的章節中,我們就來介紹如何使用這些命令來操作核心和使用者空間。