snapper

まあ、何だ、いろいろな方法でsnapshotを取る類のもののようだが、主にはbtrfs。それかlvm。でもこれほぼbtrfs用なのでは。

参考: https://wiki.archlinuxjp.org/index.php/Snapper

ここではdebian jessieの版で試してみよう。

# apt-get install -s snapper
パッケージリストを読み込んでいます... 完了
依存関係ツリーを作成しています
状態情報を読み取っています... 完了
以下の追加パッケージがインストールされます:
  libboost-system1.55.0 libboost-thread1.55.0 libsnapper2
以下のパッケージが新たにインストールされます:
  libboost-system1.55.0 libboost-thread1.55.0 libsnapper2 snapper
アップグレード: 0 個、新規インストール: 4 個、削除: 0 個、保留: 0 個。
Inst libboost-system1.55.0 (1.55.0+dfsg-3 Debian:8.4/stable [amd64])
Inst libboost-thread1.55.0 (1.55.0+dfsg-3 Debian:8.4/stable [amd64])
Inst libsnapper2 (0.2.4-1 Debian:8.4/stable [amd64])
Inst snapper (0.2.4-1 Debian:8.4/stable [amd64])
Conf libboost-system1.55.0 (1.55.0+dfsg-3 Debian:8.4/stable [amd64])
Conf libboost-thread1.55.0 (1.55.0+dfsg-3 Debian:8.4/stable [amd64])
Conf libsnapper2 (0.2.4-1 Debian:8.4/stable [amd64])
Conf snapper (0.2.4-1 Debian:8.4/stable [amd64])

このようにシミュレーションしてみても依存は少ない、いれてしまえという事。

