跳至內容
出自 Arch Linux 中文维基

Snapper 是一個由 openSUSE 的 Arvin Schnell 開發的工具,用於管理 Btrfs 子卷和 LVM 精簡配置(thin-provisioned)卷。它可以創建和比較快照,在快照間回滾,並支持自動按時間序列創建快照。

安裝

安裝 snapper 包。或者安裝開發版本 snapper-gitAUR

此外,還可以安裝 GUI 前端 snapper-gui-gitAURbtrfs-assistantAURsnapper-toolsAUR

建立一個新的配置

在為 btrfs 子卷建立一個 snapper 配置前,這個子卷必須已經存在。否則,你應該在建立 snapper 配置前創建它。

要為位置為 /path/to/subvolume 的 btrfs 子卷創建一個新的 snapper 配置文件,並命名為 config

# snapper -c config create-config /path/to/subvolume

這將會:

  • 根據 /usr/share/snapper/config-templates/default 處的默認配置模板創建一個配置文件 /etc/snapper/configs/config
  • /path/to/subvolume/.snapshots 處創建一個子卷,用於存儲未來該配置文件產生的子卷。子卷的路徑將會是 /path/to/subvolume/.snapshots/#/snapshot# 是子卷序號。
  • config 加入到 /etc/conf.d/snapperSNAPPER_CONFIGS 中。

例如,要為掛載在 / 的子卷創建一個配置文件:

# snapper -c root create-config /
注意:如果你正在使用 archinstall 推薦的 btrfs 分區布局,則 @.snapshots 子卷已經被掛載到 /.snapshots,這會導致 snapper create-config 無法正常創建配置 [1]。要讓 Snapper 使用 @.snapshots 來創建備份,需要進行如下操作:
  • 卸載 @.snapshots 子卷並刪除已存在的掛載點。
  • 創建 Snapper 配置。
  • 刪除 Snapper 創建的子卷。
  • 重新創建 /.snapshots 掛載點,重新掛載 @.snapshots 子卷。

此時,配置文件已經激活。如果你的 cron 守護進程已經運行, snapper 將會使用 #自動按時創建快照。否則,你需要使用 systemd 單元文件和定時器。參閱 #啟用/停用

參閱 snapper-configs(5)

創建快照

自動按時創建快照

一個快照時間線(timeline)由可配置數目的每小時/日/月/年快照組成。當自動按時創建啟用時,默認每小時創建一個快照。每天由時間線清理算法清理多餘快照。詳情請參照 snapper-configs(5) 中的 TIMELINE_* 變量。

啟用/停用

如果你擁有一個 cron 守護進程,該特性應該已經自動啟用。要停用,編輯你想禁用該特性的子卷對應配置文件為:

TIMELINE_CREATE="no"

如果你沒有 cron 守護進程,你可以使用提供的 systemd 單元文件。啟動啟用 snapper-timeline.timer 來啟用自動按時創建快照。另外,啟用啟動 snapper-cleanup.timer 來定期清理老舊快照。

注意:如果你有一個 cron 守護進程並同時啟用了 systemd 單元,這可能會導致重複創建快照。如果你希望使用 systemd 單元並禁用 cron 集成,一中可行的方法是使用 pacman 的 NoExtract 配置選項。參見[2]

設置快照限制

默認配置將保留 10 個每小時快照,10 個每日快照,10 個每月快照和 10 個每年快照。你可以在配置文件中更改這些限制,特別是在繁忙的子卷,例如 / 上。參閱 #減緩性能影響

這是一份名為 config 的配置文件的示例片段,它將保留 5 個每小時快照,7 個每日快照,不保留每月和每年快照:

/etc/snapper/configs/config
TIMELINE_MIN_AGE="1800"
TIMELINE_LIMIT_HOURLY="5"
TIMELINE_LIMIT_DAILY="7"
TIMELINE_LIMIT_WEEKLY="0"
TIMELINE_LIMIT_MONTHLY="0"
TIMELINE_LIMIT_YEARLY="0"

更改創建和清理頻率

如果你使用提供的 systemd 定時器,你可以修改它們來更改創建和清理頻率。

例如,編輯 snapper-timeline.timer,加入下列配置來設定快照頻率為間隔五分鐘,而不是一小時:

[Timer]
OnCalendar=
OnCalendar=*:0/5


在編輯 snapper-cleanup.timer 來每小時運行清理,而不是每天的時候, 你需要更改 OnUnitActiveSec。 加入:

[Timer]
OnUnitActiveSec=1h

參閱 Systemd/定時器Systemd#附加配置片段

