**一、什麼是PID** 學過自動控制原理的對PID並不陌生,PID控制是對偏差信號e(t)進行比例、積分和微分運算變換後形成的一種控制規律。PID 演算法的一般形式: ![](https://img2023.cnblogs.com/blog/2776504/202305/2776504-202305 ...
本章是對本書中你將遇到的Unix命令和工具的指南。
為什麼是Unix命令?這不是一本關於Linux如何工作的書嗎?當然是的,但Linux在本質上是一種Unix風格。在本章中,你會看到Unix這個詞,而不是Linux,因為你可以把你學到的東西直接帶到BSD和其他Unix風味的系統中去。我試圖避免涉及太多Linux特有的用戶界面擴展,這不僅是為了給你使用其他操作系統提供更好的背景,而且也是因為這些擴展往往是不穩定的。如果你知道核心命令,你就能更快地適應新的Linux版本。此外,瞭解這些命令可以促進你對內核的理解,因為許多命令直接對應於系統調用。
註意:如果想瞭解比這裡更多的關於Unix初學者的細節,可以考慮閱讀《The Linux Command Line》第二版(No Starch Press, 2019),《UNIX for the Impatient》第二版(Addison-Wesley Professional, 1995),以及《Learning the UNIX Operating System,》第五版(O'Reilly, 2001)。
2.1 Bourne Shell: /bin/sh
shell是Unix系統中最重要的部分之一。shell是一個運行命令的程式,就像用戶在終端視窗中輸入的命令。這些命令可以是其他程式或shell的內置功能。shell還可以作為小型的編程環境。Unix程式員經常將普通的任務分解成較小的組件,並使用shell來管理任務和拼湊事情。
系統的許多重要部分實際上是shell腳本--包含shell命令序列的文本文件。如果你以前使用過MS-DOS,你可以把shell腳本想象成非常強大的.BAT文件。因為它們很重要,第11章完全是關於shell腳本的。
隨著你在本書中的學習和實踐,你會增加你對使用shell操作命令的知識。shell最好的一點是,如果你犯了錯誤,你可以很容易地看到你輸入的內容,找出錯誤的原因,然後再試一次。
有許多不同的Unix shell,但所有的功能都來自Bourne shell(/bin/sh),這是貝爾實驗室為早期版本的Unix開發的標準外殼。每個Unix系統都需要一個版本的Bourne shell,以便正常運行,正如你在本書中看到的那樣。
Linux使用Bourne shell的增強版本,稱為bash或 "Bourne-again "shell。bash shell是大多數Linux發行版上的預設shell,在Linux系統中,/bin/sh通常是bash的鏈接。在運行本書中的例子時,你應該使用bash shell。
註意
如果你在一個你不是系統管理員的組織中使用本章作為Unix賬戶的指南,你可能沒有把bash作為你的預設shell。你可以用chsh改變你的shell或者向你的系統管理員尋求幫助。
2.2 使用Shell
當你安裝Linux時,你應該至少創建一個普通用戶,作為你的個人賬戶。在本章中,你應該以普通用戶的身份登錄。
2.2.1 Shell視窗
登錄後,打開shell視窗(通常被稱為終端)。從Gnome或KDE這樣的GUI中這樣做的最簡單方法是打開終端程式,在新視窗中啟動shell。一旦你打開了shell,它應該在頂部顯示提示,通常以美元符號($)結尾。在Ubuntu上,這個提示符應該是name@host:path$,在Fedora上是[name@host path]$,其中name是你的用戶名,host是你機器的名字,path是你當前的工作目錄(見2.4.1節)。如果你熟悉Windows,shell視窗看起來就像DOS的命令提示符;在macOS中,終端程式基本上與Linux的shell視窗相同。
本書包含許多你將在shell提示符下輸入的命令。它們都以一個$開頭,表示shell提示符。例如,輸入這個命令(只輸入粗體部分,不輸入$),然後按ENTER鍵:
andrew@andrew-HP:~$ echo Hello there.
Hello there.
註意:本書中的許多shell命令以#開頭。你應該以超級用戶(root)的身份運行這些命令,所以需要特別小心。在運行這些命令時,最好的做法是使用sudo,以便提供一些保護,並有日誌,你可以在以後查找可能的錯誤。你將在第2.20節看到如何做到這一點。
現在輸入這個命令:
andrew@andrew-HP:~$ cat /etc/passwd
root:x:0:0:root:/root:/bin/bash
...
這個命令顯示了/etc/passwd系統信息文件的內容,然後返回你的shell提示。現在不要關註這個文件的作用,你將在第7章中瞭解它的全部內容。
命令通常以要運行的程式開始,後面可能有參數,告訴程式要對什麼進行操作以及如何操作。這裡,程式是cat,有一個參數,即/etc/passwd。許多參數是修改程式預設行為的選項,通常以破折號(-)開頭。你很快就會在討論ls的時候看到這一點。然而,有一些例外情況並不遵循這種正常的命令結構,比如shell的內置參數和環境變數的臨時使用。
2.2.2 cat
cat程式是Unix中最容易理解的程式之一;它簡單地輸出一個或多個文件的內容或另一個輸入源。cat命令的一般語法如下:
$ cat file1 file2 ...
當你運行這個命令時,cat會列印file1、file2和任何其他你指定為參數的文件(在前面的例子中用...表示)的內容,然後退出。該程式被稱為cat,因為它在列印多個文件的內容時執行串聯操作。有很多方法可以運行cat;讓我們用它來探索Unix的I/O。
2.2.3 標準輸入和標準輸出
Unix進程使用I/O流來讀和寫數據。進程從輸入流中讀取數據,並將數據寫到輸出流中。流是非常靈活的。例如,輸入流的源頭可以是一個文件、一個設備、一個終端視窗,甚至是另一個進程的輸出流。
要看正在工作的輸入流,請輸入cat(沒有參數)並按下ENTER。這一次,你不會得到任何直接的輸出,你也不會得到你的shell提示符,因為cat仍然在運行。現在輸入任何內容,併在每一行的末尾按回車鍵。像這樣使用時,cat命令會重覆你輸入的任何一行。一旦你覺得足夠無聊,就在一個空行上按CTRL-D來終止cat並返回shell提示符。
cat在這裡採用互動式行為的原因與流有關。當你沒有指定輸入文件名時,cat從Linux內核提供的標準輸入流而不是連接到文件的流中讀取。在這種情況下,標準輸入被連接到你運行cat的終端。
註意:在空行上按下CTRL-D會以EOF(文件結束)信息停止當前終端的標準輸入條目(通常也會終止一個程式)。不要把它與CTRL-C混淆,後者通常會終止一個程式,而不管其輸入或輸出。
標準輸出是類似的。內核給每個進程一個標準輸出流,它可以在那裡寫出它的輸出。cat命令總是把它的輸出寫到標準輸出。當你在終端運行cat時,標準輸出被連接到該終端,所以你在那裡看到了輸出。
標準輸入和輸出通常被縮寫為stdin和stdout。許多命令的操作與cat一樣;如果你不指定輸入文件,命令就從stdin中讀取。輸出則有些不同。一些程式(如cat)只將輸出發送到stdout,但其他程式可以選擇將輸出直接發送到文件。
還有第三個標準I/O流,叫做標準錯誤。你會在第2.14.1節看到它。
標準流的最好的特點是,你可以很容易地操縱它們來讀寫終端以外的地方,你將在第2.14節中學習。特別是,你將學習如何將流連接到文件和其他進程。
2.3 基本命令
現在讓我們來看看更多的Unix命令。這是基本命令的簡化列表,沒涉及到細節。
2.3.1 ls
ls命令列出了目錄的內容。預設情況下是當前目錄,但你可以添加任何目錄或文件作為參數,而且有許多有用的選項。例如,使用ls -l來獲得詳細的(長)列表,使用ls -F來顯示文件類型信息。下麵是一個長列表的例子;它包括文件的所有者(第3列),組(第4列),文件大小(第5列),以及修改日期/時間(在第5列和文件名之間):
andrew@andrew-HP:~$ ls -l
total 119228
-rwxrwxrwx 1 andrew andrew 108 11月 10 2022 a-cov.gcda
-rwxrwxrwx 1 andrew andrew 676 11月 10 2022 a-cov.gcno
-rwxrwxrwx 1 andrew andrew 27248 11月 10 2022 a.out
-rw-rw-r-- 1 andrew andrew 1949 2月 15 14:31 base.html
drwxrwxr-x 5 andrew andrew 4096 5月 27 07:20 'Calibre 書庫'
drwxrwxrwx 24 andrew andrew 4096 5月 11 15:04 code
...
你將在第2.17節中瞭解更多關於該輸出的第1列。你可以暫時忽略第2列;它是指向文件的硬鏈接的數量,在第4.6節中有解釋。
2.3.2 cp
在其最簡單的形式中,cp複製文件。例如,要將file1複製到file2,請輸入以下內容:
$ cp file1 file2
你也可以把一個文件複製到另一個目錄,在該目錄中保持相同的文件名:
$ cp file dir
要複製一個以上的文件到名為dir的目錄(文件夾)中,請嘗試像這樣的例子,複製三個文件:
$ cp file1 file2 file3 dir
2.3.3 mv
mv(移動)命令的工作原理與cp很相似。在其最簡單的形式中,它重命名文件。例如,要把file1重命名為file2,請輸入以下內容:
$ mv file1 file2
2.3.4 touch
touch命令可以創建文件。如果目標文件已經存在,touch不會改變該文件,但會更新該文件的修改時間戳。例如,要創建空文件,可以這樣輸入:
$ touch file
然後在該文件上運行ls -l。你應該看到像下麵這樣的輸出,其中的日期和時間表示你運行觸摸的時間:
$ touch file
$ ls -l file
-rw-rw-r-- 1 andrew andrew 0 5月 27 11:20 file
要看到時間戳的更新,至少要等一分鐘,然後再運行同樣的touch命令。ls -l返回的時間戳會更新。
2.3.5 rm
rm命令刪除(移除)文件。在你刪除文件後,它通常會從你的系統中消失,除非你從備份中恢復它。
$ rm file
2.3.6 echo
echo命令將其參數列印到標準輸出:
$ echo Hello again.
Hello again.
echo命令對於查找shell globs("通配符",如*)和變數(如$HOME)的擴展非常有用,你在本章後面會遇到這些情況。
2.4 瀏覽目錄
Unix的目錄層次結構從/開始,也稱為根目錄。目錄的分隔符是斜線(/),而不是反斜線(\)。在根目錄下有幾個標準的子目錄,如/usr,你將在第2.19節中學習。
當你引用文件或目錄時,你指定路徑或路徑名。當路徑以/開頭時(如/usr/lib),它是完整或絕對的路徑。
由兩個點(...)標識的路徑組件指定一個目錄的父級。例如,如果你在/usr/lib中工作,路徑..指的是/usr。同樣地,../bin指的是/usr/bin。
點(.)指的是當前目錄;例如,如果你在/usr/lib,路徑.仍然是/usr/lib,而./X11是/usr/lib/X11。你不會經常使用.,因為如果路徑不是以/開頭,大多數命令都預設為當前目錄(所以你可以在前面的例子中直接使用X11而不是./X11)。
不以/開頭的路徑被稱為相對路徑。大多數時候,你會使用相對路徑名,因為你已經在你需要的目錄中或附近。
現在你已經對基本的目錄機制有了瞭解,下麵是一些基本的目錄命令。
cd
當前工作目錄是一個進程(如shell)當前所處的目錄。除了大多數Linux發行版中預設的shell提示外,你還可以用2.5.3節中描述的pwd命令查看你的當前目錄。
每個進程都可以獨立設置自己的當前工作目錄。cd命令可以改變shell的當前工作目錄:
$ cd dir
如果你省略了dir,shell將返回到你的主目錄,即你第一次登錄時開始的目錄。有些程式會用~符號(tilde)來簡寫你的主目錄。
註意: cd命令是shell的內置命令。它不能作為單獨的程式工作,因為如果它作為子進程運行,它不能(通常)改變其父級的當前工作目錄。
2.4.2 mkdir
mkdir命令創建新的目錄:
$ mkdir dir
2.4.3 rmdir
rmdir命令可以刪除目錄dir:
$ rmdir dir
如果dir不是空的,這個命令就會失敗。然而,如果你沒有耐心,你可能不想先費力地刪除dir裡面的所有文件和子目錄。你可以使用rm -r dir來刪除目錄和它的內容,但要小心!這是少數幾個可以造成嚴重破壞的命令之一,特別是當你以超級用戶身份運行它時。-r選項指定了遞歸刪除,重覆刪除dir中的所有內容。不要將-r標誌與星號(*)等globs一起使用。最重要的是,在運行你的命令之前一定要仔細檢查。
2.4.4 Shell的globbing("通配符")
shell可以將簡單的模式與文件和目錄名相匹配,這個過程被稱為 "通配"。這與其他系統中的通配符的概念相似。其中最簡單的是glob字元*,它告訴shell去匹配任何數量的任意字元。例如,下麵的命令可以列印出當前目錄下的文件列表:
$ echo *
shell將包含globs的參數與文件名相匹配,將文件名替換為這些參數,然後運行修改後的命令行。這種替換被稱為擴展,因為shell將所有匹配的文件名替換為一個簡化的表達式。下麵是一些使用*來擴展文件名的方法:
- at*擴展到所有以at開頭的文件名。
- *at擴展到所有以at結尾的文件名。
- at擴展到所有包含at的文件名。
另一個shell glob字元,問號(?),指示shell精確匹配一個任意字元。例如,b?at匹配boat和brat。
如果你不希望shell在命令中擴展一個glob,可以用單引號('')把這個glob括起來。例如,命令echo '*'可以列印出一顆星。你會發現這對下一節中描述的一些命令很方便,例如grep和find。(你將在第11.2節中學習更多關於引號的知識)。
註意:重要的是要記住,shell在運行命令前會進行擴展,而且只在這時進行。因此,如果一個 ""沒有被擴展到命令中,shell不會對它做任何事情;而是由命令來決定它要做什麼。
shell的模式匹配能力還有很多,但是和? 是你現在需要知道的。第2.7節描述了那些以點開頭的有趣文件的glob行為。
2.5 中級命令
這一節描述了最基本的Unix中級命令。
2.5.1 grep
grep命令列印文件或輸入流中與某個表達式相匹配的行。例如,要列印/etc/passwd文件中包含文本root的行,請輸入以下內容:
$ grep root /etc/passwd
grep命令在同時對多個文件進行操作時特別方便,因為它除了列印匹配的行外,還列印文件名。例如,如果你想檢查/etc中包含root這個詞的每個文件,你可以使用這個命令:
$ grep root /etc/*
兩個最重要的grep選項是-i(用於不區分大小寫的匹配)和-v(反轉搜索,即列印所有不匹配的行)。還有一個更強大的變體,叫做egrep(它只是grep -E的一個同義詞)。
grep能夠理解正則表達式,這些模式以電腦科學理論為基礎,在Unix工具中非常常見。正則表達式比通配符式的模式更強大,而且它們有不同的語法。關於正則表達式,有三件重要的事情需要記住:
- .* 匹配任何數量的字元,包括沒有字元(像globs和通配符中的*)。
- .+ 匹配任何一個或多個字元。
- .精確匹配一個任意字元。
註意: grep(1) 手冊頁包含了對正則表達式的詳細描述,但它可能有些難以閱讀。要瞭解更多信息,你可以閱讀Jeffrey E. F. Friedl編寫的《Mastering Regular Expressions》第三版(O'Reilly,2006年),或者參見Tom Christensen等人編寫的《Programming Perl》第四版(O'Reilly,2012年)的正則表達式章節。如果你喜歡數學,並且對正則表達式的來源感興趣,可以看看Jeffrey Ullman和John Hopcroft的《AutomataTheory, Languages, and Computation》第三版(Prentice Hall,2006)。
2.5.2 less
當文件非常大,或者命令的輸出很長,並且滾動到屏幕上方時,less命令就會派上用場。
要翻閱像/usr/share/dict/words這樣的大文件,你可以使用命令less /usr/share/dict/words。當運行 less 時,你會看到文件的內容,每次都是一屏。按空格鍵可以往前看文件,按b(小寫)可以往後跳一個屏幕。要退出,按q。
註意:less命令是一個名為more的舊程式的增強版。Linux台式機和伺服器有less,但它在許多嵌入式系統和其他Unix系統中不是標準配置。如果你遇到了不能使用less的情況,可以試試more。
你也可以在less裡面搜索文本。例如,要向前搜索一個單詞,你可以輸入/word,要向後搜索,你可以使用?word。當你找到一個匹配詞時,按n繼續搜索。
正如你在第2.14節中所瞭解的,你可以將幾乎所有程式的標準輸出直接發送到另一個程式的標準輸入。當你有命令有大量的輸出需要篩選,而你又想用 less 這樣的東西來查看輸出時,這就特別有用。下麵是將grep命令的輸出發送到less的例子:
$ grep ie /usr/share/dict/words | less
2.5.3 pwd
pwd(列印工作目錄)程式只是輸出當前工作目錄的名稱。你可能想知道為什麼你需要這個,因為大多數Linux發行版都在提示符中設置了用戶賬戶的當前工作目錄。有兩個原因。
首先,不是所有的提示符都包括當前工作目錄,特別是你可能想在自己的提示符中去掉它,因為它占用了很多空間。
第二,你將在第2.17.2節中瞭解到的符號鏈接有時會掩蓋當前工作目錄的真正完整路徑。使用pwd -P來消除這種混淆。
2.5.4 diff
要查看兩個文本文件之間的差異,可以使用diff:
$ diff file1 file2
有幾個選項可以控制輸出的格式,預設的輸出格式往往是人類最容易理解的。然而,大多數程式員在需要將輸出結果發送給別人時,更喜歡diff -u的輸出,因為自動化工具更容易處理這種格式。
2.5.5 file
如果你看到一個文件,但不確定它的格式,可以嘗試使用file命令,看看系統是否能猜到它:
$ file file
你可能會對這個看起來很單純的命令的作用感到驚訝。
2.5.6 查找和定位
當你知道某個文件在某個目錄樹下,但你不知道在哪裡時,這是很令人沮喪的。運行find來查找dir中的文件,方法如下:
$ find dir -name file -print
像本節中的大多數程式一樣,find能做一些花哨的事情。然而,在你熟知這裡顯示的形式並理解為什麼你需要-name和-print選項之前,不要嘗試諸如-exec之類的選項。find命令接受特殊的模式匹配字元,如,但你必須用單引號('')將它們括起來,以保護這些特殊字元不被shell自己的globbing功能所影響。(回顧一下第2.4.4節,shell在運行命令之前會展開globs)。
大多數系統也有查找文件的locate命令。locate不是實時搜索文件,而是搜索系統定期建立的索引。用locate搜索要比find快得多,但是如果你要找的文件比索引要新,locate就找不到它。
2.5.7 head和tail
head和tail命令允許你快速查看文件或數據流的一部分。例如,head /etc/passwd顯示密碼文件的前10行,tail /etc/passwd顯示最後10行。
要改變顯示的行數,使用-n選項,其中n是你想看的行數(例如,head -5 /etc/passwd)。要列印從第n行開始的行,使用tail +n。
2.5.8 sort
sort命令可以快速將文本文件的行數按字母數字順序排列。如果文件的行以數字開頭,並且你想按數字順序排序,使用-n選項。r選項可以反轉排序的順序。
2.6 改變你的密碼和shell
使用passwd命令來改變你的密碼。你會被要求提供你的舊密碼,然後兩次提示你的新密碼。
最好的密碼往往是容易記住的長 "廢話 "句子。密碼越長(就字元長度而言)越好;嘗試16個字元或更多。(在以前,你可以使用的字元數是有限的,所以建議你增加一些奇怪的字元之類的。)
你可以用chsh命令來改變你的shell(比如zsh、ksh或tcsh),但請記住,本書假設你運行的是bash,所以如果你做了改變,一些例子可能就不能用了。
Dot文件(隱藏文件)
如果你還沒有進入你的主目錄,就換成ls來看看,然後運行ls -a。你看到輸出的不同了嗎?當你運行ls而不使用-a時,你不會看到被稱為點文件的配置文件。這些文件和目錄的名稱都是以點(.)開頭的。常見的點文件有.bashrc和.login,還有一些點目錄,如.ssh。
點狀文件或目錄沒有什麼特別之處。一些程式預設不顯示它們,這樣你在列出你的主目錄的內容時就不會看到一個完整的混亂。例如,除非你使用-a選項,否則ls不會列出點文件。此外,除非你明確使用模式,如.*,否則shell globs不匹配點狀文件。
註意:你可能會遇到globs的問題,因為.匹配.和.(當前和父目錄)。你可能希望使用諸如.[^.]或.??*的模式來獲取除當前和父目錄之外的所有點狀文件。
2.8 環境和外殼變數
shell可以存儲臨時變數,稱為shell變數,包含文本字元串的值。shell變數對於跟蹤腳本中的數值非常有用,而且一些shell變數可以控制shell的行為方式。(例如,bash shell在顯示提示符之前會讀取PS1變數)。
要給shell變數賦值,可以使用等號(=)。下麵是一個簡單的例子:
$ STUFF=blah
前面的例子將名為STUFF的變數的值設置為blah。要訪問這個變數,使用$STUFF(例如,嘗試運行echo $STUFF)。你將在第11章中瞭解到shell變數的許多用途。
註意:在分配變數時,不要在=的周圍加上任何空格。
環境變數就像shell變數一樣,但它並不是專門針對shell的。Unix系統中的所有進程都有環境變數存儲。環境變數和shell變數的主要區別是,操作系統會將shell的所有環境變數傳遞給shell運行的程式,而shell變數不能在你運行的命令中被訪問。
你用shell的導出命令指定一個環境變數。例如,如果你想把$STUFF這個shell變數變成一個環境變數,可以用下麵的方法:
$ STUFF=blah
$ export STUFF
由於子進程繼承了父進程的環境變數,許多程式會讀取它們的配置和選項。例如,你可以把你最喜歡的less命令行選項放在LESS環境變數中,當你運行less時就會使用這些選項。(許多手冊中都有一個名為 "環境 "的章節來描述這些變數)。
2.9 命令路徑
PATH是一個特殊的環境變數,它包含了命令路徑(簡稱path),這是系統目錄列表,shell在試圖找到一個命令時,會搜索這個目錄。例如,當你運行ls時,shell會在PATH中列出的目錄中搜索ls程式。如果同名的程式出現在路徑中的幾個目錄中,shell會運行第一個匹配的程式。
如果你運行echo $PATH,你會看到路徑的組成部分是由冒號(:)分隔的。比如說
$ echo $PATH
/usr/local/bin:/usr/bin:/bin
要告訴shell在更多的地方尋找程式,可以改變PATH環境變數。例如,通過使用這個命令,你可以在路徑的開頭添加目錄dir,這樣shell就會在尋找其他PATH目錄之前尋找dir:
$ PATH=dir:$PATH
或者你可以在PATH變數的末尾加上目錄名,使Shell最後查找dir:
$ PATH=$PATH:dir
註意:如果你在修改路徑時錯誤地輸入了$PATH,你可能會意外地抹去整個路徑。如果發生這種情況,不要驚慌! 這種損害不是永久性的;你可以啟動一個新的shell。(為了達到持久的效果,你需要在編輯某個配置文件時輸入錯誤,即使這樣也不難糾正)。恢復正常的最簡單方法是關閉當前的終端視窗並啟動另一個。
特殊字元
當與他人討論Linux時,你應該知道一些你會遇到的特殊字元的名稱。如果你對這種事情感到有趣,請看 "Jargon File"(http://www.catb.org/jargon/html/)或其印刷品,《The New Hacker’s Dictionary》,第三版,作者Eric S. Raymond(MIT Press,1996)。
註意: 你經常會看到控制字元用圓點標記;例如,^C代表CTRL-C。
2.11 命令行編輯
當你使用shell的時候,註意到你可以使用左右方向鍵來編輯命令行,也可以使用上下箭頭來翻閱以前的命令。這在大多數Linux系統中是標準的。
- 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文本編輯器,即vi和Emacs。大多數Unix嚮導對他們選擇的編輯器很虔誠,但不要聽他們的。只要自己選擇就好。如果你選擇一個與你的工作方式相匹配的,你會發現它更容易學習。基本上,選擇歸結於此:
如果你想要一個幾乎可以做任何事情的編輯器,並且有廣泛的線上幫助,而且你不介意做一些額外的輸入來獲得這些功能,那就試試Emacs。
如果速度就是一切,那就試試vi;它 "玩 "起來有點像電子游戲。
學習vi和Vim編輯器: 阿諾德-羅賓斯、埃爾伯特-漢納和琳達-拉姆所寫的《Unix Text Processing》第七版(O'Reilly,2008),可以告訴你關於vi的一切。對於Emacs,使用線上教程:啟動Emacs,按CTRL-H,然後輸入T。或者閱讀《GNU Emacs Manual》第18版,作者是理查德-M-斯塔爾曼(自由軟體基金會,2018)。
還有一些更友好的編輯器,比如nano、Pico等。
註意:編輯文本是你第一次開始看到終端和GUI之間的區別的地方。像vi這樣的編輯器在終端視窗內運行,使用標準的終端I/O介面。GUI編輯器啟動他們自己的視窗並展示他們自己的界面,獨立於終端。Emacs預設在GUI中運行,但也會在終端視窗中運行。
2.13 獲得線上幫助
Linux系統有大量的文檔。對於基本的命令,手冊頁(或稱man頁)會告訴你你需要知道的東西。例如,要查看ls命令的手冊頁,請按以下方式運行man:
$ man ls
大多數手冊頁主要集中在參考信息上,也許有一些例子和交叉引用,但僅此而已。不要指望有什麼教程,也不要指望有什麼吸引人的文學風格。
當程式有許多選項時,手冊頁往往以某種系統的方式(例如,按字母順序)列出選項,但它不會告訴你哪些是重要的選項。如果你有耐心,你通常可以在手冊頁中找到你需要知道的東西。如果你沒有耐心,可以問朋友,或者花錢請人做你的朋友,這樣你就可以問他或她。
要按關鍵詞搜索手冊頁,使用-k選項:
$ 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列出了這些章節和它們的編號。
第1、5、7和8節應該是本書的良好補充。第4節可能用處不大,第6節如果再大一點就好了。如果你不是一個程式員,你可能無法使用第3節,但是一旦你在本書中閱讀了更多關於系統調用的內容,你可能就能理解第2節中的一些材料。
一些常見的術語有許多匹配的手冊頁面,跨越幾個章節。預設情況下,man會顯示它找到的第一個頁面。你可以按章節選擇手冊頁面。例如,要閱讀/etc/passwd文件描述(而不是passwd命令),你可以在頁面名稱前插入章節號,如:
$ man 5 passwd
手冊頁涵蓋了基本內容,但還有很多方法可以獲得線上幫助(除了在互聯網上搜索之外)。如果你只是在尋找某個命令的某個選項,可以嘗試在命令名稱後面輸入--help或-h(不同的命令有不同的選項)。你可能會得到大量的信息(如ls --help的情況),也可能找到你要找的東西。
前段時間,GNU項目認為它不太喜歡手冊頁,於是轉而使用另一種叫做info(或texinfo)的格式。這種文檔通常比典型的手冊頁更深入,但它可能更複雜。要訪問info手冊,請使用info的命令名:
$ info command
如果你不喜歡info閱讀器,你可以把輸出發送到less(只需添加 | less)。
有些軟體包將它們的可用文檔傾倒在/usr/share/doc中,而不考慮線上手冊系統,如man或info。如果你發現自己在搜索文檔,請查看你系統中的這個目錄--當然,也可以在網上搜索。
2.14 Shell的輸入和輸出
現在你已經熟悉了基本的Unix命令、文件和目錄,你準備學習如何重定向標準輸入和輸出。讓我們從標準輸出開始。
要把命令的輸出發送到文件而不是終端,請使用>重定向字元:
$ command > file
如果文件不存在,shell就會創建它。如果文件存在,shell會先刪除(clobbers)原始文件。(有些shell有參數可以防止clobber。例如,你可以輸入set -C來避免bash中的clobbering)。
你可以用">>重定向 "的語法將輸出附加到文件中而不是覆蓋它:
$ command >> file
這是方便的方法,當執行相關的命令序列時,可以將輸出收集在一個地方。
要把一個命令的標準輸出發送到另一個命令的標準輸入,可以使用管道字元(|)。要看這是如何工作的,請嘗試這兩條命令:
$ head /proc/cpuinfo
$ head /proc/cpuinfo | tr a-z A-Z
你可以通過你想要的管道命令發送輸出,只需在每個額外的命令前添加一個管道。
2.14.1 標準錯誤
偶爾,你可能會重定向標準輸出,但發現程式仍然會向終端列印一些東西。這被稱為標準錯誤(stderr);它是額外的輸出流,用於診斷和調試。例如,這個命令產生了錯誤:
$ ls /fffffffff > f
完成後,f應該是空的,但你仍然在終端上看到以下作為標準錯誤的錯誤信息:
ls: cannot access /fffffffff: No such file or directory
如果你願意,你可以重定向標準錯誤。例如,要把標準輸出發送到f,把標準錯誤發送到e,使用2>語法,像這樣:
$ ls /fffffffff > f 2> e
數字2指定了shell所修改的流ID。流ID 1是標準輸出(預設),而2是標準錯誤。
你也可以用>&符號將標準錯誤發送到與stdout相同的地方。例如,要把標準輸出和標準錯誤都發送到名為f的文件中,請嘗試這個命令:
$ ls /fffffffff > f 2>&1
2.14.2 標準輸入重定向
要將文件引導到程式的標準輸入,請使用<操作符:
$ head < /proc/cpuinfo
你偶爾會遇到需要這種重定向的程式,但由於大多數Unix命令都接受文件名作為參數,這種情況並不常見。例如,前面的命令可以寫成head /proc/cpuinfo。
2.15 理解錯誤信息
當你在類似Unix的系統(如Linux)上遇到問題時,你必須閱讀錯誤信息。與其他操作系統的信息不同,Unix的錯誤通常準確地告訴你出了什麼問題。
2.15.1 Unix錯誤信息的剖析
大多數Unix程式產生和報告相同的基本錯誤信息,但在任何兩個程式的輸出之間可能有細微的差別。這裡有一個例子,你肯定會以某種形式遇到:
$ ls /dsafsda
ls: cannot access /dsafsda: No such file or directory
這條信息有三個組成部分:
- 程式名稱,ls。有些程式省略了這一識別信息,當你編寫shell腳本時,這可能會讓人感到厭煩,但這其實並不是什麼大問題。
- 文件名,/dsafsda,這是一個更具體的信息。這個路徑有一個問題。
- 錯誤No such file or directory表明文件名有問題。
把它們放在一起,你會得到這樣的信息:“ls tried to open /dsafsda but couldn’t because it doesn’t exist.” 。這可能看起來很明顯,但當你運行包括不同名稱的錯誤命令的shell腳本時,這些信息會變得有點混亂。
在排除錯誤時,總是先解決第一個錯誤。有些程式在報告一系列其他問題之前,會報告它們不能做任何事情。例如,假設你運行一個名為scumd的虛構程式,你看到了這樣的錯誤信息:
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系統對文件和目錄沒有什麼區別,這個錯誤信息涵蓋了兩種情況。當你試圖讀取不存在的文件時,當你試圖改變到不存在的目錄時,當你試圖寫到不存在的目錄中的文件時,你都會得到它,等等。這種錯誤也被稱為ENOENT,是 "Error NO ENTity "的簡稱。
註意:如果你對系統調用感興趣,這通常是open()返回ENOENT的結果。關於它可能遇到的錯誤的更多信息,請參見open(2)手冊頁。
File exists
在這種情況下,你可能試圖創建已經存在的文件。當你試圖創建與文件同名的目錄時,這很常見。
Not a directory, Is a directory
當你試圖把文件作為目錄,或把目錄作為文件時,這些信息就會彈出來。例如:
$ touch a
$ touch a/b
touch: a/b: Not a directory
註意,這個錯誤信息只適用於a/b的a部分。當你遇到這個問題時,你可能需要稍微挖掘一下,找到被當作目錄的路徑組件。
No space left on device
你沒有磁碟空間了。
Permission denied
當你試圖讀取或寫入不允許訪問的文件或目錄時(你的許可權不足),你會得到這個錯誤。當你試圖執行沒有設置執行位的文件時,也會顯示這個錯誤(即使你可以讀取該文件)。你將在第2.17節中閱讀更多關於許可權的內容。
Operation not permitted
這通常發生在你試圖殺死不屬於你的進程時。
Segmentation fault, Bus error
分段故障本質上意味著編寫你剛剛運行的程式的人在某個地方搞砸了。該程式試圖訪問它不允許觸及的記憶體的某個部分,而操作系統將其殺死。同樣,匯流排錯誤意味著程式試圖以一種不應該的方式訪問一些記憶體。當你得到這些錯誤之一時,你可能是給了程式一些它不期望的輸入。在極少數情況下,可能是記憶體硬體出現了故障。
2.16 列出和操縱進程
回顧第一章,進程是正在運行的程式。系統中的每個進程都有一個數字的進程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時間,以分和秒為單位。換句話說,該進程在處理器上運行指令的總時間。請記住,由於進程不是持續運行的,這與進程開始後的時間(或 "壁鐘時間")不同。
- COMMAND 這個看起來很明顯,是用來運行程式的命令,但是要註意,進程可以改變這個欄位的原始值。此外,shell可以進行glob擴展,這個欄位將反映擴展後的命令,而不是你在提示符下輸入的命令。
註意:PID對於系統上運行的每個進程都是唯一的。然而,在進程終止後,內核最終可以為一個新的進程重新使用這個PID。
2.16.1 ps命令選項
ps命令有很多選項。為了使事情更加混亂,你可以用三種不同的方式指定選項--Unix、BSD和GNU。許多人認為BSD風格是最舒服的(也許是因為它涉及到較少的輸入),所以這就是我們在本書中要使用的風格。下麵是一些最有用的選項組合:
- ps x 顯示所有正在運行的進程。
- ps ax 顯示系統中的所有進程,而不僅僅是你自己的進程。
- ps u 包括更詳細的進程信息。
- ps w 顯示完整的命令名稱,而不僅僅是適合一行的內容。
與其他程式一樣,你可以組合選項,如ps aux和ps auxw。
要檢查特定的進程,可以在ps命令的參數列表中添加其PID。例如,要檢查當前的shell進程,你可以使用ps u $$($$是一個shell變數,評估為當前shell的PID)。你會在第8章中找到關於管理命令top和lsof的信息。這些命令對於定位進程是很有用的,即使你在做系統維護以外的事情時也是如此。
2.16.2 進程終止
要終止進程,你可以用kill命令向它發送信號--從內核向進程發送的信息。在大多數情況下,你所需要做的就是這樣:
$ kill pid
有許多類型的信號。預設的(上面使用的)是TERM,即終止。你可以通過給kill增個額外的選項來發送不同的信號。例如,要凍結進程而不是終止它,可以使用STOP信號:
$ kill -STOP pid
停止的進程仍然在記憶體中,準備繼續它的工作。使用CONT信號來繼續運行該進程:
$ kill -CONT pid
註意:使用CTRL-C來終止正在當前終端運行的進程,與使用kill來結束進程的INT(中斷)信號是一樣的。
內核在接收到信號時給大多數進程一個機會來清理自己(通過信號處理機制)。然而,一些進程可能會選擇非終結性的動作來響應信號,在試圖處理信號的過程中陷入困境,或者乾脆忽略它,所以你可能會發現進程在你試圖終止它之後仍然運行。如果發生這種情況,而你又確實需要殺死進程,那麼終止它的最粗暴的方法就是使用KILL信號。與其他信號不同,KILL不能被忽略;事實上,操作系統甚至不給進程一個機會。內核會直接終止該進程,並將其從記憶體中強行刪除。使用這種方法只是作為最後的手段。
你可能會看到其他用戶用kill輸入數字而不是名字--例如,kill -9而不是kill -KILL。這是因為內核使用數字來表示不同的信號;如果你知道你想發送的信號的編號,你可以這樣使用kill。運行kill -l來獲得信號編號與名稱的映射。
2.16.3 作業控制
Shell支持作業控制,這是一種通過使用各種按鍵和命令向程式發送TSTP(類似於STOP)和CONT信號的方法。這允許你在你使用的程式之間暫停和切換。例如,你可以用CTRL-Z發送一個TSTP信號,然後通過輸入fg(移至前臺)或bg(移至後臺;見下一節)再次啟動程式。但是,儘管它很有用,而且許多有經驗的用戶也有這樣的習慣,作業控制並不是必須的,而且對初學者來說可能會感到困惑: 用戶經常按CTRL-Z而不是CTRL-C,忘記了他們正在運行的東西,最終導致許多進程被中止。
註意:要查看你是否不小心暫停了當前終端上的任何進程,可以運行jobs命令。
如果你想運行多個程式,在單獨的終端視窗中運行每個程式,把非互動式進程放在後臺(如下一節所述),並學會使用screen和tmux工具。
2.16.4 背景進程
通常,當你從shell中運行Unix命令時,在程式執行完畢之前,你不會再得到shell提示。然而,你可以將進程從shell中分離出來,用安培號(&)把它放在 "後臺";這樣你就會得到提示符。例如,如果你有需要用 gunzip 解壓的大文件(你會在第 2.18 節中看到這個),並且你想在它運行時做一些其他的事情,可以運行這樣的命令:
$ gunzip file.gz &
shell應該通過列印新的後臺進程的PID來響應,並且提示應該立即返回,這樣你就可以繼續工作了。如果該進程需要很長的時間,它甚至可以在你註銷後繼續運行,如果你必須運行進行大量數字計算的程式,這就特別方便了。如果進程在你註銷或關閉終端視窗之前完成,shell通常會通知你,這取決於你的設置。
註意如果你正在遠程訪問一臺機器,並希望在你註銷時繼續運行一個程式,你可能需要使用nohup命令;詳情請見其手冊頁。
bash shell和大多數全屏交互程式都支持CTRL-L來重繪整個屏幕。如果一個程式是從標準輸入中讀取的,CTRL-R通常會重繪當前行,但在錯誤的時間按錯誤的順序會讓你處於比以前更糟糕的情況。例如,在bash提示符下輸入CTRL-R會使你進入反向的isearch模式(按ESC退出)。
2.17 文件模式和許可權
每個Unix文件都有一組許可權,決定你是否可以讀取、寫入或運行該文件。運行ls -l可以顯示這些許可權。下麵是這樣顯示的例子:
-rw-r-r-1 1 juser somegroup 7041 Mar 26 19:34 endnotes.html
文件的模式1表示該文件的許可權和一些額外的信息。該模式有四個部分,如圖2-1所示。
圖2-1: 文件模式的各個
模式的第一個字元是文件類型。在這個位置上的破折號(-),如圖所示,表示一個普通的文件,意味著這個文件沒有什麼特別之處;它只是二進位或文本數據。這是迄今為止最常見的文件類型。目錄也很常見,在文件類型槽中用d表示。(第3.1節列出了其餘的文件類型)。
文件模式的其餘部分包含許可權,分為三組:用戶、組和其他,按順序排列。例如,例子中的rw-字元是用戶許可權,後面的r--字元是組的許可權,最後的r--字元是其他許可權。
每個許可權集可以包含四種基本表示:
- r表示文件是可讀的。
- w表示該文件是可寫的。
- x表示該文件是可執行的(你可以把它作為一個程式運行)。
- 表示 "無"(更確切地說,這組中的那個許可權沒有被授予)。
用戶許可權(第一組)與擁有該文件的用戶有關。在前面的例子中,那就是juser。第二組,組許可權,是針對文件的組(本例中的somegroup)。該組中的任何用戶都可以利用這些許可權。(使用groups命令查看你所在的組,更多信息見7.3.5節)。
系統中的每個人都可以根據第三組許可權,即其他許可權進行訪問,這些許可權有時被稱為世界許可權。
註意:每個讀、寫和執行的許可權槽有時被稱為一個許可權位,因為操作系統中的底層表示是一系列的位。因此,你可能會聽到人們把部分許可權稱為 "讀位"。
一些可執行文件在用戶許可權列表中有一個s,而不是x,這表明該可執行文件是setuid,意味著當你執行該程式時,它的運行就好像文件所有者是用戶而不是你。許多程式利用這個setuid位,以root身份運行,以獲得他們需要的許可權來改變系統文件。比如passwd程式,它需要改變/etc/passwd文件。
2.17.1 修改許可權
要改變一個文件或目錄的許可權,可以使用chmod命令。首先,挑選你想改變的許可權集,然後挑選要改變的位。例如,要給文件增加組(g)和世界(o,代表 "其他")閱讀(r)許可權,你可以運行這兩條命令:
$ chmod g+r file
$ chmod o+r file
或者你可以一次完成:
$ chmod go+r file
要刪除這些許可權,使用go-r而不是go+r。
註意:顯然,你不應該讓文件成為世界可寫文件,因為這樣做會使你系統中的任何人都可以改變它們。但是,這是否也允許任何連接到互聯網的人改變它們呢?可能不會,除非你的系統有一個網路安全漏洞。在這種情況下,文件許可權反正也幫不了你。
你有時可能會看到有人用數字來改變許可權,例如:
$ chmod 644 file
這被稱為絕對改變,因為它一次性設置了所有許可權位。要理解這一點,你需要知道如何以八進位形式表示許可權位(每個數字代表以8為基數的數字,0到7,並對應許可權集)。參見chmod(1)手冊頁或info手冊瞭解更多。
如果你喜歡使用絕對模式,你其實不需要知道如何構建這些模式;只要記住你最常使用的模式即可。表2-4列出了最常見的幾種模式。
表2-4:絕對許可權模式
目錄也有許可權。如果目錄是可讀的,你可以列出該目錄的內容,但只有當該目錄是可執行的,你才能訪問該目錄中的文件。在大多數情況下,你都需要這兩種許可權;人們在設置目錄的許可權時常犯的錯誤是,在使用絕對模式時不小心刪除了執行許可權。
最後,你可以用umask shell命令指定一組預設的許可權,它對你創建的任何新文件應用一組預定義的許可權。一般來說,如果你希望每個人都能看到你創建的所有文件和目錄,就使用umask 022,如果你不希望,就使用umask 077。如果你想使你所希望的許可權掩碼適用於新的視窗和以後的會話,你需要把帶有所需模式的umask命令放在你的某個啟動文件中,如第13章中所討論的。
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不存在(除了ls somedir,這個命令愚蠢地告訴你somedir就是somedir)。這可能是令人困惑的,因為你可以看到名為somedir的東西就在你眼前。
這並不是符號鏈接可能令人困惑的唯一方式。另一個問題是,你不能僅僅通過查看鏈接的名稱來確定鏈接目標的特征;你必須跟蹤鏈接,看它是否指向一個文件或目錄。你的系統也可能有指向其他鏈接的鏈接,這被稱為鏈式符號鏈接,當你試圖追蹤它們時,可能是個麻煩。
要創建一個從target到linkname的符號鏈接,使用ln -s,如下所示:
$ ln -s target linkname
linkname參數是符號鏈接的名稱,target參數是鏈接指向的文件或目錄的路徑,而-s標誌則指定了符號鏈接(見後面的警告)。
當製作符號鏈接時,在運行命令前要檢查兩次,因為有幾種情況可能出錯。例如,如果你不小心顛倒了參數的順序(ln -s linkname target),如果linkname是已經存在的目錄,你就會遇到一些麻煩。如果是這種情況(經常如此),ln會在linkname內創建一個名為target的鏈接,而且這個鏈接會指向自己,除非linkname是完整的路徑。如果你在創建一個目錄的符號鏈接時出了問題,請檢查該目錄是否有錯誤的符號鏈接並刪除它們。
當你不知道它們的存在時,符號鏈接也會引起頭疼。例如,你可以很容易地編輯你認為是文件的副本,但實際上是原文件的一個符號鏈接。
警告:創建符號鏈接時不要忘記-s選項。沒有它,ln會創建硬鏈接,給文件增加真實的文件名。新的文件名具有舊文件名的狀態;它直接指向(鏈接)文件數據,而不是像符號鏈接那樣指向另一個文件名。硬鏈接可能比符號鏈接更令人困惑。除非你瞭解第4.6節的內容,否則要避免使用它們。
有了所有這些關於符號鏈接的警告,你可能想知道為什麼有人會想使用它們。事實證明,它們的缺陷大大超過了它們為組織文件所提供的力量,以及它們輕鬆修補小問題的能力。一個常見的使用情況是,當一個程式期望找到一個特定的文件或目錄,而這個文件或目錄已經存在於你系統的其他地方。你不想做一個拷貝,如果你不能改變程式,你可以直接從它那裡創建一個符號鏈接到實際的文件或目錄位置。
2.18 歸檔和壓縮文件
現在你已經瞭解了文件、許可權和可能的錯誤,你需要掌握gzip和tar,這兩個常用的工具用於壓縮和捆綁文件和目錄。
2.18.1 gzip
gzip(GNU Zip)這個程式是目前標準的 Unix 壓縮程式之一。以.gz結尾的文件是GNU Zip壓縮文件。使用 gunzip file.gz 來解壓縮
2.18.2 tar
與其他操作系統的 ZIP 程式不同,gzip 不創建文件的檔案;也就是說,它不把多個文件和目錄打包成文件。要創建歸檔文件,用tar代替:
$ tar cvf archive.tar file1 file2 ...
用tar創建的歸檔文件通常有.tar尾碼(這是慣例,不是必須的)。例如,在前面的命令中,file1、file2等是你希望歸檔在
v 標誌激活了粗略的診斷輸出,使 tar 在遇到文件和目錄時列印它們的名字。添加另一個v會使tar列印細節,如文件大小和許可權。如果你不想讓tar告訴你它在做什麼,省略v標誌。
f標誌表示文件選項。命令行中f標誌後的下一個參數必須是供tar創建的歸檔文件(在前面的例子中,它是
要用tar解壓.tar文件,使用x標誌:
$ tar xvf archive.tar
在這個命令中,x標誌使tar進入提取(解包)模式。你可以通過在命令行末尾輸入各個部分的名稱來提取檔案的各個部分,但你必須知道它們的確切名稱。(要確定這一點,請看接下來描述的內容表模式)。
註意:當使用提取模式時,記住tar在提取內容後不會刪除存檔的.tar文件。
在解壓之前,用內容表模式檢查 .tar 文件的內容通常是個好主意,使用 t 標誌而不是 x 標誌。這種模式會驗證歸檔文件的基本完整性,並列印出裡面所有文件的名稱。如果你不在解壓前測試歸檔文件,你可能最終會把一大堆亂七八糟的文件倒入當前目錄,這可能真的很難清理。
當你用t模式檢查歸檔文件時,要確認所有的文件都在合理的目錄結構中;也就是說,歸檔文件中的所有文件路徑名都應該以同一個目錄開始。如果你不確定,可以創建一個臨時目錄,換到這個目錄,然後再解壓。(如果歸檔文件沒有造成混亂,你總是可以使用mv * ...)。
當解壓時,考慮使用p選項來保留許可權。在解壓縮模式下使用這個選項,可以覆蓋你的umask,得到存檔中指定的確切許可權。當你以超級用戶身份工作時,p選項是預設的。如果你在以超級用戶身份解壓歸檔文件時遇到許可權和所有權方面的問題,請確保你一直等到命令終止並得到shell提示。儘管你可能只想解壓縮文件的一小部分,但tar必須運行整個文件,你不能打斷這個過程,因為它只有在檢查了整個壓縮文件後才設置許可權。
把本節中所有的tar選項和模式都記在腦子裡。如果你有困難,做一些快閃記憶體卡。這可能聽起來像小學生,但避免這個命令的粗心錯誤是非常重要的。
2.18.3 壓縮檔案(.tar.gz)
許多初學者發現檔案通常是壓縮的,文件名以.tar.gz結尾,這讓他們感到困惑。要解開壓縮檔案,要從右邊到左邊;先擺脫.gz,然後再擔心.tar。 例如,這兩個命令解壓和解開
$ gunzip file.tar.gz
$ tar xvf file.tar
剛開始的時候,一次做一個步驟就可以了,先運行gunzip來解壓,然後運行tar來驗證和解包。要創建一個壓縮檔案,做相反的事情:先運行tar,然後再運行gzip。經常這樣做,你很快就會記住歸檔和壓縮過程是如何進行的。但是,即使你不經常這樣做,你也可以看到所有的輸入會變得多麼令人厭煩,你會開始尋找捷徑。現在讓我們來看看這些。
2.18.4 zcat
剛纔的方法並不是在壓縮檔案中調用tar的最快或最有效的方法,它浪費了磁碟空間和內核I/O時間。更好的方法是將歸檔和壓縮功能與一個流水線結合起來。例如,這個命令流水線解壓
$ zcat file.tar.gz | tar xvf -
zcat命令與gunzip -dc相同。-d選項解壓,-c選項將結果發送到標準輸出(在本例中,發送到tar命令)。
因為使用zcat非常普遍,Linux中的tar版本有一個快捷方式。你可以用z作為選項,在歸檔文件上自動調用gzip;這對提取歸檔文件(用tar的x或t模式)和創建歸檔文件(用c)都有效。例如,用下麵的方法來驗證壓縮的存檔:
$ tar ztvf file.tar.gz
$ tar zxvf file.tar.gz # 解壓
然而,試著記住,在使用這個快捷方式時,你實際上是在執行兩個步驟。
註意:.tgz文件和.tar.gz文件是一樣的。這個尾碼是為了適應FAT(基於MS-DOS)文件系統。
2.18.5 其他壓縮工具
還有兩個壓縮程式是xz和bzip2,其壓縮文件分別以.xz和.bz2結尾。雖然比gzip稍慢,但這些程式通常會將文本文件壓縮得更多一些。要使用的解壓程式是unxz和bunzip2,這兩個程式的選項與它們的gzip對應程式足夠接近,你不需要學習任何新東西。
大多數Linux發行版都帶有與Windows系統上的ZIP檔案相容的zip和unzip程式。它們適用於通常的.zip文件,以及以.exe結尾的自解壓檔案。但是,如果你遇到一個以.Z結尾的文件,你就發現了一個由壓縮程式創建的遺跡,它曾經是Unix的標準。gunzip程式可以解壓這些文件,但gzip不會創建它們。
2.19 Linux目錄層次結構要點
現在你知道瞭如何檢查文件、改變目錄和閱讀手冊頁,你準備開始探索你的系統文件和目錄。Linux目錄結構的細節在文件系統層次標準或FHS(https://refspecs.linuxfoundation.org/fhs.shtml)中作了概述,但現在簡要介紹一下就足夠了。
圖2-2提供了層次結構的簡化概覽,顯示了/、/usr和/var下的一些目錄。請註意,/usr下的目錄結構包含一些與/相同的目錄名稱。
圖2-2:Linux目錄層次結構
下麵是根目錄中最重要的子目錄:
- /bin 包含隨時可以運行的程式(也稱為可執行程式),包括大多數基本的Unix命令,如ls和cp。/bin中的大多數程式都是二進位格式,由C語言編譯器創建,但有些是現代系統中的shell腳本。
- /dev 包含設備文件。你將在第3章中進一步瞭解這些文件。
- /etc 這個核心系統配置目錄(發音為EHT-see)包含用戶密碼、啟動、設備、網路和其他設置文件。
- /home 存放普通用戶的家庭(個人)目錄。大多數Unix安裝都符合這個標準。
- /lib 是library的縮寫,這個目錄存放包含可執行文件可以使用的代碼的庫文件。有兩種類型的庫:靜態和共用。/lib目錄應該只包含共用庫,但其他lib目錄,如/usr/lib,包含這兩種類型以及其他輔助文件。(我們將在第15章詳細討論共用庫)。
- /proc 通過一個可瀏覽的目錄和文件界面提供系統統計數據。Linux上的/proc子目錄結構大部分是獨特的,但許多其他Unix變體也有類似的功能。/proc目錄包含了關於當前運行進程的信息以及一些內核參數。
- /run 包含系統特有的運行數據,包括某些進程ID、套接字文件、狀態記錄,以及在許多情況下,系統日誌。這是最近才添加到根目錄中的;在舊系統中,你可以在/var/run中找到它。在較新的系統中,/var/run是指向/run的符號鏈接。
- /sys 這個目錄與/proc類似,它