創用 CC 授權條款
除非另有註明,本網站的著作Fygul Hether製作,以創用CC 姓名標示-非商業性-禁止改作 4.0 國際 授權條款釋出。

2020年2月26日 星期三

tar命令的進階使用

摘要

接續〈tar命令的基礎使用〉,本文談點Unix/Unix-like的tar命令的幾個進階使用與範例:
  • 檔案選擇與排除
  • 覆寫控制
  • 加密
  • 增量備份
  • 多重卷冊
  • 複製目錄並保留屬性
本文使用環境是Ubuntu MATE 18.04。

檔案選擇與排除

本機檔案選擇

以tar封存檔案時,除了可像基礎篇所述直接指定要封存的檔案或目錄,也可將想要備份的檔案列在一清單檔案中,此清單可自行建立編輯,或利用 find 指令來產生,必要時可做適當編輯修改。然後用以下選項讓tar從此清單得知要備份的檔案[1]:
  • -T, --files-from=FILE
例如,以find列出 folder_to_archive/ 中所有的 .txt 檔案並另存成include.txt,讓tar從中得知要備份的檔案:

$ find folder_to_archive/ -name '*.txt' > include.txt
$ tar cf archive.tar -T include.txt
或者 find 到的東西透過 | 傳給 tar:

$ find folder_to_archive/ -name '*.txt' | tar cf archive.tar -T-
此處 -T 後的 - 代表著stdio。

上例因用了 -T 所以就沒必要在後面指定要封存的檔案,雖然如此,使用此選項的同時,還是可以指定要封存其他檔案或目錄:

$ tar cf archive.tar -T include.txt other_folder_to_archive
當混用多種選項時,記得原則上把 c, x, t 這類操作選項放最前面,要封存的檔案或目錄名稱放最後面,其他的選項放這二者之間。

排除

以tar封存檔案時,有時想排除掉某種檔案,以下是與排除相關眾多選項中幾個較常用的[2]:
  • --exclude=PATTERN:排除某一種檔名形式,如*.bak這類的檔案。
  • -X, --exclude-from=FILE:如果要排除的檔名形式較多,可一行一種列在一文字檔中。
  • --exclude-vcs:排除VCS (version control system),如git這類版本控制系統的目錄。
  • --exclude-vcs-ignores:排除VCS的忽略檔,像.gitignore。
  • --no-recursion:tar備份檔案時會包含子目錄,除非加上此選項。
幾個例子:

