Snapper

提供: ArchWiki
2019年6月2日 (日) 14:17時点におけるHiromi-mi (トーク | 投稿記録)による版 (英語版と同期)
ナビゲーションに移動 検索に移動

関連記事

Snapper は openSUSE の Arvin Schnell によって作られた、Btrfs のサブボリュームと LVM のボリュームのスナップショットの管理を助けるツールです。スナップショットを作成して比較したり、前のスナップショットに戻したり、自動スナップショットが行えます。

インストール

安定版は snapper パッケージからインストールできます。開発版は snapper-gitAUR パッケージで利用可能です。

GUI は snapper-gui-gitAUR パッケージでインストールすることができます。

新しい設定の作成

Btrfs サブボリュームで Snapper の設定を作成する前に、あらかじめサブボリュームが作成されている必要があります。サブボリュームが存在しない場合、Snapper の設定をするまえにサブボリュームを作成してください。

Btrfs サブボリュームが /path/to/subvolume に存在していて、config という名前で新しく Snapper の設定を作るには:

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

上記のコマンドを実行すると:

  • /etc/snapper/config-templates にあるデフォルトのテンプレートに基づいて /etc/snapper/configs/config に設定ファイルが作成されます。
  • /path/to/subvolume/.snapshots にサブボリュームが作成されてスナップショットが保存されます。スナップショットのパスは /path/to/subvolume/.snapshots/#/snapshot になります (# はスナップショット番号です)。
  • /etc/conf.d/snapperSNAPPER_CONFIGSconfig が追加されます。

例えば、/ にマウントされたサブボリュームの設定ファイルを作成する場合:

# snapper -c root create-config /

この時点で、設定は有効になっています。cron デーモンが動作している場合、snapper は自動タイムラインスナップショットを作成します。cron デーモンを使っていない場合、systemd サービスとタイマーを使用する必要があります。#有効化/無効化を見てください。

設定について詳しくは snapper-configsman ページを参照。

スナップショットの作成

自動タイムラインスナップショット

Snapper では毎時・毎日・毎月・毎年に保存するスナップショットの数を設定できるスナップショットタイムラインを作成することができます。デフォルトでは1時間毎にスナップショットが取得されます。そして1日1回、タイムラインのクリーンアップアルゴリズムによって"古くなって要らなくなった"スナップショットを削除します。

有効化/無効化

cron デーモンが動作している場合、自動タイムラインスナップショットは自動的に起動します。無効化するには、サブボリュームに存在する設定ファイルを編集して以下を設定してください:

TIMELINE_CREATE="no"

cron デーモンを使っていない場合、パッケージに含まれている systemd ユニットを使うことができます。snapper-timeline.timer起動有効化することで自動タイムラインスナップショットが開始されます。さらに、snapper-cleanup.timer起動有効化すると定期的に古いスナップショットが消去されます。

ノート: cron デーモンと有効化された systemd ユニットがともに動作すると、重複したスナップショットが作成される結果になる場合があります。systemd ユニットを使いつつ cron 側を無効にできるかもしれない一つの手法に、pacmanNoExtract および NoUpgrade を使い、snapper のパッケージの cron ファイルをインストールしない方法があります。[1] を見てください。

スナップショットのリミットの設定

デフォルト設定では、毎時間10個、毎日10個、毎月10個、毎年10個のスナップショットが保存されます。/ など頻繁にサブボリュームに変更を加える場合は、この設定を変更したほうが良いでしょう。#ドライブの負担を抑えるを見て下さい。

以下は、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 を編集して以下のようにすることで5分毎にスナップショットが作成されます:

[Timer]
OnCalendar=
OnCalendar=*:0/5
ノート: 設定パラメータ TIMELINE_LIMIT_HOURLY は上記の設定に関連付けられています。上の例では5分毎にスナップショットが作成されるようになります。

snapper-cleanup.timer を編集するときは OnUnitActiveSec を変更してください。1時間毎に古いスナップショットを消去するには、以下を追加:

[Timer]
OnUnitActiveSec=1h

詳しくは Systemd/タイマーSystemd#ドロップインファイルを参照。

手動スナップショット

シンプルなスナップショット

デフォルトでは Snapper は他のスナップショットと特別な関係を持たない、単純なスナップショットを作成します。

手動でサブボリュームのスナップショットを作成するには、以下のコマンドを実行:

# snapper -c config create --description desc

上記のコマンドはクリーンアップアルゴリズムを使用しないため、スナップショットは明示的に削除するまでずっと残り続けます。

クリーンアップアルゴリズムを設定するには create の後に -c フラグを使用して number, timeline, pre, post のどれかを選択してください。number は設定ファイルで指定された番号にあわせて定期的にスナップショットを削除します。例えば、number アルゴリズムを使用するスナップショットを作成するには:

# snapper -c config create -c number

timeline スナップショットについては自動タイムラインスナップショットを、prepost については事前事後のスナップショットを見てください。

事前事後のスナップショット