# dpkg -L snapper
/.
/usr
/usr/share
/usr/share/dbus-1
/usr/share/dbus-1/system-services
/usr/share/dbus-1/system-services/org.opensuse.Snapper.service
/usr/share/locale
/usr/share/locale/el
/usr/share/locale/el/LC_MESSAGES
/usr/share/locale/el/LC_MESSAGES/snapper.mo
/usr/share/locale/cs
/usr/share/locale/cs/LC_MESSAGES
/usr/share/locale/cs/LC_MESSAGES/snapper.mo
/usr/share/locale/de
/usr/share/locale/de/LC_MESSAGES
/usr/share/locale/de/LC_MESSAGES/snapper.mo
/usr/share/locale/da
/usr/share/locale/da/LC_MESSAGES
/usr/share/locale/da/LC_MESSAGES/snapper.mo
/usr/share/locale/ko
/usr/share/locale/ko/LC_MESSAGES
/usr/share/locale/ko/LC_MESSAGES/snapper.mo
/usr/share/locale/nb
/usr/share/locale/nb/LC_MESSAGES
/usr/share/locale/nb/LC_MESSAGES/snapper.mo
/usr/share/locale/pl
/usr/share/locale/pl/LC_MESSAGES
/usr/share/locale/pl/LC_MESSAGES/snapper.mo
/usr/share/locale/tr
/usr/share/locale/tr/LC_MESSAGES
/usr/share/locale/tr/LC_MESSAGES/snapper.mo
/usr/share/locale/pt_BR
/usr/share/locale/pt_BR/LC_MESSAGES
/usr/share/locale/pt_BR/LC_MESSAGES/snapper.mo
/usr/share/locale/zh_TW
/usr/share/locale/zh_TW/LC_MESSAGES
/usr/share/locale/zh_TW/LC_MESSAGES/snapper.mo
/usr/share/locale/nl
/usr/share/locale/nl/LC_MESSAGES
/usr/share/locale/nl/LC_MESSAGES/snapper.mo
/usr/share/locale/lt
/usr/share/locale/lt/LC_MESSAGES
/usr/share/locale/lt/LC_MESSAGES/snapper.mo
/usr/share/locale/es
/usr/share/locale/es/LC_MESSAGES
/usr/share/locale/es/LC_MESSAGES/snapper.mo
/usr/share/locale/zh_CN
/usr/share/locale/zh_CN/LC_MESSAGES
/usr/share/locale/zh_CN/LC_MESSAGES/snapper.mo
/usr/share/locale/ru
/usr/share/locale/ru/LC_MESSAGES
/usr/share/locale/ru/LC_MESSAGES/snapper.mo
/usr/share/locale/km
/usr/share/locale/km/LC_MESSAGES
/usr/share/locale/km/LC_MESSAGES/snapper.mo
/usr/share/locale/fi
/usr/share/locale/fi/LC_MESSAGES
/usr/share/locale/fi/LC_MESSAGES/snapper.mo
/usr/share/locale/sv
/usr/share/locale/sv/LC_MESSAGES
/usr/share/locale/sv/LC_MESSAGES/snapper.mo
/usr/share/locale/ar
/usr/share/locale/ar/LC_MESSAGES
/usr/share/locale/ar/LC_MESSAGES/snapper.mo
/usr/share/locale/fr
/usr/share/locale/fr/LC_MESSAGES
/usr/share/locale/fr/LC_MESSAGES/snapper.mo
/usr/share/locale/ja
/usr/share/locale/ja/LC_MESSAGES
/usr/share/locale/ja/LC_MESSAGES/snapper.mo
/usr/share/locale/hu
/usr/share/locale/hu/LC_MESSAGES
/usr/share/locale/hu/LC_MESSAGES/snapper.mo
/usr/share/locale/it
/usr/share/locale/it/LC_MESSAGES
/usr/share/locale/it/LC_MESSAGES/snapper.mo
/usr/share/doc
/usr/share/doc/snapper
/usr/share/doc/snapper/changelog.Debian.gz
/usr/share/doc/snapper/copyright
/usr/share/doc/snapper/AUTHORS
/usr/share/doc/snapper/dbus-protocol.txt
/usr/share/man
/usr/share/man/man5
/usr/share/man/man5/snapper-configs.5.gz
/usr/share/man/man8
/usr/share/man/man8/snapperd.8.gz
/usr/share/man/man8/pam_snapper.8.gz
/usr/share/man/man8/snapper.8.gz
/usr/bin
/usr/bin/snapper
/usr/sbin
/usr/sbin/snapperd
/etc
/etc/logrotate.d
/etc/logrotate.d/snapper
/etc/snapper
/etc/snapper/configs
/etc/snapper/config-templates
/etc/snapper/config-templates/default
/etc/snapper/filters
/etc/snapper/filters/x11.txt
/etc/snapper/filters/lvm.txt
/etc/snapper/filters/base.txt
/etc/dbus-1
/etc/dbus-1/system.d
/etc/dbus-1/system.d/org.opensuse.Snapper.conf
/etc/cron.hourly
/etc/cron.hourly/snapper
/etc/cron.daily
/etc/cron.daily/snapper
/etc/default
/etc/default/snapper

デーモンではなく、cronなどで起動されてくるタイプのもの、のように見えるが、snapperdというのもある。spamassasinのようなものだろうか? /etc/cron.*/以下にいろいろファイルがおかれているがこの手のタイプはとにかく/etc/default/snapperを見るべきかもしれないが、とりあえずちょっと置いておく。

前提と事前準備

btrfsを利用する。/dev/sdh1をまるごとbtrfsでフォーマットしておきました。デバイスファイル名などは適時読みかえてください。

とりあえず/backup.mediaに(親を)mountしてある状況

# df -h | grep backup.media
/dev/sdg1        2.8T  544K  2.8T    1% /backup.media

コンフィグを作成する

# snapper -c media create-config /backup.media/

-c の後はコンフィグ名(任意)。 そして後ろが生成先である。なので、config名とpathは適当に変更する事

で、。。とかすると /etc/snapper/の下などが更新されるというなかなか強烈な操作が行われる、のと、対象ディレクトリにサブボリュームが生成される(ここでは/backup.media)

/etc/snapper/configs/media
/etc/default/snapper

この辺が更新されるので見てみよう。

/etc/defaults/snapper

## Path: System/Snapper

## Type:        string
## Default:     ""
# List of snapper configurations.

SNAPPER_CONFIGS="media"

これは後ほど。で、 /etc/snapper/configs/media (最後のmediaていうのは当然config名を変更すると変わる)

# subvolume to snapshot
SUBVOLUME="/backup.media"

# filesystem type
FSTYPE="btrfs"


# users and groups allowed to work with config
ALLOW_USERS=""
ALLOW_GROUPS=""