$ tar cf archive.tar --exclude=*.bak --exclude-vcs folder_to_archive/
$ tar cf archive.tar -X excluded.txt folder_to_archive/
$ tar cf ../archive.tar --no-recursion ./*
上例最後一個是備份目前目錄下的所有檔案,排除子目錄,並改在上一層目錄建立備份檔,以避免備份時也包含到備份檔本身。

覆寫控制

在解開操作時,有時想避免覆寫取代掉既有的檔案,相關的選項像:
  • -k, --keep-old-files:別取代掉既有的檔案。
  • --keep-newer-files:若是既有的檔案比封存檔中的還新或相同則保留。
範例:

$ tar xf archive.tar -k
$ tar xf archive.tar --keep-newer-files

加密

tar本身並不提供加密功能,但可配合其他加密工具程式使用,如gpg, openssl, bcrypt, ccrypt。若覺得這樣做有點麻煩,就改用像zip或7-zip本身有提供加密功能的壓縮程式[3]。

本文僅以gpg為例,只用到它最簡單的少許功能,完整使用法可見gpg man page

gpg的語法形式是:gpg [選項] [命令]

幾個選項:
  • --cipher-algo:指定加密演算法。
  • -o, --output:指定輸出的檔案。若寫到stdout,以 - 做為檔名。
幾個命令:
  • -h, --help:顯示簡單的語法說明。
  • --version:顯示版號與支援的演算法。
  • -c, --symmetric:使用passphrase做對稱式加密。預設使用AES-256。
  • -d, --decrypt:解密。
注意到選項與命令的順序不可錯置,否則出錯。以下是對檔案做加密的簡單例子:

$ gpg --cipher-algo 3des -c test.txt
在圖形桌面環境執行會跳出小視窗,要輸入二次密碼。注意,輸入焦點並不在此小視窗上,還要再以滑鼠點一下。

完成後會出現個test.txt.gpg的檔案,若要將其解密並存成另一檔案newfile.txt:

$ gpg -o newfile.txt -d test.txt.gpg
解密時不會問密碼?因為已存在自己家目錄下.gnupg目錄中。總之,檔案給別人解密時就會問密碼。

要將folder1目錄以tar做封存並以gpg加密:

$ tar cvzf - folder1/ | gpg -o folder1.tar.gz.gpg -c
將上例的folder1.tar.gz.gpg解密並以tar解開還原到另一個已先建立好的folder2目錄下:

$ gpg -d folder1.tar.gz.gpg | tar xvzf - -C folder2/

增量備份

以tar做增量備份封存時,tar會做些記錄在一個快照檔snapshot file中,以此來決定每次備份之間檔案的異動情形。如此在下回做增量備份時,只備份有變動的檔案,而不是全部。與此工作較相關的選項有:
  • -g, --listed-incremental=FILE:指定增量備份時所用的快照檔。採用新式GNU格式增量備份。
  • --level=NUMBER:指定備份層級,後詳述。
  • -G, --incremental:建議只用在解開還原與列示的操作,後述。處理舊式GNU格式增量備份。
本節只是較簡要的內容,詳細的可見[4]。

備份

做第一次增量備份,由於是第一次,所以事實上也是完整備份:

$ tar cf archive1.tar -g snap folder_to_archive/
此時會建立個名稱為snap的檔案來存放快照,而archive1.tar是level 0備份。

對folder_to_archive/目錄中的東西做了修改或新增、刪除之後,做第二次增量備份:

$ tar cf archive2.tar -g snap folder_to_archive/
此時tar先比較folder_to_archive/中的檔案與原snap中的記錄以發現其中的不同,只備份新增與修改過的檔案,然後再把新的記錄寫入snap中。archive2.tar則是level 1的備份;如果往後依此法每做一回增量備份,level都會加1。

假定之後想重新重頭開始做增量備份,可將前述的快照檔刪除,再使用前述相同的指令;或是在第一次備份時,指定 --level=0 :

$ tar cf archive1.tar -g snap --level=0 folder_to_archive/
由於增量備份依賴時間戳記,所以若在做備份的同時又修改了檔案時間或是調整系統的時間,可是會出差錯的。

還原

延續上例,假定要還原資料,結合使用 -x 與 -g 選項,依序還原即可,tar會還原到備份檔建立時的檔案狀態,會刪除系統中有而備份檔中沒有的檔案。此時tar已沒必要讀取快照檔,因要解出的檔案都在備份檔中,所以 -g 可給予任意參數,通常可用 -g /dev/null;或者改用 -G, --incremental,它可在extract或list操作時做為 -g 的替代。範例:

$ tar xf archive1.tar -g /dev/null
$ tar xf archive2.tar -G

列示

列示增量備份檔中的內容,結合使用 -t與 -g 或 -G。若要顯示較詳細的資訊,可再加上二個--verbose參數,例:

$ tar tvvf archive2.tar -G

多重卷冊

現在一般較少使用多重卷冊multi-volume功能了。一些較流行常見的壓縮軟體多半都有這項功能,在過去磁碟片盛行時期,可用此功能把較大的檔案壓縮並存到多張磁碟片中。隨著儲存裝置的價格下降與容量大增,以及網路傳輸頻寬的大幅擴大以及傳輸品質穩定化,較少有這種把大檔案壓縮並分割以方便儲存或以網路傳輸的需要。無論如何,這種功能還是會繼續存在,tar也有這功能,可用在磁帶機,或是一般儲存裝置,與此較相關的重要選項有:
  • -M, --multi-volume:建立/列示/解開時,指定使用多重卷冊。
  • -L, --tape-length=N:指定磁帶長度,即容量,如20M,或2G,分別表20 MB與2 GB。如果數字後無後置字母,預設的容量單位為1024 bytes,也就是MB。
例如,在裝有磁帶機的機器上,備份folder_to_archive/到磁帶機,第一個磁帶存滿了,提示更換成第二個磁帶後繼續動作:

$ tar cf /dev/tape -M folder_to_archive/
tar在偵測到達磁帶尾端的方法並不是很靠譜,在某些作業系統或裝置上會出錯。此時可以用 -L 選項讓tar知道磁帶的容量,此選項也會自動選擇 -M 選項。例如磁帶容量是4 GB:

$ tar cf /dev/tape -L 4G folder_to_archive/
或是:

$ tar cf /dev/tape -L 41943040 folder_to_archive/
第一個磁帶寫滿時會出現提示文字,要你準備好卷冊 #2,也就是第二個磁帶。可在此提示中輸入 ? 查看進一步說明。記得只有在更換好磁帶之後才按 y 繼續備份動作,不然可能會寫到尚未換掉的第一個磁帶中。

如果備份到檔案,採用上述方式時,則是要在提示中輸入 n 第2卷冊檔案名稱,例如 n archive2.tar ,然後按Enter鍵繼續。若卷冊較多時,這顯然不很方便,此時可利用Bash的Brace Expansion展開的功能,指定多個卷冊檔案,如:

$ tar c --file=archive_{00..10}.tar -L 10M folder_to_archive/
上行會產生archive_00.tar到archive_10.tar的檔名,而實際上可能只會用到06。這數量可事先估計一下,例如估計在100之內,也可改成像{000..100}。另外要注意一點,所要封存檔案的檔名若太長,無法寫到多重卷冊標頭之中,會被截斷,並且會出現警示文字,不過自己實測後並無發現不良影響。

以上例的備份而言,若要還原解開到另一目錄folder2:

$ tar x --file=archive_{00..10}.tar -M -C folder2/
注意上行因為不需要指定容量大小,所以改用 -M 而不是 -L 。

以上只是多重卷冊方面較簡單的說明,較詳細的資訊可見[5]。[6]則提到另一種做法是配合split做檔案分割,如:

$ tar czvf - folder_to_archive/ | split -d -b 10M archive.tar.gz._
這樣分割出來的檔案群會像 archive.tar.gz._00, archive.tar.gz._01, ... archive.tar.gz._06
解開還原的方式則是:

$ cat archive.tar.gz._* | tar xzvf - -C folder2/

複製目錄並保留屬性

有時想從某處複製整個目錄,並且想保留目錄或檔案的原有屬性都不變動,像時間戳記,除了使用 rsync 指令:

$ rsync -av folder1 folder2
也可利用tar的封存、解開的功能:

$ tar cf- source-dir/ | tar xf- -C target-parent-dir/
上例中的 - 代表著stdout/stdio,因 -f- 是預設(見 tar --show-defaults ),所以可省略:

$ tar c source-dir/ | tar x -C target-parent-dir/

參考與資源連結

  1. 6.3 Reading Names from a File
  2. 6.4 Excluding Some Files
  3. 7 Tools to Encrypt/Decrypt and Password Protect Files in Linux
  4. 5.2 Using tar to Perform Incremental Dumps
  5. 9.6.1 Archives Longer than One Tape or Disk
  6. How to create tar archive split into, or spanning, multiple files?

沒有留言:

張貼留言