シンプルなスナップショットだけでなく、Snapper では事前事後のスナップショットを作成できます。事前 (pre) スナップショットには必ず対応する事後 (post) スナップショットが存在します。このペアによってシステムに変更を加える前後のスナップショットを作成することができます。

事前事後のスナップショットを作成するには、まず事前スナップショットを作成:

# snapper -c config create -t pre -p

上記のコマンドでスナップショット番号が出力されます。

それからシステムに何らかの変更を加えます (例えば新しいプログラムをインストールしたり、ソフトウェアをアップグレードするなど)。

次に事後のスナップショットを作成:

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

# は事前スナップショットの番号に置き換えてください。

create--command フラグを指定して、コマンドをラップすることもできます:

# snapper -c config create --command cmd

cmd は事前事後のスナップショットを作成する間に実行したいコマンドに置き換えてください。

pacman のトランザクションをスナップショットで記録も見てください。

起動時にスナップショットを作成

snapper で root 設定のスナップショットを作成するには snapper-boot.timer有効化してください。

スナップショットの確認

作成されたスナップショットを確認するには:

# snapper -c config list

設定の確認

全ての設定を確認するには:

# snapper list-configs

スナップショットの削除

スナップショット番号 # を削除するには:

# snapper -c config delete #

一度に複数のスナップショットを削除できます。例えば、root 設定の65と70のスナップショットを削除するには:

# snapper -c root delete 65 70
ノート: 事前スナップショットを削除した場合、事後スナップショットも一緒に削除してください。逆も然りです。

root 以外のユーザーでアクセス

設定は root ユーザーによって作成され、デフォルトでは、root だけが設定を確認したり変更できます。

特定のユーザーからもスナップショットを確認できるようにしたいときは、/etc/snapper/configs/config ファイルの ALLOW_USERS の値を変更してください。そうすれば通常ユーザーでも snapper -c configlist を実行できるようになります。

さらに、ユーザーを使って .snapshots ディレクトリを閲覧できるようにしたい、それでいてディレクトリの所有者は root のままにしておきたいということが考えられます。そのような場合、使用したいユーザーが属しているグループに、グループ所有者を変更してください。例えば users を使う場合:

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

ヒントとテクニック

pacman のトランザクションをスナップショットで記録

pacman の操作時に自動的にスナップショットを作成するためのパッケージが複数存在します:

  • pacupg — Btrfs のスナップショットでパッケージと AUR のアップグレードを記録して、簡単にロールバックできるようにするスクリプト。
https://github.com/crossroads1112/bin/tree/master/pacupg || pacupgAUR
https://github.com/wesbarnett/snap-pac || snap-pac
  • snap-pac-grubsnap-pac でスナップショットが作成された後に grub-btrfs 用に GRUB エントリを更新します。Pacman#フックを使用します。
|| snap-pac-grubAUR
  • snp — シェルコマンドの実行前後に snapper でスナップショットを取るラッパー。例: $ snp pacman -Syu
https://gist.github.com/erikw/5229436 ||

boot パーティションのバックアップ

/boot パーティションが btrfs ファイルシステム上に存在しない場合 (例: ESP)、snapper でバックアップすることはできません。フックを使用してカーネルのアップデート時に boot パーティションを自動的に btrfs ファイルシステムにコピーさせることはできます。snap-pac でも上手くバックアップされます。

/usr/share/libalpm/hooks/50_bootbackup.hook
[Trigger]
Operation = Upgrade
Operation = Install
Operation = Remove
Type = Package
Target = linux*

[Action]
Depends = rsync
Description = Backing up /boot...
When = PreTransaction
Exec = /usr/bin/rsync -a --delete /boot /.bootbackup

外部ドライブに差分バックアップ

以下のパッケージは btrfs sendbtrfs receive を使用して外部ドライブにバックアップを差分で送信します:

  • buttersink — Btrfs スナップショットの rsync のようなもので、スナップショットの差分だけを送信することで自動的に同期を最適化します。
https://github.com/AmesCornish/buttersink.git || buttersink-gitAUR
  • snap-sync — snapper スナップショットを使用して外部ドライブにバックアップします。
https://github.com/wesbarnett/snap-sync.git || snap-sync
  • snapsync — snapper 用の同期ツール。
https://github.com/doudou/snapsync || ruby-snapsyncAUR

推奨ファイルシステムレイアウト

ノート: 以下のレイアウトは snapper rollback を使用することは想定していませんが、コマンドで / をリストアしたときの問題を軽減します。フォーラムスレッド を参照してください。

以下は / を簡単に復元できるようにするための推奨ファイルシステムレイアウトです:

subvolid=5
   |
   ├── @
   |       |
   |       ├── /usr
   |       |
   |       ├── /bin
   |       |
   |       ├── /.snapshots
   |       |
   |       ├── ...
   |
   ├── @snapshots
   |
   └── @...