# sync users and groups from ALLOW_USERS and ALLOW_GROUPS to .snapshots
# directory
SYNC_ACL="no"


# start comparing pre- and post-snapshot in background after creating
# post-snapshot
BACKGROUND_COMPARISON="yes"


# run daily number cleanup
NUMBER_CLEANUP="yes"

# limit for number cleanup
NUMBER_MIN_AGE="1800"
NUMBER_LIMIT="50"
NUMBER_LIMIT_IMPORTANT="10"


# create hourly snapshots
TIMELINE_CREATE="yes"

# cleanup hourly snapshots after some time
TIMELINE_CLEANUP="yes"

# limits for timeline cleanup
TIMELINE_MIN_AGE="1800"
TIMELINE_LIMIT_HOURLY="10"
TIMELINE_LIMIT_DAILY="10"
TIMELINE_LIMIT_MONTHLY="10"
TIMELINE_LIMIT_YEARLY="10"


# cleanup empty pre-post-pairs
EMPTY_PRE_POST_CLEANUP="yes"

# limits for empty pre-post-pair cleanup
EMPTY_PRE_POST_MIN_AGE="1800"

まあいろいろ書いてあるのだが、最初はこれでよしとしよう。あとは生成先だが

/backup.media
/backup.media/.snapshots

となっている。タイミングがタイミングだと、もう少し増えちゃってるかもしれないが。ともあれこれはsubvolumeなのでrmでは消せない。

# btrfs subvolume list /backup.media 
ID 260 gen 24 top level 5 path .snapshots

で、先にタイミングと書いたが、この次点で実はもう動作し初めている。これはcron.hourlyでやっている

/etc/cron.hourly/snapper

#!/bin/sh

#
# paranoia settings
#
umask 022
PATH=/sbin:/bin:/usr/sbin:/usr/bin
export PATH


#
# get information from /etc/default/snapper
#
if [ -f /etc/default/snapper ] ; then
    . /etc/default/snapper
fi


#
# run snapper for all configs
#
for CONFIG in $SNAPPER_CONFIGS ; do

    TIMELINE_CREATE="no"

    . /etc/snapper/configs/$CONFIG

    if [ "$TIMELINE_CREATE" = "yes" ] ; then
        snapper --config=$CONFIG --quiet create --description="timeline" --cleanup-algorithm="timeline"
    fi

done

exit 0

単純な動作であるが、/etc/defaults/snapperで定義したconfigファイルを空白で区切ってループし、/etc/snapper/configの下を評価した後

snapper --config=$CONFIG --quiet create --description="timeline" --cleanup-algorithm="timeline"

というコマンドを実行している。これにより毎時実行されるので、cronのタイミングによってはスナップショットが既に取得されている事があるという事だ。

で、どうなるの?

先述したように、ほったらかしておくと、どんどんsnapshotが作られるぞ…

とりあえずコマンドオプションを見ておこう。