手動創建快照

Single 快照

默認情況下 snapper 創建 single 類型的快照,它們與其他快照沒有特別關係。

要為一個子卷創建快照:

 # snapper -c config create --description desc

以上命令沒有對應的清理算法,因此該快照將會一直存儲直到 刪除 它。

要設置一個清理算法,在 create 後使用 -c 選項,並在 numbertimelineprepost 中選擇一個參數。 number 使 snapper 定期清理超出配置文件中設置的數量限制的快照。例如,要創建一個使用 number 清理算法的快照:

 # snapper -c config create -c number

參閱 #自動按時創建快照 查看 timeline 是如何工作的。參閱 #pre/post 快照 查看 pre post 如何工作。

pre/post 快照

另一種快照類型是 pre/post 快照。兩個快照會在進行重大更改時先後成對創建(例如進行系統更新時)。


如果這種重大更改是/可被單個命令調用,那麼 snapper create --command 可以在調用這個命令的同時創建 pre/post 快照。


# snapper -c config create --command cmd
提示:要在創建 pre/post 快照時執行任何 shell 命令,可以考慮使用 snpAUR 腳本。這個腳本相比 Snapper 自身的 --command 選項能更好的處理輸出重定向。

pre/post快照也可以被手動創建。

首先創建一個pre快照:

# snapper -c config create -t pre -p

記下被創建快照的序號(在創建post快照時需要用到)。

然後進行想要進行的操作(比如安裝一個程序,或是進行升級等)。

最後創建post快照,將下文的 N 替換為pre快照的序號:

# snapper -c config create -t post --pre-number N

參閱 #在進行 pacman 操作時創建快照

啟動時快照

要讓 snapper 為 root 配置文件創建一個快照,啟用 snapper-boot.timer。通過這種方式創建的快照是 Single 快照。

管理快照

列出配置

列出所有你已經創建的配置:

 # snapper list-configs

列出快照

要列出名為 config 的配置文件對應的快照:

 # snapper -c config list

還原快照

在還原快照時,部分文件可能會保持原樣,原因可能是快照中不包含該文件(例如,該文件位於另一個子卷上),也可能是過濾配置排除了該文件。

過濾配置

本文或本章節的事實準確性存在爭議。

原因: /etc/mtab is a symlink to /proc/self/mounts, so reverting it has no effect on the system.(在 Talk:Snapper 中討論)


部分文件保存著系統的狀態信息,例如 /etc/mtab。這些文件不應該被還原。Arch Linux 提供的 Snapper 的默認配置已經排除了這些文件。Snapper 支持按照用戶排除某些文件或文件夾。/etc/snapper/filters/*.txt/usr/share/snapper/filters/*.txt 中的每行指定了要排除的項目。當 Snapper 計算快照之間的差別時,會排除這些文件。注意,這些文件仍會包含在快照中,如果不想讓這些文件包含在快照中,使用單獨的子卷或者掛載點。

本文或本章節的事實準確性存在爭議。

原因: How is the list from SLES documentation relevant for Arch Linux?(在 Talk:Snapper 中討論)


參見 SUSE 的文檔Directories That Are Excluded from Snapshots[失效連結 2024-03-03 ⓘ]

還原快照

本文或本章節的事實準確性存在爭議。

原因: What is the "default layout"? What is the alternative?(在 Talk:Snapper 中討論)


如果你使用 Snapper 的默認布局,每個快照是在所指定子卷下的 .snapshots 目錄的下層子卷,例如 @home 的快照位於 @home/.snapshots下。

本文或本章節的事實準確性存在爭議。

原因: Subvolumes that are not used for / can be restored from the system itself. Just log in as root, make sure that the subvolume is not used, and unmount it.(在 Talk:Snapper 中討論)


例如要將某個快照恢復到 home,首先啟動到 Arch Linux 的 LiveCD。 使用UUID將 btrfs 的頂層子卷掛載到/mnt

# mount -t btrfs -o subvol=/ /dev/disk/by-uuid/UUID_of_root_volume /mnt
# cd /mnt

將目前的子卷移動到其他地方,例如將 @home 移動到@home-backup

# mv @home @home-backup

找到你想恢復快照的序號(每個快照都單獨顯示為一行,所以能很方便的按照時間查找序號):

# grep -r '<date>'  /mnt/@home-backup/.snapshots/*/info.xml
...
/mnt/@home-backup/.snapshots/number/info.xml:  <date>2021-07-26 22:00:00</date>
...
注意:info.xml記錄的時間為 UTC 時間,請務必將其和本地時間的時差計算在內。

