間違えてファイルの上書きをしてしまったりして、バックアップを取得していないとかなり大変な事になる。
そんなときでも、ファイルシステムでバージョン管理ができれば過去のバージョンのファイルをスグに取り出す事ができる。

今回は、そんなバージョン管理が出来るファイルシステム『NILFS』を利用し、ファイルのバージョン管理をしてみようとおもう。

『NILFS』は数秒、または同期書き込みのタイミングで変更のあった場合、その時点でのチェックポイントを生成してくれる。管理者は、そのチェックポイントの中から重要なバージョンを戻したり、スナップショットとして変換できる。このスナップショットはSambaでWindowsのShadow Copy機能で利用できるので、バージョン管理ファイルサーバーを簡単に構築することもできる。

なお、今回の検証はCentOS 7で行う。

1.インストール

DebianやUbuntu、Fedoraなど大半のディストリビューションで最初から利用できるのだが、CentOSにおいては、パッケージを別途インストールする必要がある。
CentOS 7用のパッケージをこちらのページからダウンロードし、インストールする。

wget http://nilfs.sourceforge.net/pub/centos/7/RPMS/x86_64/kmod-nilfs2-0.1-1.el7.x86_64.rpm
wget http://nilfs.sourceforge.net/pub/centos/7/RPMS/x86_64/nilfs-utils-2.2.3-1.el7.x86_64.rpm
rpm -ihv kmod-nilfs2-0.1-1.el7.x86_64.rpm
rpm -ihv nilfs-utils-2.2.3-1.el7.x86_64.rpm

これで、NILFSが利用出来るようになった。

2.ディスクのフォーマット&マウント

さて、NILFSはファイルシステムなので、当然そのパーティションのファイルシステムをNILFSにして利用する必要がある。
今回は、空のHDDを「/dev/sdb」として追加しフォーマット、新規のパーティションをNILFSで作成、「/work」にマウントする。

まずは、fdiskで/dev/sdb2をフォーマットする。

fdisk /dev/sdb
[root@dctest01 ~]# fdisk /dev/sdb
Welcome to fdisk (util-linux 2.23.2).

Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.

Device does not contain a recognized partition table
Building a new DOS disklabel with disk identifier 0xe56b95b5.

コマンド (m でヘルプ): n
Partition type:
   p   primary (0 primary, 0 extended, 4 free)
   e   extended
Select (default p): p
パーティション番号 (1-4, default 1): 1
最初 sector (2048-33554431, 初期値 2048): 2048
Last sector, +sectors or +size{K,M,G} (2048-33554431, 初期値 33554431): 33554431
Partition 1 of type Linux and of size 16 GiB is set

コマンド (m でヘルプ): q

次に、ファイルシステムを「nilfs2」に指定してパーティションを作成する。

mkfs -t nilfs2 /dev/sdb
[root@dctest01 ~]# mkfs -t nilfs2 /dev/sdb
mkfs.nilfs2 (nilfs-utils 2.2.3)
Start writing file system initial data to the device
       Blocksize:4096  Device:/dev/sdb  Device Size:17179869184
File system initialization succeeded !!

さて、ここまで終わったら「/work」にマウントする。

mount -t nilfs2 /dev/sdb /work

なお、この時に以下のようなエラーが表示された場合は、利用しているLinuxカーネルのバージョンと「kmod-nilfs2-0.1-1.el7.x86_64.rpm」のカーネルのバージョンが異なるため、モジュールが読み込まれていない事が原因である可能性が高い。この場合は、支障ないようであればカーネルのバージョンをダウングレードしてしまうと良いだろう。

[root@test-centos7 ~]# mount -t nilfs2 /dev/sdb /work
mount.nilfs2: cannot find or load niflfs2 filesystem

3.バージョン管理を行ってみる

さて、それでは実際にバージョン管理を行ってみよう。
NILFSでは、チェックポイントの確認に「lscp」コマンドを用いている。実際に「/work」フォルダ配下にファイルを作成し、チェックポイントが作成されることを確認してみよう。