# snapper --help
usage: snapper [グローバルオプション] <コマンド> [コマンドオプション] [コマンド引数]

    グローバルオプション:
        --quiet, -q                     通常出力される項目の省略。
        --verbose, -v                   より詳しい出力を行う。
        --utc                           日付と時刻をUTC形式で表示します。
        --iso                           日付と時刻をISO形式で表示します。
        --table-style, -t <スタイル>    表のスタイル(整数)。
        --config, -c <名前>             使用する設定ファイル名を指定する。
        --no-dbus                       DBusなしで処理を行います。
        --version                       バージョンを印刷して終了する。

  環境設定の一覧表示:
        snapper list-configs

  環境設定の作成:
        snapper create-config <サブボリューム>

    「create-config」コマンドに対するオプション:
        --fstype, -f <種類>             手動でファイルシステムの種類を指定する。
        --template, -t <名前>           使用する設定テンプレートの指定。

  設定の削除:
        snapper delete-config

  設定の取得:
        snapper get-config

  設定:
        snapper set-config <configdata>

  スナップショットの一覧表示:
        snapper list

    「list」コマンドに対するオプション:
        --type, -t <種類>               一覧表示するスナップショットの種類。

  スナップショットの作成:
        snapper create

    「create」コマンドに対するオプション:
        --type, -t <種類>               スナップショットの種類。
        --pre-number <番号>             プリスナップショットの番号を指定。
        --print-number, -p              作成したスナップショットの印刷枚数を表示。
        --description, -d <説明>        スナップショットの説明。
        --cleanup-algorithm, -c <アルゴリズム>          スナップショットに対するクリーンアップアルゴリズムの指定
        --userdata, -u <データ> スナップショットに対するユーザデータの指定
        --command <command>     コマンドを実行し、その前後にスナップショットを採取する

  スナップショットの変更:
        snapper modify <番号>

    「modify」コマンドに対するオプション:
        --description, -d <説明>        スナップショットの説明。
        --cleanup-algorithm, -c <アルゴリズム>          スナップショットに対するクリーンアップアルゴリズムの指定
        --userdata, -u <データ> スナップショットに対するユーザデータの指定

  スナップショットの削除:
        snapper delete <番号>

  スナップショットのマウント:
        snapper mount <番号>

  スナップショットのマウント解除:
        snapper umount <番号>

  スナップショットの比較:
        snapper status <番号 1>..<番号 2>

    'status' コマンドに対するオプション:
        --output, -o <ファイル>         状態をファイルに保存する

  スナップショットの比較:
        snapper diff <番号 1>..<番号 2> [ファイル]

  スナップショットの拡張属性の比較:
        snapper xadiff <number1>..<number2> [files]

  変更の取り消し:
        snapper undochange <番号 1>..<番号 2> [ファイル]

    「undochange」コマンドに対するオプション:
        --input, -i <ファイル>          ファイルから変更内容を取り消すファイルを読み込む。

  ロールバック:
        snapper rollback [番号]

    「rollback」コマンドに対するオプション:
        --print-number, -p              2番目に作成したスナップショットの印刷枚数を表示。
        --description, -d <説明>        スナップショットの説明。
        --cleanup-algorithm, -c <アルゴリズム>  スナップショットに対するクリーンアップアルゴリズムの指定。
        --userdata, -u <データ> スナップショットに対するユーザデータの指定。

  スナップショットのクリーンアップ:
        snapper cleanup <クリーンアップアルゴリズム>

snapshotのリスト

これは当然ながら?snapper listを使えばよさそうだね。

# snapper -c media list
種類   | #  | 前 # | 日付                        | ユーザ | 整理     | 説明     | ユーザデータ
-------+----+------+-----------------------------+--------+----------+----------+-------------
single | 0  |      |                             | root   |          | current  |
single | 1  |      | 2016年10月17日 03時17分03秒 | root   | timeline | timeline |
single | 22 |      | 2016年10月18日 00時17分03秒 | root   | timeline | timeline |
single | 34 |      | 2016年10月18日 12時17分03秒 | root   | timeline | timeline |
single | 35 |      | 2016年10月18日 13時17分03秒 | root   | timeline | timeline |
single | 36 |      | 2016年10月18日 14時17分03秒 | root   | timeline | timeline |
single | 37 |      | 2016年10月18日 15時17分02秒 | root   | timeline | timeline |
single | 38 |      | 2016年10月18日 16時17分04秒 | root   | timeline | timeline |
single | 39 |      | 2016年10月18日 17時17分03秒 | root   | timeline | timeline |
single | 40 |      | 2016年10月18日 18時17分03秒 | root   | timeline | timeline |
single | 41 |      | 2016年10月18日 19時17分03秒 | root   | timeline | timeline |
single | 42 |      | 2016年10月18日 20時17分03秒 | root   | timeline | timeline |
single | 43 |      | 2016年10月18日 21時17分03秒 | root   | timeline | timeline |
single | 44 |      | 2016年10月18日 22時17分04秒 | root   | timeline | timeline |
single | 45 |      | 2016年10月18日 23時17分03秒 | root   | timeline | timeline |
single | 46 |      | 2016年10月19日 00時17分02秒 | root   | timeline | timeline |

このように、もりもりっと取得されている。このインターバルに問題がある場合はチューニングする必要アリ。

なんかやれよ

、、、といったものの、今このディレクトリには何も無いのであった。。 とりあえず、もう一度さっぱりした状態で、やってみよう。

# umount /backup.media 
# mkfs.btrfs -f  /dev/sdg1
Btrfs v3.17
See http://btrfs.wiki.kernel.org for more information.