記住 number

使用 number 快照來創建新快照。

# btrfs subvolume snapshot @home-backup/.snapshots/number/snapshot @home

.snapshots 移回恢復完成的子卷下,例如@home


# mv @home-backup/.snapshots @home/
注意:如果在 fstab中指定的是 subvolid 而不是子卷路徑,則需要更改 /mnt/@/etc/fstab 中的 subvolid(假定把@子卷掛載到了/)。 可以使用 btrfs subvolume list /mnt | grep @home$ 來查詢新的 subvolid


重新啟動計算機。

檢查計算機運行是否正常。這時可以刪除在還原之前創建的快照了——例如@home-backup。在刪除前記得檢查是否有需要保留的數據。

刪除快照

要刪除序號為 N 的快照:

 # snapper -c config delete N

可以一次刪除多個快照。例如,要刪除 root 配置文件的 65 和 70 號快照:

 # snapper -c root delete 65 70

要同時刪除多個連續的快照,例如刪除 65 到 70 號所有快照:

# snapper -c root delete 65-70

要立即釋放快照占用的磁碟空間,使用 --sync 選項:

# snapper -c root delete --sync 65

要刪除一個 Snapper 配置和其所有快照,包括 .snapshots 子卷:

# snapper -c config delete-config 
注意:刪除 pre 快照時, 你應該總是刪除對應的 post 快照。反之亦然。

允許非 root 用戶訪問

所有配置文件都是由 root 用戶創建的,默認情況下,也只有 root 用戶可以查看並訪問它們。

要讓指定用戶可以列出某一配置文件的快照,修改 /etc/snapper/configs/config 中的 ALLOW_USERS 項。現在你應該可以以普通用戶權限運行 snapper -c configlist

最後,如果你想允許某一用戶瀏覽 .snapshots 目錄,但是該目錄的擁有者必須為 root。因此,你應該修改包括該用戶的組為組擁有者,以 users 為例:

# chmod a+rx .snapshots
# chown :users .snapshots

提示與技巧

在進行 pacman 操作時創建快照

下列軟體包可以依據 pacman 進行的事務自動創建快照。

https://github.com/wesbarnett/snap-pac || snap-pac
  • grub-btrfs — 包含了一個名為 grub-btrfsd 的 systemd 單元。可自動查找快照並將其添加到 GRUB 菜單中。
https://github.com/Antynea/grub-btrfs || grub-btrfs
https://github.com/maximbaz/snap-pac-grub || snap-pac-grubAUR
  • refind-btrfs — 在 snap-pac 創建快照後自動在 rEFInd 中創建啟動項。
