計算機系統管理員的一個主要任務就是保護系統的數據安全,其中一種方法是通過時時備份系統文件,來保護 數據。即使你不是一名系統管理員,像做做拷貝或者在各個位置和設備之間移動大量的文件,通常也是很有幫助的。 在這一章中,我們將會看看幾個經常用來管理文件集合的程序。
它們就是文件壓縮程序:
> * gzip – 壓縮或者展開文件
> * bzip2 – 塊排序文件壓縮器
歸檔程序:
> * tar – 磁帶打包工具
> * zip – 打包和壓縮文件
還有文件同步程序:
> * rsync – 同步遠端文件和目錄
## 壓縮文件
縱觀計算領域的發展歷史,人們努力想把最多的數據存放到到最小的可用空間中,不管是內存,存儲設備 還是網絡帶寬。今天我們把許多數據服務都看作是理所當然的事情,但是諸如便攜式音樂播放器, 高清電視,或寬帶網絡之類的存在都應歸功于高效的數據壓縮技術。
數據壓縮就是一個刪除冗余數據的過程。讓我們考慮一個假想的例子,比方說我們有一張100*100像素的 純黑的圖片文件。根據數據存儲方案(假定每個像素占24位,或者3個字節),那么這張圖像將會占用 30,000個字節的存儲空間:
~~~
100 * 100 * 3 = 30,000
~~~
一張單色圖像包含的數據全是多余的。我們要是聰明的話,可以用這種方法來編碼這些數據, 我們只要簡單地描述這個事實,我們有3萬個黑色的像素數據塊。所以,我們不存儲包含3萬個0 (通常在圖像文件中,黑色由0來表示)的數據塊,取而代之,我們把這些數據壓縮為數字30,000, 后跟一個0,來表示我們的數據。這種數據壓縮方案被稱為游程編碼,是一種最基本的壓縮技術。
壓縮算法(數學技巧被用來執行壓縮任務)分為兩大類,無損壓縮和有損壓縮。無損壓縮保留了 原始文件的所有數據。這意味著,當還原一個壓縮文件的時候,還原的文件與原文件一模一樣。 而另一方面,有損壓縮,執行壓縮操作時會刪除數據,允許更大的壓縮。當一個有損文件被還原的時候, 它與原文件不相匹配; 相反,它是一個近似值。有損壓縮的例子有 JPEG(圖像)文件和 MP3(音頻)文件。 在我們的討論中,我們將看看完全無損壓縮,因為計算機中的大多數數據是不能容忍丟失任何數據的。
### gzip
這個 gzip 程序被用來壓縮一個或多個文件。當執行 gzip 命令時,則原始文件的壓縮版會替代原始文件。 相對應的 gunzip 程序被用來把壓縮文件復原為沒有被壓縮的版本。這里有個例子:
~~~
[me@linuxbox ~]$ ls -l /etc > foo.txt
[me@linuxbox ~]$ ls -l foo.*
-rw-r--r-- 1 me me 15738 2008-10-14 07:15 foo.txt
[me@linuxbox ~]$ gzip foo.txt
[me@linuxbox ~]$ ls -l foo.*
-rw-r--r-- 1 me me 3230 2008-10-14 07:15 foo.txt.gz
[me@linuxbox ~]$ gunzip foo.txt.gz
[me@linuxbox ~]$ ls -l foo.*
-rw-r--r-- 1 me me 15738 2008-10-14 07:15 foo.txt
~~~
在這個例子里,我們創建了一個名為 foo.txt 的文本文件,其內容包含一個目錄的列表清單。 接下來,我們運行 gzip 命令,它會把原始文件替換為一個叫做 foo.txt.gz 的壓縮文件。在 foo.* 文件列表中,我們看到原始文件已經被壓縮文件替代了,并將這個壓縮文件大約是原始 文件的十五分之一。我們也能看到壓縮文件與原始文件有著相同的權限和時間戳。
接下來,我們運行 gunzip 程序來解壓縮文件。隨后,我們能見到壓縮文件已經被原始文件替代了, 同樣地保留了相同的權限和時間戳。
gzip 命令有許多選項。這里列出了一些:
表19-1: gzip 選項
| 選項 | 說明 |
|---------|------------|
| -c | 把輸出寫入到標準輸出,并且保留原始文件。也有可能用--stdout 和--to-stdout 選項來指定。 |
| -d | 解壓縮。正如 gunzip 命令一樣。也可以用--decompress 或者--uncompress 選項來指定. |
| -f | 強制壓縮,即使原始文件的壓縮文件已經存在了,也要執行。也可以用--force 選項來指定。 |
| -h | 顯示用法信息。也可用--help 選項來指定。 |
| -l | 列出每個被壓縮文件的壓縮數據。也可用--list 選項。 |
| -r | 若命令的一個或多個參數是目錄,則遞歸地壓縮目錄中的文件。也可用--recursive 選項來指定。 |
| -t | 測試壓縮文件的完整性。也可用--test 選項來指定。 |
| -v | 顯示壓縮過程中的信息。也可用--verbose 選項來指定。 |
| -number | 設置壓縮指數。number 是一個在1(最快,最小壓縮)到9(最慢,最大壓縮)之間的整數。 數值1和9也可以各自用--fast 和--best 選項來表示。默認值是整數6。 |
返回到我們之前的例子中:
~~~
[me@linuxbox ~]$ gzip foo.txt
[me@linuxbox ~]$ gzip -tv foo.txt.gz
foo.txt.gz: OK
[me@linuxbox ~]$ gzip -d foo.txt.gz
~~~
這里,我們用壓縮文件來替代文件 foo.txt,壓縮文件名為 foo.txt.gz。下一步,我們測試了壓縮文件 的完整性,使用了-t 和-v 選項。
~~~
[me@linuxbox ~]$ ls -l /etc | gzip > foo.txt.gz
~~~
這個命令創建了一個目錄列表的壓縮文件。
這個 gunzip 程序,會解壓縮 gzip 文件,假定那些文件名的擴展名是.gz,所以沒有必要指定它, 只要指定的名字與現有的未壓縮文件不沖突就可以:
~~~
[me@linuxbox ~]$ gunzip foo.txt
~~~
如果我們的目標只是為了瀏覽一下壓縮文本文件的內容,我們可以這樣做:
~~~
[me@linuxbox ~]$ gunzip -c foo.txt | less
~~~
另外,對應于 gzip 還有一個程序,叫做 zcat,它等同于帶有-c 選項的 gunzip 命令。 它可以被用來如 cat 命令作用于 gzip 壓縮文件:
~~~
[me@linuxbox ~]$ zcat foo.txt.gz | less
~~~
* * *
小貼士:?還有一個 zless 程序。它與上面的管道線有相同的功能。
* * *
### bzip2
這個 bzip2 程序,由 Julian Seward 開發,與 gzip 程序相似,但是使用了不同的壓縮算法, 舍棄了壓縮速度,而實現了更高的壓縮級別。在大多數情況下,它的工作模式等同于 gzip。 由 bzip2 壓縮的文件,用擴展名 .bz2 來表示:
~~~
[me@linuxbox ~]$ ls -l /etc > foo.txt
[me@linuxbox ~]$ ls -l foo.txt
-rw-r--r-- 1 me me 15738 2008-10-17 13:51 foo.txt
[me@linuxbox ~]$ bzip2 foo.txt
[me@linuxbox ~]$ ls -l foo.txt.bz2
-rw-r--r-- 1 me me 2792 2008-10-17 13:51 foo.txt.bz2
[me@linuxbox ~]$ bunzip2 foo.txt.bz2
~~~
正如我們所看到的,bzip2 程序使用起來和 gzip 程序一樣。我們之前討論的 gzip 程序的所有選項(除了-r) ,bzip2 程序同樣也支持。注意,然而,壓縮級別選項(-number)對于 bzip2 程序來說,有少許不同的含義。 伴隨著 bzip2 程序,有 bunzip2 和 bzcat 程序來解壓縮文件。bzip2 文件也帶有 bzip2recover 程序,其會 試圖恢復受損的 .bz2 文件。
> 不要強迫性壓縮
>
> 我偶然見到人們試圖用高效的壓縮算法,來壓縮一個已經被壓縮過的文件,通過這樣做:
>
> $ gzip picture.jpg
>
> 不要這樣。你可能只是在浪費時間和空間!如果你再次壓縮已經壓縮過的文件,實際上你 會得到一個更大的文件。這是因為所有的壓縮技術都會涉及一些開銷,文件中會被添加描述 此次壓縮過程的信息。如果你試圖壓縮一個已經不包含多余信息的文件,那么再次壓縮不會節省 空間,以抵消額外的花費。
## 歸檔文件
一個常見的,與文件壓縮結合一塊使用的文件管理任務是歸檔。歸檔就是收集許多文件,并把它們 捆綁成一個大文件的過程。歸檔經常作為系統備份的一部分來使用。當把舊數據從一個系統移到某 種類型的長期存儲設備中時,也會用到歸檔程序。
### tar
在類 Unix 的軟件世界中,這個 tar 程序是用來歸檔文件的經典工具。它的名字,是 tape archive 的簡稱,揭示了它的根源,它是一款制作磁帶備份的工具。而它仍然被用來完成傳統任務, 它也同樣適用于其它的存儲設備。我們經常看到擴展名為 .tar 或者 .tgz 的文件,它們各自表示“普通” 的 tar 包和被 gzip 程序壓縮過的 tar 包。一個 tar 包可以由一組獨立的文件,一個或者多個目錄,或者 兩者混合體組成。命令語法如下:
~~~
tar mode[options] pathname...
~~~
這里的 mode 是指以下操作模式(這里只展示了一部分,查看 tar 的手冊來得到完整列表)之一:
表19-2: tar 模式
| 模式 | 說明 |
|---------|------------|
| c | 為文件和/或目錄列表創建歸檔文件。 |
| x | 抽取歸檔文件。 |
| r | 追加具體的路徑到歸檔文件的末尾。 |
| t | 列出歸檔文件的內容。 |
tar 命令使用了稍微有點奇怪的方式來表達它的選項,所以我們需要一些例子來展示它是 怎樣工作的。首先,讓我們重新創建之前我們用過的操練場:
~~~
[me@linuxbox ~]$ mkdir -p playground/dir-{00{1..9},0{10..99},100}
[me@linuxbox ~]$ touch playground/dir-{00{1..9},0{10..99},100}/file-{A-Z}
~~~
下一步,讓我們創建整個操練場的 tar 包:
~~~
[me@linuxbox ~]$ tar cf playground.tar playground
~~~
這個命令創建了一個名為 playground.tar 的 tar 包,其包含整個 playground 目錄層次結果。我們 可以看到模式 c 和選項 f,其被用來指定這個 tar 包的名字,模式和選項可以寫在一起,而且不 需要開頭的短橫線。注意,然而,必須首先指定模式,然后才是其它的選項。
要想列出歸檔文件的內容,我們可以這樣做:
~~~
[me@linuxbox ~]$ tar tf playground.tar
~~~
為了得到更詳細的列表信息,我們可以添加選項 v:
~~~
[me@linuxbox ~]$ tar tvf playground.tar
~~~
現在,抽取 tar 包 playground 到一個新位置。我們先創建一個名為 foo 的新目錄,更改目錄, 然后抽取 tar 包中的文件:
~~~
[me@linuxbox ~]$ mkdir foo
[me@linuxbox ~]$ cd foo
[me@linuxbox ~]$ tar xf ../playground.tar
[me@linuxbox ~]$ ls
playground
~~~
如果我們檢查 ~/foo/playground 目錄中的內容,會看到這個歸檔文件已經被成功地安裝了,就是創建了 一個精確的原始文件的副本。有一個警告,然而:除非你是超級用戶,要不然從歸檔文件中抽取的文件 和目錄的所有權由執行此復原操作的用戶所擁有,而不屬于原始所有者。
tar 命令另一個有趣的行為是它處理歸檔文件路徑名的方式。默認情況下,路徑名是相對的,而不是絕對 路徑。當創建歸檔文件的時候,tar 命令會簡單地刪除路徑名開頭的斜杠。為了說明問題,我們將會 重新創建我們的歸檔文件,這次指定一個絕對路徑:
~~~
[me@linuxbox foo]$ cd
[me@linuxbox ~]$ tar cf playground2.tar ~/playground
~~~
記住,當按下回車鍵后,~/playground 會展開成 /home/me/playground,所以我們將會得到一個 絕對路徑名。接下來,和之前一樣我們會抽取歸檔文件,觀察發生什么事情:
~~~
[me@linuxbox ~]$ cd foo
[me@linuxbox foo]$ tar xf ../playground2.tar
[me@linuxbox foo]$ ls
home playground
[me@linuxbox foo]$ ls home
me
[me@linuxbox foo]$ ls home/me
playground
~~~
這里我們看到當我們抽取第二個歸檔文件時,它重新創建了 home/me/playground 目錄, 相對于我們當前的工作目錄,~/foo,而不是相對于 root 目錄,作為帶有絕對路徑名的案例。 這看起來似乎是一種奇怪的工作方式,但事實上這種方式很有用,因為這樣就允許我們抽取文件 到任意位置,而不是強制地把抽取的文件放置到原始目錄下。加上 verbose(v)選項,重做 這個練習,將會展現更加詳細的信息。
讓我們考慮一個假設,tar 命令的實際應用。假定我們想要復制家目錄及其內容到另一個系統中, 并且有一個大容量的 USB 硬盤,可以把它作為傳輸工具。在現代 Linux 系統中, 這個硬盤會被“自動地”掛載到 /media 目錄下。我們也假定硬盤中有一個名為 BigDisk 的邏輯卷。 為了制作 tar 包,我們可以這樣做:
~~~
[me@linuxbox ~]$ sudo tar cf /media/BigDisk/home.tar /home
~~~
tar 包制作完成之后,我們卸載硬盤,然后把它連接到第二個計算機上。再一次,此硬盤被 掛載到 /media/BigDisk 目錄下。為了抽取歸檔文件,我們這樣做:
~~~
[me@linuxbox2 ~]$ cd /
[me@linuxbox2 /]$ sudo tar xf /media/BigDisk/home.tar
~~~
值得注意的一點是,因為歸檔文件中的所有路徑名都是相對的,所以首先我們必須更改目錄到根目錄下, 這樣抽取的文件路徑就相對于根目錄了。
當抽取一個歸檔文件時,有可能限制從歸檔文件中抽取什么內容。例如,如果我們想要抽取單個文件, 可以這樣實現:
~~~
tar xf archive.tar pathname
~~~
通過給命令添加末尾的路徑名,tar 命令就只會恢復指定的文件。可以指定多個路徑名。注意 路徑名必須是完全的,精準的相對路徑名,就如存儲在歸檔文件中的一樣。當指定路徑名的時候, 通常不支持通配符;然而,GNU 版本的 tar 命令(在 Linux 發行版中最常出現)通過 --wildcards 選項來 支持通配符。這個例子使用了之前 playground.tar 文件:
~~~
[me@linuxbox ~]$ cd foo
[me@linuxbox foo]$ tar xf ../playground2.tar --wildcards 'home/me/playground/dir-\*/file-A'
~~~
這個命令將只會抽取匹配特定路徑名的文件,路徑名中包含了通配符 dir-*。
tar 命令經常結合 find 命令一起來制作歸檔文件。在這個例子里,我們將會使用 find 命令來 產生一個文件集合,然后這些文件被包含到歸檔文件中。
~~~
[me@linuxbox ~]$ find playground -name 'file-A' -exec tar rf playground.tar '{}' '+'
~~~
這里我們使用 find 命令來匹配 playground 目錄中所有名為 file-A 的文件,然后使用-exec 行為,來 喚醒帶有追加模式(r)的 tar 命令,把匹配的文件添加到歸檔文件 playground.tar 里面。
使用 tar 和 find 命令,來創建逐漸增加的目錄樹或者整個系統的備份,是個不錯的方法。通過 find 命令匹配新于某個時間戳的文件,我們就能夠創建一個歸檔文件,其只包含新于上一個 tar 包的文件, 假定這個時間戳文件恰好在每個歸檔文件創建之后被更新了。
tar 命令也可以利用標準輸出和輸入。這里是一個完整的例子:
~~~
[me@linuxbox foo]$ cd
[me@linuxbox ~]$ find playground -name 'file-A' | tar cf - --files-from=-
| gzip > playground.tgz
~~~
在這個例子里面,我們使用 find 程序產生了一個匹配文件列表,然后把它們管道到 tar 命令中。 如果指定了文件名“-”,則其被看作是標準輸入或輸出,正是所需(順便說一下,使用“-”來表示 標準輸入/輸出的慣例,也被大量的其它程序使用)。這個 --file-from 選項(也可以用 -T 來指定) 導致 tar 命令從一個文件而不是命令行來讀入它的路徑名列表。最后,這個由 tar 命令產生的歸檔 文件被管道到 gzip 命令中,然后創建了壓縮歸檔文件 playground.tgz。此 .tgz 擴展名是命名 由 gzip 壓縮的 tar 文件的常規擴展名。有時候也會使用 .tar.gz 這個擴展名。
雖然我們使用 gzip 程序來制作我們的壓縮歸檔文件,但是現在的 GUN 版本的 tar 命令 ,gzip 和 bzip2 壓縮兩者都直接支持,各自使用 z 和 j 選項。以我們之前的例子為基礎, 我們可以這樣簡化它:
~~~
[me@linuxbox ~]$ find playground -name 'file-A' | tar czf playground.tgz -T -
~~~
如果我們本要創建一個由 bzip2 壓縮的歸檔文件,我們可以這樣做:
~~~
[me@linuxbox ~]$ find playground -name 'file-A' | tar cjf playground.tbz -T -
~~~
通過簡單地修改壓縮選項,把 z 改為 j(并且把輸出文件的擴展名改為 .tbz,來指示一個 bzip2 壓縮文件), 就使 bzip2 命令壓縮生效了。另一個 tar 命令與標準輸入和輸出的有趣使用,涉及到在系統之間經過 網絡傳輸文件。假定我們有兩臺機器,每臺都運行著類 Unix,且裝備著 tar 和 ssh 工具的操作系統。 在這種情景下,我們可以把一個目錄從遠端系統(名為 remote-sys)傳輸到我們的本地系統中:
~~~
[me@linuxbox ~]$ mkdir remote-stuff
[me@linuxbox ~]$ cd remote-stuff
[me@linuxbox remote-stuff]$ ssh remote-sys 'tar cf - Documents' | tar xf -
me@remote-sys’s password:
[me@linuxbox remote-stuff]$ ls
Documents
~~~
這里我們能夠從遠端系統 remote-sys 中復制目錄 Documents 到本地系統名為 remote-stuff 目錄中。 我們怎樣做的呢?首先,通過使用 ssh 命令在遠端系統中啟動 tar 程序。你可記得 ssh 允許我們 在遠程聯網的計算機上執行程序,并且在本地系統中看到執行結果——遠端系統中產生的輸出結果 被發送到本地系統中查看。我們可以利用。在本地系統中,我們執行 tar 命令,
### zip
這個 zip 程序既是壓縮工具,也是一個打包工具。這程序使用的文件格式,Windows 用戶比較熟悉, 因為它讀取和寫入.zip 文件。然而,在 Linux 中 gzip 是主要的壓縮程序,而 bzip2則位居第二。
在 zip 命令最基本的使用中,可以這樣喚醒 zip 命令:
~~~
zip options zipfile file...
~~~
例如,制作一個 playground 的 zip 版本的文件包,這樣做:
~~~
[me@linuxbox ~]$ zip -r playground.zip playground
~~~
除非我們包含-r 選項,要不然只有 playground 目錄(沒有任何它的內容)被存儲。雖然會自動添加 .zip 擴展名,但為了清晰起見,我們還是包含文件擴展名。
在創建 zip 版本的文件包時,zip 命令通常會顯示一系列的信息:
~~~
adding: playground/dir-020/file-Z (stored 0%)
adding: playground/dir-020/file-Y (stored 0%)
adding: playground/dir-020/file-X (stored 0%)
adding: playground/dir-087/ (stored 0%)
adding: playground/dir-087/file-S (stored 0%)
~~~
這些信息顯示了添加到文件包中每個文件的狀態。zip 命令會使用兩種存儲方法之一,來添加 文件到文件包中:要不它會“store”沒有壓縮的文件,正如這里所示,或者它會“deflate”文件, 執行壓縮操作。在存儲方法之后顯示的數值表明了壓縮量。因為我們的 playground 目錄 只是包含空文件,沒有對它的內容執行壓縮操作。
使用 unzip 程序,來直接抽取一個 zip 文件的內容。
~~~
[me@linuxbox ~]$ cd foo
[me@linuxbox foo]$ unzip ../playground.zip
~~~
對于 zip 命令(與 tar 命令相反)要注意一點,就是如果指定了一個已經存在的文件包,其被更新 而不是被替代。這意味著會保留此文件包,但是會添加新文件,同時替換匹配的文件。可以列出 文件或者有選擇地從一個 zip 文件包中抽取文件,只要給 unzip 命令指定文件名:
~~~
[me@linuxbox ~]$ unzip -l playground.zip playground/dir-87/file-Z
Archive: ../playground.zip
Length Date Time Name
0 10-05-08 09:25 playground/dir-87/file-Z
0 1 file
[me@linuxbox ~]$ cd foo
[me@linuxbox foo]$ unzip ./playground.zip playground/dir-87/file-Z
Archive: ../playground.zip
replace playground/dir-87/file-Z? [y]es, [n]o, [A]ll, [N]one,
[r]ename: y
extracting: playground/dir-87/file-Z
~~~
使用-l 選項,導致 unzip 命令只是列出文件包中的內容而沒有抽取文件。如果沒有指定文件, unzip 程序將會列出文件包中的所有文件。添加這個-v 選項會增加列表的冗余信息。注意當抽取的 文件與已經存在的文件沖突時,會在替代此文件之前提醒用戶。
像 tar 命令一樣,zip 命令能夠利用標準輸入和輸出,雖然它的實施不大有用。通過-@選項,有可能把一系列的 文件名管道到 zip 命令。
~~~
[me@linuxbox foo]$ cd
[me@linuxbox ~]$ find playground -name "file-A" | zip -@ file-A.zip
~~~
這里我們使用 find 命令產生一系列與“file-A”相匹配的文件列表,并且把此列表管道到 zip 命令, 然后創建包含所選文件的文件包 file-A.zip。
zip 命令也支持把它的輸出寫入到標準輸出,但是它的使用是有限的,因為很少的程序能利用輸出。 不幸地是,這個 unzip 程序,不接受標準輸入。這就阻止了 zip 和 unzip 一塊使用,像 tar 命令那樣, 來復制網絡上的文件。
然而,zip 命令可以接受標準輸入,所以它可以被用來壓縮其它程序的輸出:
~~~
[me@linuxbox ~]$ ls -l /etc/ | zip ls-etc.zip -
adding: - (deflated 80%)
~~~
在這個例子里,我們把 ls 命令的輸出管道到 zip 命令。像 tar 命令,zip 命令把末尾的橫杠解釋為 “使用標準輸入作為輸入文件。”
這個 unzip 程序允許它的輸出發送到標準輸出,當指定了-p 選項之后:
~~~
[me@linuxbox ~]$ unzip -p ls-etc.zip | less
~~~
我們討論了一些 zip/unzip 可以完成的基本操作。它們兩個都有許多選項,其增加了 命令的靈活性,雖然一些選項只針對于特定的平臺。zip 和 unzip 命令的說明手冊都相當不錯, 并且包含了有用的實例。然而,這些程序的主要用途是為了和 Windows 系統交換文件, 而不是在 Linux 系統中執行壓縮和打包操作,tar 和 gzip 程序在 Linux 系統中更受歡迎。
## 同步文件和目錄
維護系統備份的常見策略是保持一個或多個目錄與另一個本地系統(通常是某種可移動的存儲設備) 或者遠端系統中的目錄(或多個目錄)同步。我們可能,例如有一個正在開發的網站的本地備份, 需要時不時的與遠端網絡服務器中的文件備份保持同步。在類 Unix 系統的世界里,能完成此任務且 備受人們喜愛的工具是 rsync。這個程序能同步本地與遠端的目錄,通過使用 rsync 遠端更新協議,此協議 允許 rsync 快速地檢測兩個目錄的差異,執行最小量的復制來達到目錄間的同步。比起其它種類的復制程序, 這就使 rsync 命令非常快速和高效。
rsync 被這樣喚醒:
~~~
rsync options source destination
~~~
這里 source 和 destination 是下列選項之一:
* 一個本地文件或目錄
* 一個遠端文件或目錄,以[user@]host:path 的形式存在
* 一個遠端 rsync 服務器,由 rsync://[user@]host[:port]/path 指定
注意 source 和 destination 兩者之一必須是本地文件。rsync 不支持遠端到遠端的復制
讓我們試著對一些本地文件使用 rsync 命令。首先,清空我們的 foo 目錄:
~~~
[me@linuxbox ~]$ rm -rf foo/*
~~~
下一步,我們將同步 playground 目錄和它在 foo 目錄中相對應的副本
~~~
[me@linuxbox ~]$ rsync -av playground foo
~~~
我們包括了-a 選項(遞歸和保護文件屬性)和-v 選項(冗余輸出), 來在 foo 目錄中制作一個 playground 目錄的鏡像。當這個命令執行的時候, 我們將會看到一系列的文件和目錄被復制。在最后,我們將看到一條像這樣的總結信息:
~~~
sent 135759 bytes received 57870 bytes 387258.00 bytes/sec
total size is 3230 speedup is 0.02
~~~
說明復制的數量。如果我們再次運行這個命令,我們將會看到不同的結果:
~~~
[me@linuxbox ~]$ rsync -av playgound foo
building file list ... done
sent 22635 bytes received 20 bytes
total size is 3230 speedup is 0.14
45310.00 bytes/sec
~~~
注意到沒有文件列表。這是因為 rsync 程序檢測到在目錄~/playground 和 ~/foo/playground 之間 不存在差異,因此它不需要復制任何數據。如果我們在 playground 目錄中修改一個文件,然后 再次運行 rsync 命令:
~~~
[me@linuxbox ~]$ touch playground/dir-099/file-Z
[me@linuxbox ~]$ rsync -av playground foo
building file list ... done
playground/dir-099/file-Z
sent 22685 bytes received 42 bytes 45454.00 bytes/sec
total size is 3230 speedup is 0.14
~~~
我們看到 rsync 命令檢測到更改,并且只是復制了更新的文件。作為一個實際的例子, 讓我們考慮一個假想的外部硬盤,之前我們在 tar 命令中用到過的。如果我們再次把此 硬盤連接到我們的系統中,它被掛載到/media/BigDisk 目錄下,我們可以執行一個有 用的系統備份了,首先在外部硬盤上創建一個目錄,名為/backup,然后使用 rsync 程序 從我們的系統中復制最重要的數據到此外部硬盤上:
~~~
[me@linuxbox ~]$ mkdir /media/BigDisk/backup
[me@linuxbox ~]$ sudo rsync -av --delete /etc /home /usr/local /media/BigDisk/backup
~~~
在這個例子里,我們把/etc,/home,和/usr/local 目錄從我們的系統中復制到假想的存儲設備中。 我們包含了–delete 這個選項,來刪除可能在備份設備中已經存在但卻不再存在于源設備中的文件, (這與我們第一次創建備份無關,但是會在隨后的復制操作中有用途)。掛載外部驅動器,運行 rsync 命令,不斷重復這個過程,是一個不錯的(雖然不理想)方式來保存少量的系統備份文件。 當然,別名會對這個操作更有幫助些。我們將會創建一個別名,并把它添加到.bashrc 文件中, 來提供這個特性:
~~~
alias backup='sudo rsync -av --delete /etc /home /usr/local /media/BigDisk/backup'
~~~
現在我們所做的事情就是連接外部驅動器,然后運行 backup 命令來完成工作。
### 在網絡間使用 rsync 命令
rsync 程序的真正好處之一,是它可以被用來在網絡間復制文件。畢竟,rsync 中的“r”象征著“remote”。 遠程復制可以通過兩種方法完成。第一個方法要求另一個系統已經安裝了 rsync 程序,還安裝了 遠程 shell 程序,比如 ssh。比方說我們本地網絡中的一個系統有大量可用的硬盤空間,我們想要 用遠程系統來代替一個外部驅動器,來執行文件備份操作。假定遠程系統中有一個名為/backup 的目錄, 其用來存放我們傳送的文件,我們這樣做:
~~~
[me@linuxbox ~]$ sudo rsync -av --delete --rsh=ssh /etc /home /usr/local remote-sys:/backup
~~~
我們對命令做了兩處修改,來方便網絡間文件復制。首先,我們添加了--rsh=ssh 選項,其指示 rsync 使用 ssh 程序作為它的遠程 shell。以這種方式,我們就能夠使用一個 ssh 加密通道,把數據 安全地傳送到遠程主機中。其次,通過在目標路徑名前加上遠端主機的名字(在這種情況下, 遠端主機名為 remote-sys),來指定遠端主機。
rsync 可以被用來在網絡間同步文件的第二種方式是通過使用 rsync 服務器。rsync 可以被配置為一個 守護進程,監聽即將到來的同步請求。這樣做經常是為了允許一個遠程系統的鏡像。例如,Red Hat 軟件中心為它的 Fedora 發行版,維護著一個巨大的正在開發中的軟件包的倉庫。對于軟件測試人員, 在發行周期的測試階段,鏡像這些軟件集合是非常有幫助的。因為倉庫中的這些文件會頻繁地 (通常每天不止一次)改動,定期同步本地鏡像,這是可取的,而不是大量地拷貝軟件倉庫。 這些軟件庫之一被維護在 Georgia Tech;我們可以使用本地 rsync 程序和它們的 rsync 服務器來鏡像它。
~~~
[me@linuxbox ~]$ mkdir fedora-devel
[me@linuxbox ~]$ rsync -av -delete rsync://rsync.gtlib.gatech.edu/fedora-linux-
core/development/i386/os fedora-devel
~~~
在這個例子里,我們使用了遠端 rsync 服務器的 URI,其由協議(rsync://),遠端主機名 (rsync.gtlib.gatech.edu),和軟件倉庫的路徑名組成。
## 拓展閱讀
* 在這里討論的所有命令的手冊文檔都相當清楚明白,并且包含了有用的例子。另外, GNU 版本的 tar 命令有一個不錯的在線文檔。可以在下面鏈接處找到:
[http://www.gnu.org/software/tar/manual/index.html](http://www.gnu.org/software/tar/manual/index.html)
- 第一章:引言
- 第二章:什么是shell
- 第三章:文件系統中跳轉
- 第四章:研究操作系統
- 第五章:操作文件和目錄
- 第六章:使用命令
- 第七章:重定向
- 第八章:從shell眼中看世界
- 第九章:鍵盤高級操作技巧
- 第十章:權限
- 第十一章:進程
- 第十二章:shell環境
- 第十三章:VI簡介
- 第十四章:自定制shell提示符
- 第十五章:軟件包管理
- 第十六章:存儲媒介
- 第十七章:網絡系統
- 第十八章:查找文件
- 第十九章:歸檔和備份
- 第二十章:正則表達式
- 第二十一章:文本處理
- 第二十二章:格式化輸出
- 第二十三章:打印
- 第二十四章:編譯程序
- 第二十五章:編寫第一個shell腳本
- 第二十六章:啟動一個項目
- 第二十七章:自頂向下設計
- 第二十八章:流程控制 if分支結構
- 第二十九章:讀取鍵盤輸入
- 第三十章:流程控制 while/until 循環
- 第三十一章:疑難排解
- 第三十二章:流程控制 case分支
- 第三十三章:位置參數
- 第三十四章:流程控制 for循環
- 第三十五章:字符串和數字
- 第三十六章:數組
- 第三十七章:奇珍異寶