Turning ON incompat feature 'extref': increased hardlink limit per file to 65536
fs created label (null) on /dev/sdg1
	nodesize 16384 leafsize 16384 sectorsize 4096 size 2.73TiB
# mount /dev/sdg1 /backup.media/
# btrfs subvolume create /backup.media/.snapshots
Create subvolume '/backup.media/.snapshots'

最後のsubvolumeのcreateはsnapperに任せてもいいのかもしれない。

で、何かファイルを作りましょう。わかりやすいように適当なテキストファイルを

# echo "mogemoge" > /backup.media/test.txt

snapperはcronで動くけれど、このcronスクリプトを手で叩けば当然、作ってくださるので、時間を待てないような時(今)みたいな場合は手で叩いてしまう。

# /etc/cron.hourly/snapper

すると、こんな感じ

# snapper -c media list
種類   | # | 前 # | 日付                        | ユーザ | 整理     | 説明     | ユーザデータ
-------+---+------+-----------------------------+--------+----------+----------+-------------
single | 0 |      |                             | root   |          | current  |             
single | 1 |      | 2016年10月19日 12時52分05秒 | root   | timeline | timeline |      

snapshotが取られたので、test.txtをさらに変更する

# echo "hogehoge" >> /backup.media/test.txt
# cat /backup.media/test.txt 
mogemoge
hogehoge

まあ、こんな感じになるだろうから、ここでさらにsnapshotを取る

# /etc/cron.hourly/snapper
# snapper -c media list
種類   | # | 前 # | 日付                        | ユーザ | 整理     | 説明     | ユーザデータ
-------+---+------+-----------------------------+--------+----------+----------+-------------
single | 0 |      |                             | root   |          | current  |             
single | 1 |      | 2016年10月19日 12時52分05秒 | root   | timeline | timeline |             
single | 2 |      | 2016年10月19日 12時55分53秒 | root   | timeline | timeline | 

もう1段階やっておこう。

# echo "fugafuga" >> /backup.media/test.txt
# cat /backup.media/test.txt 
mogemoge
hogehoge
fugafuga
# /etc/cron.hourly/snapper 
# snapper -c media list
種類   | # | 前 # | 日付                        | ユーザ | 整理     | 説明     | ユーザデータ
-------+---+------+-----------------------------+--------+----------+----------+-------------
single | 0 |      |                             | root   |          | current  |             
single | 1 |      | 2016年10月19日 12時52分05秒 | root   | timeline | timeline |             
single | 2 |      | 2016年10月19日 12時55分53秒 | root   | timeline | timeline |             
single | 3 |      | 2016年10月19日 12時57分03秒 | root   | timeline | timeline |

diffを取ったりしてみる

# snapper -c media diff 1..2
--- /backup.media/.snapshots/1/snapshot/test.txt	2016-10-19 12:51:02.943459311 +0900
+++ /backup.media/.snapshots/2/snapshot/test.txt	2016-10-19 12:55:06.367457079 +0900
@@ -1 +1,2 @@
 mogemoge
+hogehoge
# snapper -c media diff 1..3
--- /backup.media/.snapshots/1/snapshot/test.txt	2016-10-19 12:51:02.943459311 +0900
+++ /backup.media/.snapshots/3/snapshot/test.txt	2016-10-19 12:56:36.187456255 +0900
@@ -1 +1,3 @@
 mogemoge
+hogehoge
+fugafuga

変更点だけ追いかける場合は

# snapper -c media status 1..2
c..... /backup.media/test.txt

など。

で、現状3なわけだがこれを1に戻す場合

snapper -v undochange 事前#..事後# ファイル名 (複数可)

というわけだから、

# snapper -v -c media undochange 1..3 
作成:0 修正:1 削除:0
/backup.media/test.txt を修正しています

的な

# cat /backup.media/test.txt 
mogemoge

逆方向にも出来る。

# snapper -v -c media undochange 3..1
作成:0 修正:1 削除:0
/backup.media/test.txt を修正しています
# cat /backup.media/test.txt 
mogemoge
hogehoge
fugafuga

ファイル名を与えてもヨシ。

あとこれ、btrfsのラッパーみたいなものだからbtrfsで何とかしてもいい、というかsnapper自体は実はlvmでもいい