https://github.com/Venom1991/refind-btrfs || refind-btrfsAUR
  • snp — 包裝任何 shell 命令以供創建 pre/post 快照(例如snp pacman -Syu)相比 Snapper 自身的 --command 選項能更好的處理輸出重定向(參見 #pre/post 快照)。
https://gist.github.com/erikw/5229436 || snpAUR
https://gitlab.com/Zesko/limine-snapper-sync || limine-snapper-syncAUR

啟動到只讀快照中

使用 grub-btrfssnap-pac-grubAURlimine-snapper-syncAUR的用戶應該注意:在默認狀態下,Snapper 創建的快照是只讀的。而在啟動到只讀快照時會有一些困難。許多服務,例如顯示管理器,都需要一個可寫的 /var 目錄。在啟動到只讀快照時,這些服務將無法正常工作。

為了避免這個問題,可以使快照設為可寫,或者使用 overlayfs 啟動到快照中,這也是開發者認可的方法。這種情況下快照像是一個 Live CD 環境。

注意: 任何對快照中文件的更改都不會被保存,因為文件系統只是存在於內存上。

要使用 overlayfs 啟動快照:

  • 確保 grub-btrfs 已經安裝。
  • 添加 grub-btrfs-overlayfs/etc/mkinitcpio.conf HOOKS 的末尾。例如:
    HOOKS=(base udev autodetect microcode modconf kms keyboard keymap consolefont block filesystems fsck grub-btrfs-overlayfs)
注意:因為 grub-btrfs-overlayfs只提供了 運行時鉤子,沒有提供 systemd 單元,所以並支持基於 systemd 的 initramfs。確保你使用的是 基於 Busybox 的 initramfs。參見GitHub issue

進一步了解:

提示:你可以使用 Limine 啟動到快照中。Limine 和 Snaper 間的集成由 limine-snapper-syncAUR 提供。參見Limine#Snapper snapshot integration for Btrfs

在進行 pacman 事務時備份非 btrfs /boot 分區

如果你的 /boot 分區是在一個非 btrfs 文件系統上(例如一個 ESP 分區),Snapper 無法備份這些分區。 在系統備份#快照與_/boot_分區中提供了一個自動在內核更新時將 /boot複製到你的 btrfs 根目錄下的方法。這種方法也能和 snap-pac 一起使用。

增量備份到外部驅動器

一些工具可以使用 Snapper 進行自動備份。參見 Btrfs#增量備份到外置設備

建議的文件系統布局

注意:下列布局是為了與 snapper rollback 搭配使用。而是為了緩解#Restoring / to its previous snapshot 中的某些問題。參見 論壇帖子

這是一種建議的文件系統布局,可以方便的將掛載到 /@ 子卷還原到之前的狀態:

文件系統布局
子卷 掛載點
@ /
@home /home
@snapshots /.snapshots
@var_log /var/log
subvolid=5
  |
  ├── @ -|
  |     contained directories:
  |       ├── /usr
  |       ├── /bin
  |       ├── /.snapshots
  |       ├── ...
  |
  ├── @home
  ├── @snapshots
  ├── @var_log
  └── @...

子卷@...應當掛載到任何應有自己子卷的目錄。

注意:
  • 當對 @ 子卷(掛載到/)創建快照時,其餘子卷的將不會被包含在快照中。即使這些子卷位於 @ 之下(子卷不是遞歸包含的)。如果需要為其他子卷創建快照,需要單獨為這些子卷創建 Snapper 配置。
  • 由於Btrfs 的限制,需要創建快照的子卷中不能包含swap 文件。將 swap 文件放到另外的子卷或者使用 swap 分區

如果你想將@子卷恢復到之前的狀態,其他的子卷將不會被影響。例如,當你在將@恢復到之前的快照時,/home將不會受到影響,因為/home掛載到了單獨的子卷下。

這個布局能使 Snapper 定期為 /創建快照,並能讓在出現啟動問題時更容易還原快照。

在這種情況下,進行初始設置之後,Snapper不需要更多配置。

提示:
  • 考慮為其他不想包含在@快照中的目錄創建子卷。例如 /var/cache, /var/spool, /var/tmp, /var/lib/machines (systemd-nspawn), /var/lib/docker (Docker), /var/lib/postgres (PostgreSQL),或是其他 /var/lib/ 下的目錄。你可以使用類似上面的平行子卷結構,或是創建下層子卷。但是,pacman 資料庫 /var/lib/pacman 必須位於掛載到/的子卷下。
  • 你可以為@home或是其他子卷單獨創建快照或者還原快照。

配置 Snapper 和掛載點

假定@掛載到了/下,同時 /.snapshots 未被掛載,同時也不存在同名目錄。可以使用如下命令確認:

# umount /.snapshots
# rm -r /.snapshots

接下來為/#建立一個新的配置。Snapper 會自動在@下創建 .snapshots 子卷。這在建議的布局下是不必要的,可以刪除。

# btrfs subvolume delete /.snapshots

刪除這個子卷之後,重新創建 /.snapshots 目錄。

# mkdir /.snapshots

現在將 @snapshots 子卷掛載/.snapshots 目錄。例如,當文件系統位於 /dev/sda1 時:

# mount -o subvol=@snapshots /dev/sda1 /.snapshots

要使此配置永久生效,在 fstab 中添加條目。

若 fstab 中已存在這個條目,重新掛載:

# mount -a

將此文件夾權限設為 750

這將使 Snapper 創建的快照儲存在 @ 之外。所以 @ 被還原或替換時也不會丟失快照。

還原到之前的快照

要將 / 還原到某個快照的狀態,首先啟動到 Arch Linux Live CD。

掛載頂層子卷(subvolid=5)。也就是說,不使用任何 subvolidsubvol 掛載參數。

找到想還原快照的序號:


# grep -r '<date>' /mnt/@snapshots/*/info.xml

輸出類似這樣。每個快照都單獨顯示為一行,所以能很方便的按照時間查找序號。

/mnt/@snapshots/number/info.xml:  <date>2021-07-26 22:00:00</date>
注意:info.xml記錄的時間為 UTC 時間,請務必將其和本地時間的時差計算在內。

記住number

@移動到其他位置,例如 /@.broken來備份當前的系統狀態。或是直接刪除@子卷:btrfs subvolume delete /mnt/@

為 Snapper 創建的快照創建一個可讀寫快照:

# btrfs subvolume snapshot /mnt/@snapshots/number/snapshot /mnt/@

number 替換為你想還原的快照序號。

注意:如果在 fstab中指定的是 subvolid 而不是子卷路徑,則需要更改 /mnt/@/etc/fstab 中的 subvolid(假定把@子卷掛載到了/)。 可以使用 btrfs subvolume list /mnt | grep @$ 來查詢新的 subvolid。另外若在啟動加載器中使用了 subvolid,也需要一併更改。例如 refind_linux.conf

最後,卸載頂層子卷(subvolid=5),掛載@/mnt以及 ESP分區。chroot到完成還原的根目錄下,並重新生成 initramfs

現在/已經恢復到了之前快照的狀態。重新啟動計算機。

提示:你也可以使用為這種布局設計的自動回滾工具:snapper-rollbackAUR。編輯 /etc/snapper-rollback.conf 來匹配系統的實際布局情況。

還原其他子卷到之前的狀態

參見#還原快照

從快照中刪除文件

若你想刪除指定的文件或文件夾而不想刪除整個快照,可以使用 snappersAUR 實現。這個腳本還可用於以 Snapper 目前不支持的其他方式操作過去的快照。

若你不想使用其他腳本,你可以使 快照變為可讀寫

# btrfs property set /path/to/.snapshots/<snapshot_num>/snapshot ro false

驗證 ro=false

# btrfs property get /path/to/.snapshots/<snapshot_num>/snapshot
ro=false

現在可以像平常一樣修改 /path/to/.snapshots/<snapshot_num>/snapshot 了。你也可以使用 shell 循環批量處理快照。

減緩性能影響

/這種繁忙的文件系統中,長時間保留大量快照會導致嚴重的性能影響。你可以通過以下方式減緩影響:

  • 為不值得被快照的目錄創建單獨的子卷,例如/var/cache/pacman/pkg/var/abs/var/tmp/srv
  • 編輯默認創建快照的頻率,參見#自動按時創建快照

updatedb

默認情況下,updatedb(參見locate)也會索引由 snapper 創建的 .snapshots 目錄,如果快照較多,這可能會導致運行速度嚴重的性能影響和大量內存占用。你可以編輯updatedb,阻止.snapshots索引該目錄:

/etc/updatedb.conf
PRUNENAMES = ".snapshots"

禁用配額

有報告稱,配額會導致運行速度明顯變慢,例如,snapper ls需要數分鐘才能返回結果,這可能就是配額導致的。參見 [3]

要確定配額是否已啟用,使用如下命令:

# btrfs qgroup show /

可以使用如下命令禁用配額:

# btrfs quota disable /

計算快照數量

如果禁用配額沒有減緩性能問題,那麼計算快照數量可能會有用:

# btrfs subvolume list -s / | wc -l

為用戶數據和日誌創建子卷

如果目錄中包含用戶數據(如電子郵件或日誌),建議將其存儲在自己的子卷而不是根子卷 / 中。這樣,如果恢復 / 的快照,用戶數據和日誌不會受到影響。可以為用戶數據使用單獨的 timeline。不建議為 /var/log 創建日誌快照。這可能會導致難以排除故障。

還可以使用#過濾配置在還原過程中跳過某些目錄。有關跳過某些目錄的示例和原因,請參閱 SLES 文檔

依據磁碟使用量清理快照

這篇文章的某些內容需要擴充。

原因:See [4] for ideas. (在 Talk:Snapper 中討論)


疑難解答

日誌

Snapper 將所有活動寫入到 /var/log/snapper.log 中——在你認為出錯時,首先檢查該文件。

當你遇到關於每小時/每日/每周快照的問題時,最常見的原因是由於 cronie 服務(或者你使用的其他 cron 守護進程)沒有運行。

IO 錯誤

如果你在試圖創建快照時遇到 'IO Error',請確認你試圖創建快照的子卷對應的 .snapshots 目錄是一個子卷。

另一個可能的原因是 .snapshots 目錄的擁有者不是 root。你會在在 /var/log/snapper.log 中找到 Btrfs.cc(openInfosDir):219 - .snapshots must have owner root

未被管理的快照導致空間浪費

快照有可能「丟失」,它們仍然存在於磁碟上,但不會被 snapper 管理。這會造成大量磁碟空間浪費。要檢查這種情況,請比較:

# snapper -c <config> list

# btrfs subvolume list -o <parent subvolume>/.snapshots 

第二個命令列出的子卷但未出現在第一個命令的輸出中的都是未被 snapper 管理的快照。可以手動刪除

相關資源