/.snapshots@snapshots のマウントポイントです。@.../ にマウントするサブボリューム (@) とは別に保存したいサブボリュームになります。/ のスナップショットを作成するとき、他のサブボリュームはスナップショットに含まれません。ただし、別の snapper 設定を作成することで他のサブボリュームもスナップショットで記録できます。システムを / のスナップショットの時点まで戻したいと思ったときに、他のサブボリュームには影響が及びません。

例えば、/ をスナップショット時に戻したいが /home は最新の状態のままにしたい場合、サブボリュームを作成して /home にマウントしてください。詳しくは Btrfs#サブボリュームをマウントするを参照。

上記のレイアウトは snapper ユーティリティで定期的に / のスナップショットが作成できるのと同時に、起動できなくなった場合に Arch のライブ CD から / を簡単に復元することができます。

その場合、初期設定をしたら snapper に特別な設定をする必要はありません。

ノート: サブボリュームが @ 下に入れ子になっていても、/ のスナップショットには含まれません。/ にマウントしているサブボリュームのスナップショットを保存したい場合は snapper でサブボリュームの設定を行ってください。

snapper の設定とマウントポイント

/.snapshots がマウントされていないこと、フォルダとして存在しないことを確認してください:

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

それから /新しい設定を作成します。

そして @snapshots/.snapshotsマウントしてください。例えば、ファイルシステムが /dev/sda1 に存在する場合:

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

マウントを永続化させるには、fstab にエントリを作成します。

もしくは fstab エントリが既に存在する場合、スナップショットのサブボリュームを再マウントします:

# mount -a

フォルダには 750パーミッションを設定してください。

snapper が作成するスナップショットは全て @ サブボリュームの外に保存されるため、snapper のスナップショットを削除しなくても @ を簡単に置き換えることができます。

/@ のスナップショットに復元

snapper のスナップショットを使って / をリストアしたくなったら、まずは Arch Linux のライブ USB/CD を起動します。

トップレベルのサブボリューム (subvolid=5) をマウントしてください。subvolid マウントフラグは省略します。

/mnt/@snapshots/*/info.xml から復元したいスナップショットを確認します:

ヒント: vi を使ってファイルを確認できます:
# vi /mnt/@snapshots/*/info.xml
次のファイルを見たいときは :n を、最初のファイルに戻りたいときは :rew を使用します。

<description> タグと <date> タグを見て、リストアしたいスナップショットが確認できたら、<num> の番号をメモしてください。

そして @ を他の場所 (例: /@.broken) にして現在のシステムのコピーを保存します。もしくは btrfs subvolume delete@ を削除します。

読み取り専用のスナップショットから読み書き可能なスナップショットを作成:

# btrfs subvol snapshot /mnt/@snapshots/#/snapshot /mnt/@

# は復元したい snapper のスナップショットの番号に置き換えてください。これで / は前の状態に戻ります。再起動してください。

スナップショットからファイルを削除

過去のスナップショットから特定のファイルやフォルダを削除したい場合、snapperS というスクリプトが存在します。

スクリプトを使わずにファイルを削除したい場合、以下のコマンドを実行して スナップショットのサブボリュームを読み書き可能 にする必要があります:

# 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 のファイルは通常通りに編集することが可能になります。

ドライブの負担を抑える

頻繁に変更が加わるファイルシステム (例えば多数のシステムアップデートが行われる / など) で長期間にわたって頻繁にスナップショットを取得すると動作がかなり遅くなることがあります。以下のようにすることで遅くなるのを回避できます:

  • スナップショットを作成する価値がない /var/cache/pacman/pkg, /var/abs, /var/tmp, /srv などのサブボリュームを作成する。
  • 自動タイムラインスナップショットを使う場合に、毎時・毎日・毎周・毎年のスナップショットのデフォルト設定を変更する。

updatedb

デフォルトでは、updatedb は snapper によって作成された .snapshots ディレクトリのインデックスも作成してしまい、スナップショットが大量にある場合、深刻な遅延が発生したりメモリが異常に消費される原因になります。以下のように設定ファイルを編集することでインデックスを作成しないように updatedb を設定できます:

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

ログファイルの保持

/var/log のサブボリュームを作成して / のスナップショットに含まれないようにすることを推奨します。/ のスナップショットを復元したときにログファイルまで前の状態に戻ってしまうことがなくなり、トラブルシューティングが楽になります。

トラブルシューティング

Snapper のログ

Snapper は全ての活動を /var/log/snapper.log に書き出します。何か問題が発生しているように感じたら真っ先にこのファイルをチェックしてください。

毎時・毎日・毎週のスナップショットに問題がある場合、おそらく cronie サービス (もしくはその他の cron デーモン) が動いていなかったのが原因だということが多くあります。

IO エラー

スナップショットを作成しようとすると IO エラーが表示される場合、スナップショットを作成しようとしたサブボリュームと関連付けられている .snapshots ディレクトリもサブボリュームになっていることを確認してください。

また、.snapshots の所有者が root になっていない可能性もあります (/var/log/snapper.logBtrfs.cc(openInfosDir):219 - .snapshots must have owner root というエラーが出力されます)。

参照