運用

とりあえず/etcでもrsyncするスクリプトでも書いておこう。

/etc/cron.d/backup-media

25 * * * * root rsync -acSHXA --numeric-ids /etc /backup.media/

25分なのは適当なんで適当に変更してください…

これで何となくetckeeper的な使い方もできますね(しかもrsyncしながら)

で、いくら何でもsnapshotが多い過ぎるんじゃないの

放っておくとこのザマである

# snapper -cmedia list
種類   | #  | 前 # | 日付                        | ユーザ | 整理     | 説明     | ユーザデータ
-------+----+------+-----------------------------+--------+----------+----------+-------------
single | 0  |      |                             | root   |          | current  |
single | 1  |      | 2016年10月19日 14時28分28秒 | root   | timeline | timeline |
single | 13 |      | 2016年10月20日 00時17分01秒 | root   | timeline | timeline |
single | 34 |      | 2016年10月20日 21時17分01秒 | root   | timeline | timeline |
single | 35 |      | 2016年10月20日 22時17分02秒 | root   | timeline | timeline |
single | 36 |      | 2016年10月20日 23時17分01秒 | root   | timeline | timeline |
single | 37 |      | 2016年10月21日 00時17分01秒 | root   | timeline | timeline |
single | 38 |      | 2016年10月21日 01時17分01秒 | root   | timeline | timeline |
single | 39 |      | 2016年10月21日 02時17分01秒 | root   | timeline | timeline |
single | 40 |      | 2016年10月21日 03時17分01秒 | root   | timeline | timeline |
single | 41 |      | 2016年10月21日 04時17分01秒 | root   | timeline | timeline |
single | 42 |      | 2016年10月21日 05時17分01秒 | root   | timeline | timeline |
single | 43 |      | 2016年10月21日 06時17分01秒 | root   | timeline | timeline |
single | 44 |      | 2016年10月21日 07時17分01秒 | root   | timeline | timeline |
single | 45 |      | 2016年10月21日 08時17分01秒 | root   | timeline | timeline |
single | 46 |      | 2016年10月21日 09時17分01秒 | root   | timeline | timeline |
single | 47 |      | 2016年10月21日 10時17分01秒 | root   | timeline | timeline |
single | 48 |      | 2016年10月21日 11時17分01秒 | root   | timeline | timeline |
single | 49 |      | 2016年10月21日 12時17分01秒 | root   | timeline | timeline |
single | 50 |      | 2016年10月21日 13時17分01秒 | root   | timeline | timeline |
single | 51 |      | 2016年10月21日 14時17分01秒 | root   | timeline | timeline |
single | 52 |      | 2016年10月21日 15時17分01秒 | root   | timeline | timeline |
single | 53 |      | 2016年10月21日 16時17分01秒 | root   | timeline | timeline |
single | 54 |      | 2016年10月21日 17時17分01秒 | root   | timeline | timeline |
single | 55 |      | 2016年10月21日 18時17分01秒 | root   | timeline | timeline |
single | 56 |      | 2016年10月21日 19時17分01秒 | root   | timeline | timeline |
single | 57 |      | 2016年10月21日 20時17分01秒 | root   | timeline | timeline |
single | 58 |      | 2016年10月21日 21時17分01秒 | root   | timeline | timeline |
single | 59 |      | 2016年10月21日 22時17分01秒 | root   | timeline | timeline |
single | 60 |      | 2016年10月21日 23時17分01秒 | root   | timeline | timeline |
single | 61 |      | 2016年10月22日 00時17分01秒 | root   | timeline | timeline |
single | 62 |      | 2016年10月22日 01時17分01秒 | root   | timeline | timeline |
single | 63 |      | 2016年10月22日 02時17分01秒 | root   | timeline | timeline |

これは、まあ、「あ、やばい」と思った時にすぐ1時間前に戻れるのがいいが、たとえば、デカいファイルをコピーしたりする時などには全然向いていない、というか、rsyncするならrsyncごとでもいいようにも思うがフックをかけるのが面倒だというのもあるかもしれんので、まあ。。いろいろ。

個人的にはcron.hourly/は使っていません

snapper.txt · 最終更新: 2016/10/22 15:30 by admin
www.chimeric.de Creative Commons License Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0