計(jì)算機(jī)系統(tǒng)管理員的一個主要任務(wù)就是保護(hù)系統(tǒng)的數(shù)據(jù)安全,其中一種方法是通過時時備份系統(tǒng)文件,來保護(hù) 數(shù)據(jù)。即使你不是一名系統(tǒng)管理員,像做做拷貝或者在各個位置和設(shè)備之間移動大量的文件,通常也是很有幫助的。 在這一章中,我們將會看看幾個經(jīng)常用來管理文件集合的程序。它們就是文件壓縮程序:
gzip – 壓縮或者展開文件
歸檔程序:
tar – 磁帶打包工具
還有文件同步程序:
縱觀計(jì)算領(lǐng)域的發(fā)展歷史,人們努力想把最多的數(shù)據(jù)存放到到最小的可用空間中,不管是內(nèi)存,存儲設(shè)備 還是網(wǎng)絡(luò)帶寬。今天我們把許多數(shù)據(jù)服務(wù)都看作是理所當(dāng)然的事情,但是諸如便攜式音樂播放器, 高清電視,或?qū)拵ЬW(wǎng)絡(luò)之類的存在都應(yīng)歸功于高效的數(shù)據(jù)壓縮技術(shù)。
數(shù)據(jù)壓縮就是一個刪除冗余數(shù)據(jù)的過程。讓我們考慮一個假想的例子,比方說我們有一張100*100像素的 純黑的圖片文件。根據(jù)數(shù)據(jù)存儲方案(假定每個像素占24位,或者3個字節(jié)),那么這張圖像將會占用 30,000個字節(jié)的存儲空間:
100 * 100 * 3 = 30,000
一張單色圖像包含的數(shù)據(jù)全是多余的。我們要是聰明的話,可以用這種方法來編碼這些數(shù)據(jù), 我們只要簡單地描述這個事實(shí),我們有3萬個黑色的像素?cái)?shù)據(jù)塊。所以,我們不存儲包含3萬個0 (通常在圖像文件中,黑色由0來表示)的數(shù)據(jù)塊,取而代之,我們把這些數(shù)據(jù)壓縮為數(shù)字30,000, 后跟一個0,來表示我們的數(shù)據(jù)。這種數(shù)據(jù)壓縮方案被稱為游程編碼,是一種最基本的壓縮技術(shù)。
壓縮算法(數(shù)學(xué)技巧被用來執(zhí)行壓縮任務(wù))分為兩大類,無損壓縮和有損壓縮。無損壓縮保留了 原始文件的所有數(shù)據(jù)。這意味著,當(dāng)還原一個壓縮文件的時候,還原的文件與原文件一模一樣。 而另一方面,有損壓縮,執(zhí)行壓縮操作時會刪除數(shù)據(jù),允許更大的壓縮。當(dāng)一個有損文件被還原的時候, 它與原文件不相匹配; 相反,它是一個近似值。有損壓縮的例子有 JPEG(圖像)文件和 MP3(音頻)文件。 在我們的討論中,我們將看看完全無損壓縮,因?yàn)橛?jì)算機(jī)中的大多數(shù)數(shù)據(jù)是不能容忍丟失任何數(shù)據(jù)的。
這個 gzip 程序被用來壓縮一個或多個文件。當(dāng)執(zhí)行 gzip 命令時,則原始文件的壓縮版會替代原始文件。 相對應(yīng)的 gunzip 程序被用來把壓縮文件復(fù)原為沒有被壓縮的版本。這里有個例子:
[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
在這個例子里,我們創(chuàng)建了一個名為 foo.txt 的文本文件,其內(nèi)容包含一個目錄的列表清單。 接下來,我們運(yùn)行 gzip 命令,它會把原始文件替換為一個叫做 foo.txt.gz 的壓縮文件。在 foo.* 文件列表中,我們看到原始文件已經(jīng)被壓縮文件替代了,并將這個壓縮文件大約是原始 文件的十五分之一。我們也能看到壓縮文件與原始文件有著相同的權(quán)限和時間戳。
接下來,我們運(yùn)行 gunzip 程序來解壓縮文件。隨后,我們能見到壓縮文件已經(jīng)被原始文件替代了, 同樣地保留了相同的權(quán)限和時間戳。
gzip 命令有許多選項(xiàng)。這里列出了一些:
選項(xiàng) | 說明 |
---|---|
-c | 把輸出寫入到標(biāo)準(zhǔn)輸出,并且保留原始文件。也有可能用--stdout 和--to-stdout 選項(xiàng)來指定。 |
-d | 解壓縮。正如 gunzip 命令一樣。也可以用--decompress 或者--uncompress 選項(xiàng)來指定. |
-f | 強(qiáng)制壓縮,即使原始文件的壓縮文件已經(jīng)存在了,也要執(zhí)行。也可以用--force 選項(xiàng)來指定。 |
-h | 顯示用法信息。也可用--help 選項(xiàng)來指定。 |
-l | 列出每個被壓縮文件的壓縮數(shù)據(jù)。也可用--list 選項(xiàng)。 |
-r | 若命令的一個或多個參數(shù)是目錄,則遞歸地壓縮目錄中的文件。也可用--recursive 選項(xiàng)來指定。 |
-t | 測試壓縮文件的完整性。也可用--test 選項(xiàng)來指定。 |
-v | 顯示壓縮過程中的信息。也可用--verbose 選項(xiàng)來指定。 |
-number | 設(shè)置壓縮指數(shù)。number 是一個在1(最快,最小壓縮)到9(最慢,最大壓縮)之間的整數(shù)。 數(shù)值1和9也可以各自用--fast 和--best 選項(xiàng)來表示。默認(rèn)值是整數(shù)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 選項(xiàng)。
[me@linuxbox ~]$ ls -l /etc | gzip > foo.txt.gz
這個命令創(chuàng)建了一個目錄列表的壓縮文件。
這個 gunzip 程序,會解壓縮 gzip 文件,假定那些文件名的擴(kuò)展名是.gz,所以沒有必要指定它, 只要指定的名字與現(xiàn)有的未壓縮文件不沖突就可以:
[me@linuxbox ~]$ gunzip foo.txt
如果我們的目標(biāo)只是為了瀏覽一下壓縮文本文件的內(nèi)容,我們可以這樣做:
[me@linuxbox ~]$ gunzip -c foo.txt | less
另外,對應(yīng)于 gzip 還有一個程序,叫做 zcat,它等同于帶有-c 選項(xiàng)的 gunzip 命令。 它可以被用來如 cat 命令作用于 gzip 壓縮文件:
[me@linuxbox ~]$ zcat foo.txt.gz | less
小貼士: 還有一個 zless 程序。它與上面的管道線有相同的功能。
這個 bzip2 程序,由 Julian Seward 開發(fā),與 gzip 程序相似,但是使用了不同的壓縮算法, 舍棄了壓縮速度,而實(shí)現(xiàn)了更高的壓縮級別。在大多數(shù)情況下,它的工作模式等同于 gzip。 由 bzip2 壓縮的文件,用擴(kuò)展名 .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 程序的所有選項(xiàng)(除了-r) ,bzip2 程序同樣也支持。注意,然而,壓縮級別選項(xiàng)(-number)對于 bzip2 程序來說,有少許不同的含義。 伴隨著 bzip2 程序,有 bunzip2 和 bzcat 程序來解壓縮文件。bzip2 文件也帶有 bzip2recover 程序,其會 試圖恢復(fù)受損的 .bz2 文件。
不要強(qiáng)迫性壓縮
我偶然見到人們試圖用高效的壓縮算法,來壓縮一個已經(jīng)被壓縮過的文件,通過這樣做:
$ gzip picture.jpg
不要這樣。你可能只是在浪費(fèi)時間和空間!如果你再次壓縮已經(jīng)壓縮過的文件,實(shí)際上你 會得到一個更大的文件。這是因?yàn)樗械膲嚎s技術(shù)都會涉及一些開銷,文件中會被添加描述 此次壓縮過程的信息。如果你試圖壓縮一個已經(jīng)不包含多余信息的文件,那么再次壓縮不會節(jié)省 空間,以抵消額外的花費(fèi)。
一個常見的,與文件壓縮結(jié)合一塊使用的文件管理任務(wù)是歸檔。歸檔就是收集許多文件,并把它們 捆綁成一個大文件的過程。歸檔經(jīng)常作為系統(tǒng)備份的一部分來使用。當(dāng)把舊數(shù)據(jù)從一個系統(tǒng)移到某 種類型的長期存儲設(shè)備中時,也會用到歸檔程序。
在類 Unix 的軟件世界中,這個 tar 程序是用來歸檔文件的經(jīng)典工具。它的名字,是 tape archive 的簡稱,揭示了它的根源,它是一款制作磁帶備份的工具。而它仍然被用來完成傳統(tǒng)任務(wù), 它也同樣適用于其它的存儲設(shè)備。我們經(jīng)常看到擴(kuò)展名為 .tar 或者 .tgz 的文件,它們各自表示“普通” 的 tar 包和被 gzip 程序壓縮過的 tar 包。一個 tar 包可以由一組獨(dú)立的文件,一個或者多個目錄,或者 兩者混合體組成。命令語法如下:
tar mode[options] pathname...
這里的 mode 是指以下操作模式(這里只展示了一部分,查看 tar 的手冊來得到完整列表)之一:
模式 | 說明 |
---|---|
c | 為文件和/或目錄列表創(chuàng)建歸檔文件。 |
x | 抽取歸檔文件。 |
r | 追加具體的路徑到歸檔文件的末尾。 |
t | 列出歸檔文件的內(nèi)容。 |
tar 命令使用了稍微有點(diǎn)奇怪的方式來表達(dá)它的選項(xiàng),所以我們需要一些例子來展示它是 怎樣工作的。首先,讓我們重新創(chuàng)建之前我們用過的操練場:
[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}
下一步,讓我們創(chuàng)建整個操練場的 tar 包:
[me@linuxbox ~]$ tar cf playground.tar playground
這個命令創(chuàng)建了一個名為 playground.tar 的 tar 包,其包含整個 playground 目錄層次結(jié)果。我們 可以看到模式 c 和選項(xiàng) f,其被用來指定這個 tar 包的名字,模式和選項(xiàng)可以寫在一起,而且不 需要開頭的短橫線。注意,然而,必須首先指定模式,然后才是其它的選項(xiàng)。
要想列出歸檔文件的內(nèi)容,我們可以這樣做:
[me@linuxbox ~]$ tar tf playground.tar
為了得到更詳細(xì)的列表信息,我們可以添加選項(xiàng) v:
[me@linuxbox ~]$ tar tvf playground.tar
現(xiàn)在,抽取 tar 包 playground 到一個新位置。我們先創(chuàng)建一個名為 foo 的新目錄,更改目錄, 然后抽取 tar 包中的文件:
[me@linuxbox ~]$ mkdir foo
[me@linuxbox ~]$ cd foo
[me@linuxbox ~]$ tar xf ../playground.tar
[me@linuxbox ~]$ ls
playground
如果我們檢查 ~/foo/playground 目錄中的內(nèi)容,會看到這個歸檔文件已經(jīng)被成功地安裝了,就是創(chuàng)建了 一個精確的原始文件的副本。有一個警告,然而:除非你是超級用戶,要不然從歸檔文件中抽取的文件 和目錄的所有權(quán)由執(zhí)行此復(fù)原操作的用戶所擁有,而不屬于原始所有者。
tar 命令另一個有趣的行為是它處理歸檔文件路徑名的方式。默認(rèn)情況下,路徑名是相對的,而不是絕對 路徑。當(dāng)創(chuàng)建歸檔文件的時候,tar 命令會簡單地刪除路徑名開頭的斜杠。為了說明問題,我們將會 重新創(chuàng)建我們的歸檔文件,這次指定一個絕對路徑:
[me@linuxbox foo]$ cd
[me@linuxbox ~]$ tar cf playground2.tar ~/playground
記住,當(dāng)按下回車鍵后,~/playground 會展開成 /home/me/playground,所以我們將會得到一個 絕對路徑名。接下來,和之前一樣我們會抽取歸檔文件,觀察發(fā)生什么事情:
[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
這里我們看到當(dāng)我們抽取第二個歸檔文件時,它重新創(chuàng)建了 home/me/playground 目錄, 相對于我們當(dāng)前的工作目錄,~/foo,而不是相對于 root 目錄,作為帶有絕對路徑名的案例。 這看起來似乎是一種奇怪的工作方式,但事實(shí)上這種方式很有用,因?yàn)檫@樣就允許我們抽取文件 到任意位置,而不是強(qiáng)制地把抽取的文件放置到原始目錄下。加上 verbose(v)選項(xiàng),重做 這個練習(xí),將會展現(xiàn)更加詳細(xì)的信息。
讓我們考慮一個假設(shè),tar 命令的實(shí)際應(yīng)用。假定我們想要復(fù)制家目錄及其內(nèi)容到另一個系統(tǒng)中, 并且有一個大容量的 USB 硬盤,可以把它作為傳輸工具。在現(xiàn)代 Linux 系統(tǒng)中, 這個硬盤會被“自動地”掛載到 /media 目錄下。我們也假定硬盤中有一個名為 BigDisk 的邏輯卷。 為了制作 tar 包,我們可以這樣做:
[me@linuxbox ~]$ sudo tar cf /media/BigDisk/home.tar /home
tar 包制作完成之后,我們卸載硬盤,然后把它連接到第二個計(jì)算機(jī)上。再一次,此硬盤被 掛載到 /media/BigDisk 目錄下。為了抽取歸檔文件,我們這樣做:
[me@linuxbox2 ~]$ cd /
[me@linuxbox2 /]$ sudo tar xf /media/BigDisk/home.tar
值得注意的一點(diǎn)是,因?yàn)闅w檔文件中的所有路徑名都是相對的,所以首先我們必須更改目錄到根目錄下, 這樣抽取的文件路徑就相對于根目錄了。
當(dāng)抽取一個歸檔文件時,有可能限制從歸檔文件中抽取什么內(nèi)容。例如,如果我們想要抽取單個文件, 可以這樣實(shí)現(xiàn):
tar xf archive.tar pathname
通過給命令添加末尾的路徑名,tar 命令就只會恢復(fù)指定的文件。可以指定多個路徑名。注意 路徑名必須是完全的,精準(zhǔn)的相對路徑名,就如存儲在歸檔文件中的一樣。當(dāng)指定路徑名的時候, 通常不支持通配符;然而,GNU 版本的 tar 命令(在 Linux 發(fā)行版中最常出現(xiàn))通過 --wildcards 選項(xiàng)來 支持通配符。這個例子使用了之前 playground.tar 文件:
[me@linuxbox ~]$ cd foo
[me@linuxbox foo]$ tar xf ../playground2.tar --wildcards 'home/me/playground/dir-\*/file-A'
這個命令將只會抽取匹配特定路徑名的文件,路徑名中包含了通配符 dir-*。
tar 命令經(jīng)常結(jié)合 find 命令一起來制作歸檔文件。在這個例子里,我們將會使用 find 命令來 產(chǎn)生一個文件集合,然后這些文件被包含到歸檔文件中。
[me@linuxbox ~]$ find playground -name 'file-A' -exec tar rf playground.tar '{}' '+'
這里我們使用 find 命令來匹配 playground 目錄中所有名為 file-A 的文件,然后使用-exec 行為,來 喚醒帶有追加模式(r)的 tar 命令,把匹配的文件添加到歸檔文件 playground.tar 里面。
使用 tar 和 find 命令,來創(chuàng)建逐漸增加的目錄樹或者整個系統(tǒng)的備份,是個不錯的方法。通過 find 命令匹配新于某個時間戳的文件,我們就能夠創(chuàng)建一個歸檔文件,其只包含新于上一個 tar 包的文件, 假定這個時間戳文件恰好在每個歸檔文件創(chuàng)建之后被更新了。
tar 命令也可以利用標(biāo)準(zhǔn)輸出和輸入。這里是一個完整的例子:
[me@linuxbox foo]$ cd
[me@linuxbox ~]$ find playground -name 'file-A' | tar cf - --files-from=-
| gzip > playground.tgz
在這個例子里面,我們使用 find 程序產(chǎn)生了一個匹配文件列表,然后把它們管道到 tar 命令中。 如果指定了文件名“-”,則其被看作是標(biāo)準(zhǔn)輸入或輸出,正是所需(順便說一下,使用“-”來表示 標(biāo)準(zhǔn)輸入/輸出的慣例,也被大量的其它程序使用)。這個 --file-from 選項(xiàng)(也可以用 -T 來指定) 導(dǎo)致 tar 命令從一個文件而不是命令行來讀入它的路徑名列表。最后,這個由 tar 命令產(chǎn)生的歸檔 文件被管道到 gzip 命令中,然后創(chuàng)建了壓縮歸檔文件 playground.tgz。此 .tgz 擴(kuò)展名是命名 由 gzip 壓縮的 tar 文件的常規(guī)擴(kuò)展名。有時候也會使用 .tar.gz 這個擴(kuò)展名。
雖然我們使用 gzip 程序來制作我們的壓縮歸檔文件,但是現(xiàn)在的 GUN 版本的 tar 命令 ,gzip 和 bzip2 壓縮兩者都直接支持,各自使用 z 和 j 選項(xiàng)。以我們之前的例子為基礎(chǔ), 我們可以這樣簡化它:
[me@linuxbox ~]$ find playground -name 'file-A' | tar czf playground.tgz -T -
如果我們本要創(chuàng)建一個由 bzip2 壓縮的歸檔文件,我們可以這樣做:
[me@linuxbox ~]$ find playground -name 'file-A' | tar cjf playground.tbz -T -
通過簡單地修改壓縮選項(xiàng),把 z 改為 j(并且把輸出文件的擴(kuò)展名改為 .tbz,來指示一個 bzip2 壓縮文件), 就使 bzip2 命令壓縮生效了。另一個 tar 命令與標(biāo)準(zhǔn)輸入和輸出的有趣使用,涉及到在系統(tǒng)之間經(jīng)過 網(wǎng)絡(luò)傳輸文件。假定我們有兩臺機(jī)器,每臺都運(yùn)行著類 Unix,且裝備著 tar 和 ssh 工具的操作系統(tǒng)。 在這種情景下,我們可以把一個目錄從遠(yuǎn)端系統(tǒng)(名為 remote-sys)傳輸?shù)轿覀兊谋镜叵到y(tǒng)中:
[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
這里我們能夠從遠(yuǎn)端系統(tǒng) remote-sys 中復(fù)制目錄 Documents 到本地系統(tǒng)名為 remote-stuff 目錄中。 我們怎樣做的呢?首先,通過使用 ssh 命令在遠(yuǎn)端系統(tǒng)中啟動 tar 程序。你可記得 ssh 允許我們 在遠(yuǎn)程聯(lián)網(wǎng)的計(jì)算機(jī)上執(zhí)行程序,并且在本地系統(tǒng)中看到執(zhí)行結(jié)果——遠(yuǎn)端系統(tǒng)中產(chǎn)生的輸出結(jié)果 被發(fā)送到本地系統(tǒng)中查看。我們可以利用。在本地系統(tǒng)中,我們執(zhí)行 tar 命令,
這個 zip 程序既是壓縮工具,也是一個打包工具。這程序使用的文件格式,Windows 用戶比較熟悉, 因?yàn)樗x取和寫入.zip 文件。然而,在 Linux 中 gzip 是主要的壓縮程序,而 bzip2則位居第二。
在 zip 命令最基本的使用中,可以這樣喚醒 zip 命令:
zip options zipfile file...
例如,制作一個 playground 的 zip 版本的文件包,這樣做:
[me@linuxbox ~]$ zip -r playground.zip playground
除非我們包含-r 選項(xiàng),要不然只有 playground 目錄(沒有任何它的內(nèi)容)被存儲。雖然會自動添加 .zip 擴(kuò)展名,但為了清晰起見,我們還是包含文件擴(kuò)展名。
在創(chuàng)建 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%)
這些信息顯示了添加到文件包中每個文件的狀態(tài)。zip 命令會使用兩種存儲方法之一,來添加 文件到文件包中:要不它會“store”沒有壓縮的文件,正如這里所示,或者它會“deflate”文件, 執(zhí)行壓縮操作。在存儲方法之后顯示的數(shù)值表明了壓縮量。因?yàn)槲覀兊?playground 目錄 只是包含空文件,沒有對它的內(nèi)容執(zhí)行壓縮操作。
使用 unzip 程序,來直接抽取一個 zip 文件的內(nèi)容。
[me@linuxbox ~]$ cd foo
[me@linuxbox foo]$ unzip ../playground.zip
對于 zip 命令(與 tar 命令相反)要注意一點(diǎn),就是如果指定了一個已經(jīng)存在的文件包,其被更新 而不是被替代。這意味著會保留此文件包,但是會添加新文件,同時替換匹配的文件。可以列出 文件或者有選擇地從一個 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 選項(xiàng),導(dǎo)致 unzip 命令只是列出文件包中的內(nèi)容而沒有抽取文件。如果沒有指定文件, unzip 程序?qū)谐鑫募械乃形募?。添加這個-v 選項(xiàng)會增加列表的冗余信息。注意當(dāng)抽取的 文件與已經(jīng)存在的文件沖突時,會在替代此文件之前提醒用戶。
像 tar 命令一樣,zip 命令能夠利用標(biāo)準(zhǔn)輸入和輸出,雖然它的實(shí)施不大有用。通過-@選項(xiàng),有可能把一系列的 文件名管道到 zip 命令。
[me@linuxbox foo]$ cd
[me@linuxbox ~]$ find playground -name "file-A" | zip -@ file-A.zip
這里我們使用 find 命令產(chǎn)生一系列與“file-A”相匹配的文件列表,并且把此列表管道到 zip 命令, 然后創(chuàng)建包含所選文件的文件包 file-A.zip。
zip 命令也支持把它的輸出寫入到標(biāo)準(zhǔn)輸出,但是它的使用是有限的,因?yàn)楹苌俚某绦蚰芾幂敵觥?不幸地是,這個 unzip 程序,不接受標(biāo)準(zhǔn)輸入。這就阻止了 zip 和 unzip 一塊使用,像 tar 命令那樣, 來復(fù)制網(wǎng)絡(luò)上的文件。
然而,zip 命令可以接受標(biāo)準(zhǔn)輸入,所以它可以被用來壓縮其它程序的輸出:
[me@linuxbox ~]$ ls -l /etc/ | zip ls-etc.zip -
adding: - (deflated 80%)
在這個例子里,我們把 ls 命令的輸出管道到 zip 命令。像 tar 命令,zip 命令把末尾的橫杠解釋為 “使用標(biāo)準(zhǔn)輸入作為輸入文件?!?/p>
這個 unzip 程序允許它的輸出發(fā)送到標(biāo)準(zhǔn)輸出,當(dāng)指定了-p 選項(xiàng)之后:
[me@linuxbox ~]$ unzip -p ls-etc.zip | less
我們討論了一些 zip/unzip 可以完成的基本操作。它們兩個都有許多選項(xiàng),其增加了 命令的靈活性,雖然一些選項(xiàng)只針對于特定的平臺。zip 和 unzip 命令的說明手冊都相當(dāng)不錯, 并且包含了有用的實(shí)例。然而,這些程序的主要用途是為了和 Windows 系統(tǒng)交換文件, 而不是在 Linux 系統(tǒng)中執(zhí)行壓縮和打包操作,tar 和 gzip 程序在 Linux 系統(tǒng)中更受歡迎。
維護(hù)系統(tǒng)備份的常見策略是保持一個或多個目錄與另一個本地系統(tǒng)(通常是某種可移動的存儲設(shè)備) 或者遠(yuǎn)端系統(tǒng)中的目錄(或多個目錄)同步。我們可能,例如有一個正在開發(fā)的網(wǎng)站的本地備份, 需要時不時的與遠(yuǎn)端網(wǎng)絡(luò)服務(wù)器中的文件備份保持同步。在類 Unix 系統(tǒng)的世界里,能完成此任務(wù)且 備受人們喜愛的工具是 rsync。這個程序能同步本地與遠(yuǎn)端的目錄,通過使用 rsync 遠(yuǎn)端更新協(xié)議,此協(xié)議 允許 rsync 快速地檢測兩個目錄的差異,執(zhí)行最小量的復(fù)制來達(dá)到目錄間的同步。比起其它種類的復(fù)制程序, 這就使 rsync 命令非??焖俸透咝?。
rsync 被這樣喚醒:
rsync options source destination
這里 source 和 destination 是下列選項(xiàng)之一:
一個本地文件或目錄
一個遠(yuǎn)端文件或目錄,以[user@]host:path 的形式存在
注意 source 和 destination 兩者之一必須是本地文件。rsync 不支持遠(yuǎn)端到遠(yuǎn)端的復(fù)制
讓我們試著對一些本地文件使用 rsync 命令。首先,清空我們的 foo 目錄:
[me@linuxbox ~]$ rm -rf foo/*
下一步,我們將同步 playground 目錄和它在 foo 目錄中相對應(yīng)的副本
[me@linuxbox ~]$ rsync -av playground foo
我們包括了-a 選項(xiàng)(遞歸和保護(hù)文件屬性)和-v 選項(xiàng)(冗余輸出), 來在 foo 目錄中制作一個 playground 目錄的鏡像。當(dāng)這個命令執(zhí)行的時候, 我們將會看到一系列的文件和目錄被復(fù)制。在最后,我們將看到一條像這樣的總結(jié)信息:
sent 135759 bytes received 57870 bytes 387258.00 bytes/sec
total size is 3230 speedup is 0.02
說明復(fù)制的數(shù)量。如果我們再次運(yùn)行這個命令,我們將會看到不同的結(jié)果:
[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
注意到?jīng)]有文件列表。這是因?yàn)?rsync 程序檢測到在目錄~/playground 和 ~/foo/playground 之間 不存在差異,因此它不需要復(fù)制任何數(shù)據(jù)。如果我們在 playground 目錄中修改一個文件,然后 再次運(yùn)行 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 命令檢測到更改,并且只是復(fù)制了更新的文件。作為一個實(shí)際的例子, 讓我們考慮一個假想的外部硬盤,之前我們在 tar 命令中用到過的。如果我們再次把此 硬盤連接到我們的系統(tǒng)中,它被掛載到/media/BigDisk 目錄下,我們可以執(zhí)行一個有 用的系統(tǒng)備份了,首先在外部硬盤上創(chuàng)建一個目錄,名為/backup,然后使用 rsync 程序 從我們的系統(tǒng)中復(fù)制最重要的數(shù)據(jù)到此外部硬盤上:
[me@linuxbox ~]$ mkdir /media/BigDisk/backup
[me@linuxbox ~]$ sudo rsync -av --delete /etc /home /usr/local /media/BigDisk/backup
在這個例子里,我們把/etc,/home,和/usr/local 目錄從我們的系統(tǒng)中復(fù)制到假想的存儲設(shè)備中。 我們包含了--delete 這個選項(xiàng),來刪除可能在備份設(shè)備中已經(jīng)存在但卻不再存在于源設(shè)備中的文件, (這與我們第一次創(chuàng)建備份無關(guān),但是會在隨后的復(fù)制操作中有用途)。掛載外部驅(qū)動器,運(yùn)行 rsync 命令,不斷重復(fù)這個過程,是一個不錯的(雖然不理想)方式來保存少量的系統(tǒng)備份文件。 當(dāng)然,別名會對這個操作更有幫助些。我們將會創(chuàng)建一個別名,并把它添加到.bashrc 文件中, 來提供這個特性:
alias backup='sudo rsync -av --delete /etc /home /usr/local /media/BigDisk/backup'
現(xiàn)在我們所做的事情就是連接外部驅(qū)動器,然后運(yùn)行 backup 命令來完成工作。
rsync 程序的真正好處之一,是它可以被用來在網(wǎng)絡(luò)間復(fù)制文件。畢竟,rsync 中的“r”象征著“remote”。 遠(yuǎn)程復(fù)制可以通過兩種方法完成。第一個方法要求另一個系統(tǒng)已經(jīng)安裝了 rsync 程序,還安裝了 遠(yuǎn)程 shell 程序,比如 ssh。比方說我們本地網(wǎng)絡(luò)中的一個系統(tǒng)有大量可用的硬盤空間,我們想要 用遠(yuǎn)程系統(tǒng)來代替一個外部驅(qū)動器,來執(zhí)行文件備份操作。假定遠(yuǎn)程系統(tǒng)中有一個名為/backup 的目錄, 其用來存放我們傳送的文件,我們這樣做:
[me@linuxbox ~]$ sudo rsync -av --delete --rsh=ssh /etc /home /usr/local remote-sys:/backup
我們對命令做了兩處修改,來方便網(wǎng)絡(luò)間文件復(fù)制。首先,我們添加了--rsh=ssh 選項(xiàng),其指示 rsync 使用 ssh 程序作為它的遠(yuǎn)程 shell。以這種方式,我們就能夠使用一個 ssh 加密通道,把數(shù)據(jù) 安全地傳送到遠(yuǎn)程主機(jī)中。其次,通過在目標(biāo)路徑名前加上遠(yuǎn)端主機(jī)的名字(在這種情況下, 遠(yuǎn)端主機(jī)名為 remote-sys),來指定遠(yuǎn)端主機(jī)。
rsync 可以被用來在網(wǎng)絡(luò)間同步文件的第二種方式是通過使用 rsync 服務(wù)器。rsync 可以被配置為一個 守護(hù)進(jìn)程,監(jiān)聽即將到來的同步請求。這樣做經(jīng)常是為了允許一個遠(yuǎn)程系統(tǒng)的鏡像。例如,Red Hat 軟件中心為它的 Fedora 發(fā)行版,維護(hù)著一個巨大的正在開發(fā)中的軟件包的倉庫。對于軟件測試人員, 在發(fā)行周期的測試階段,鏡像這些軟件集合是非常有幫助的。因?yàn)閭}庫中的這些文件會頻繁地 (通常每天不止一次)改動,定期同步本地鏡像,這是可取的,而不是大量地拷貝軟件倉庫。 這些軟件庫之一被維護(hù)在 Georgia Tech;我們可以使用本地 rsync 程序和它們的 rsync 服務(wù)器來鏡像它。
[me@linuxbox ~]$ mkdir fedora-devel
[me@linuxbox ~]$ rsync -av -delete rsync://rsync.gtlib.gatech.edu/fedora-linux-
core/development/i386/os fedora-devel
在這個例子里,我們使用了遠(yuǎn)端 rsync 服務(wù)器的 URI,其由協(xié)議(rsync://),遠(yuǎn)端主機(jī)名 (rsync.gtlib.gatech.edu),和軟件倉庫的路徑名組成。
在這里討論的所有命令的手冊文檔都相當(dāng)清楚明白,并且包含了有用的例子。另外, GNU 版本的 tar 命令有一個不錯的在線文檔??梢栽谙旅骀溄犹幷业剑?/p>