[root@dctest01 ~]# df -h /dev/sdb
ファイルシス   サイズ  使用  残り 使用% マウント位置
/dev/sdb          16G   16M   16G    1% /work
[root@dctest01 ~]# lscp
                 CNO        DATE     TIME  MODE  FLG      BLKCNT       ICNT
                   1  2015-05-12 06:14:09   cp    -            4          2
[root@dctest01 ~]# touch /work/test
[root@dctest01 ~]# lscp
                 CNO        DATE     TIME  MODE  FLG      BLKCNT       ICNT
                   1  2015-05-12 06:14:09   cp    -            4          2
                   2  2015-05-12 20:42:18   cp    -            4          3
[root@dctest01 ~]# cat /work/test
[root@dctest01 ~]# echo test > /work/test
[root@dctest01 ~]# cat /work/test
test
[root@dctest01 ~]# lscp
                 CNO        DATE     TIME  MODE  FLG      BLKCNT       ICNT
                   1  2015-05-12 06:14:09   cp    -            4          2
                   2  2015-05-12 20:42:18   cp    -            4          3
                   3  2015-05-12 20:43:28   cp    -            5          3

確かに、ファイルシステムに変更が行われるごと(厳密には、その数秒後)にチェックポイントが作成されていく。

さて、実は大変なのはこのチェックポイントからファイルをリカバリする方法。このチェックポイント(cp)を一度スナップショット(ss)に切り替え、ファイルシステムを別のマウントポイントでマウントし、そこからファイルを取り出す事でリカバリすることになる。
チェックポイントをスナップショットに切り替える場合は、chcpコマンドを利用する。
例えば、CNO2をスナップショットにする場合は以下のようにコマンドを実行する。

chcp ss 2
[root@dctest01 ~]# lscp
                 CNO        DATE     TIME  MODE  FLG      BLKCNT       ICNT
                   1  2015-05-12 06:14:09   cp    -            4          2
                   2  2015-05-12 20:42:18   cp    -            4          3
                   3  2015-05-12 20:43:28   cp    -            5          3
[root@dctest01 ~]# chcp ss 2
[root@dctest01 ~]# lscp
                 CNO        DATE     TIME  MODE  FLG      BLKCNT       ICNT
                   1  2015-05-12 06:14:09   cp    -            4          2
                   2  2015-05-12 20:42:18   ss    -            4          3
                   3  2015-05-12 20:43:28   cp    -            5          3
[root@dctest01 ~]#

CNO 2のMODEがssに切り替わっている事が確認出来る。
後は、以下のように/dev/sdbをマウントさせる。

mount -t nilfs2 -r -o cp=2 /dev/sdb /リストア用のマウントポイント
[root@dctest01 ~]# mkdir /work_restore
[root@dctest01 ~]# mount -t nilfs2 -r -o cp=2 /dev/sdb /work_restore
[root@dctest01 ~]# ls -la /work_restore/
合計 5
drwxr-xr-x.  2 root root 4096  5月 12 20:42 .
drwxr-xr-x. 22 root root 4096  5月 12 20:53 ..
-rw-r--r--.  1 root root    0  5月 12 06:14 .nilfs
-rw-r--r--.  1 root root    0  5月 12 20:42 test
[root@dctest01 ~]# cat /work_restore/test
[root@dctest01 ~]# cat /work/test
test
[root@dctest01 ~]#

うーん…確かにリストアは出来るんだけど…結構手間が掛かるというか、わざわざマウントするなんて大掛かりすぎるというか…この方法だと、一般ユーザでのリカバリは難しいような…「利用するユーザ=root」な環境だったら使えると思う。
ちょっと修正を戻したいな、という時にこんな手順を踏むってのは、ちょっと面倒だなぁ…複数のファイル(それぞれで更新したタイミングは違う)をリカバリしたい場合だと、やはりそのタイミングごとにマウントし直す必要があるようだし…

あくまでも保険の意味合いが強いかも。