Snapper - Arch Linux 中文维基

跳至內容

# Snapper

出自 Arch Linux 中文维基
翻譯狀態：

- 本文（或部分內容）譯自 Snapper，最近一次同步於 2025-02-08，若英文版本有所更改，則您可以幫助同步與翻譯更改的內容。
- 您可以在 ArchWiki 的對應頁面找到本文翻譯的原始修訂歷史。
- 本文可能與英文原文存在出入。

相關文章

- Btrfs
- mkinitcpio-btrfs

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

## 安裝

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

此外，還可以安裝 GUI 前端 snapper-gui-gitAUR、btrfs-assistant包 或 snapper-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/snapper` 的 `SNAPPER_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` 選項，並在 `number`，`timeline`，`pre` 或 `post` 中選擇一個參數。 `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 進行的事務自動創建快照。

- snap-pac — 使用 pacman 鉤子使 pacman 自動使用 Snapper 創建#pre/post 快照。類似與 openSUSE 的 YaST 的行為。

  https://github.com/wesbarnett/snap-pac || snap-pac包

- grub-btrfs — 包含了一個名為 grub-btrfsd 的 systemd 單元。可自動查找快照並將其添加到 GRUB 菜單中。

  https://github.com/Antynea/grub-btrfs || grub-btrfs包

- snap-pac-grub — 在 snap-pac包 創建快照後自動使用 grub-btrfs包 更新 GRUB 啟動項。同樣使用pacman 鉤子。

  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

- limine-snapper-sync — 在 snap-pac包 創建快照後自動在 Limine 中創建啟動項。（參見Limine#Snapper snapshot integration for Btrfs）

  https://gitlab.com/Zesko/limine-snapper-sync || limine-snapper-syncAUR

#### 啟動到只讀快照中

使用 grub-btrfs包、snap-pac-grubAUR或limine-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。

- 重新生成 initramfs。

進一步了解：

- grub-btrfs README （包含了使用 dracut包 而不是 mkinitcpio包 的配置方法）
- Github 上的討論

提示：你可以使用 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）。也就是說，不使用任何 `subvolid` 或 `subvol` 掛載參數。

找到想還原快照的序號：

    # 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"

#### 禁用配額

Btrfs 的配額功能（不是後來引入的「簡單配額」（simple quota））可能會導致刪除快照時占用大量 CPU 來維護配額信息。

要確定配額是否已啟用，使用如下命令：

    # btrfs qgroup show /

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

    # btrfs quota disable /

#### 計算快照數量

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

    # btrfs subvolume list -s / | wc -l

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

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

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

### 依據磁碟使用量清理快照

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

原因：See [3] 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 管理的快照。可以手動刪除。

## 相關資源

- Snapper homepage
- openSUSE Snapper portal
- Btrfs homepage
- Linux.com: Snapper: SUSE's Ultimate Btrfs Snapshot Manager

分類：​

- 文件系統
- 包含失效連結的頁面

隱藏分類：​

- 使用「模板:準確性」標記的頁面或章節

Snapper
新增話題