絵描きのzfs snapshot活用術
あっ、線画レイヤーに色塗ってる!
突然ですが、私、趣味で絵を描きます(NSFWです)
絵描きあるあるが「線画レイヤーに色を直接塗ってしまっており、それに気づくことなく作業をガンガン進めてしまい、気づいたら手遅れなところまで進んでしまっている」という事故です。ご丁寧に保存しちゃってたりするともはや後には戻れません。なんとか、お絵かきソフトを駆使して線画と中の色塗りの部分を分離するみたいなことをするしかないです。とてもとても面倒くさいです。
なので考えました。せっかくzfsのNASを組んだのだから、zfs snapshotで一時間ごとに絵のファイルが保存されてる作業フォルダのスナップショットを取っておけばよいのでは?と。そしたら、ミスに気づいた時点で過去のスナップショットをさかのぼって、そこから色が塗られちゃう前の古い作業データの線画レイヤだけ取り出して現作業ファイルにコピペすればらくらく回復できます。
というわけで、さっそくやってみました。
まず、定期zfs snapshot。cronとかつかって自分でやってもいいですが面倒ですよね。ここはsanoidっていうツールがあるのでこれを使います。
Pythonで書かれてるっぽいです。まあ、Debianだったらapt-getでインストールできますので楽ちん。
$ sudo apt install sanoid
んで、次に設定ファイル。/etc/sanoid/sanoid.conf
に設定ファイルあるので、emacsだかviだかで編集します。私はこんな感じにしました。
[tank/working] use_template = template_daily [template_daily] hourly = 24 daily = 7 monthly = 0 yearly = 0 autosnap = yes autoprune = yes
tank/working
というzfsがイラストのファイルが入ってる領域です。これをsambaで外部に公開して、Windowsからマウントして使ってる感じです。
hourly = 24
で一日に一時間に一回snapshotを取り、daily = 7
で一日一個。保存する感じにしてます。多分これであってる。。。sanoid.conf
を編集したら、sanoidを再起動しときます。
$ sudo systemctl restart sanoid
これで、定期的にsnapshotが取れます。
root@liella:/home/takahashi# zfs list -t snapshot NAME USED AVAIL REFER MOUNTPOINT tank/working@autosnap_2022-03-13_00:22:35_monthly 0B - 4.81G - tank/working@autosnap_2022-03-13_00:22:35_daily 0B - 4.81G - tank/working@autosnap_2022-03-13_00:22:35_hourly 0B - 4.81G - tank/working@autosnap_2022-03-13_01:00:01_hourly 0B - 4.81G - tank/working@autosnap_2022-03-13_02:00:24_hourly 0B - 4.81G - tank/working@autosnap_2022-03-13_03:00:24_hourly 0B - 4.81G - tank/working@autosnap_2022-03-13_04:00:24_hourly 0B - 4.81G - tank/working@autosnap_2022-03-13_05:00:24_hourly 0B - 4.81G - tank/working@autosnap_2022-03-13_06:00:24_hourly 0B - 4.81G - tank/working@autosnap_2022-03-13_07:00:24_hourly 0B - 4.81G - tank/working@autosnap_2022-03-13_08:00:01_hourly 0B - 4.81G - tank/working@autosnap_2022-03-13_09:00:01_hourly 0B - 4.81G - tank/working@autosnap_2022-03-13_10:00:01_hourly 0B - 4.81G - tank/working@autosnap_2022-03-13_11:00:24_hourly 0B - 4.81G - tank/working@autosnap_2022-03-13_12:00:24_hourly 0B - 4.81G -
この設定で一時間に一枚snapshot取れてます。
特定の場所だけsnapshot取りたい!
余談ですが、zfsでスナップショットを取る場合は、zfsのファイルシステム(か、zvol)単位になります。つまりzfs内部にある特定のディレクトリだけsnapshotを取る!みたいなことはできないわけです。
root@liella:/home/takahashi# zfs list NAME USED AVAIL REFER MOUNTPOINT tank 1.65T 12.8T 1.64T /tank
例えば、こんなzfsがあったとしましょう。ここで、/tank
ディレクトリの下にoekaki
みたいなディレクトリを作り、このoekaki
ディレクトリ内部だけのsnapshotを取りたい!みたいなことはできないんですね。上の例だとtank
全体でしかsnapshotがとれません。
tank
の下にoekaki
とは別のディレクトリもたくさんあって、そこにデータもたくさんある場合はそこもまとめてスナップショットされてしまいます。すると、スナップショットの容量が大きくなってzfs poolの容量を圧迫します。
スナップショット領域は最も重要なファイルがあるディレクトリだけに限定したいですね。
とはいえ、スナップショット対象領域を別にした構成に新たに作り直すのも面倒です。後付で特定のディレクトリだけ、例えば/tank/samba/public/working
の場所だけsnapshot取りたい場合は一工夫すれば一応それっぽいことが可能です。
まず、tank
の下に新しいzfsを後付します。
root@liella:/home/takahashi# zfs create tank/working root@liella:/home/takahashi# zfs list NAME USED AVAIL REFER MOUNTPOINT tank 1.65T 12.8T 1.64T /tank tank/working 4.81G 12.8T 4.81G /tank/working
これで、tank/working
という新しいzfsが作れました。あとはMOUNTPOINTを変更します。
root@liella:/home/takahashi# zfs set mountpoint=/tank/samba/public/working tank/working root@liella:/home/takahashi# zfs list NAME USED AVAIL REFER MOUNTPOINT tank 1.65T 12.8T 1.64T /tank tank/working 4.81G 12.8T 4.81G /tank/samba/public/working
これで、tank/working
のスナップショットをとれば/tank/samba/public/working
サブディレクトリの中身のみスナップショットを取るみたいなことが事実上できます。あとはtank/working
をマウントすればいいです。
root@liella:/home/takahashi# zfs mount tank/working root@liella:/home/takahashi# df -h Filesystem Size Used Avail Use% Mounted on tank 15T 1.7T 13T 12% /tank tank/working 13T 4.9G 13T 1% /tank/samba/public/working
こんな感じで。もちろん、もともと/tank/samba/public/working
に存在していたファイルはmount時点で見えなくなってしまうので(消えるわけではなくて見えなくなるだけです。mount解除すればまた見えるようになります)もともとあったファイルはどこかに退避しといた上でzfs mount
後に移動し直せばいいです。
もともとあったファイルの移動のひと手間がありますが、zfsを作り直すよりは楽だと思いますので、特定ディレクトリだけスナップショット取りたい場合はこのやり方はおすすめです。
さて、/tank/samba/public/working
のスナップショットを取ったとして、スナップショットもWindowsから楽に参照できればいいですよね?というわけで、このスナップショットをマウントしてSambaで公開します。
まず、スナップショットのマウントから。
root@liella:/home/takahashi# zfs list NAME USED AVAIL REFER MOUNTPOINT tank 1.65T 12.8T 1.64T /tank tank/working 4.81G 12.8T 4.81G /tank/samba/public/working root@liella:/home/takahashi# zfs set snapdir=visible tank/working
さて、zfs set snapdir=visible tank/working
を実行したあとで/tank/samba/public/working
の中身を見てみると。。。
root@liella:/tank/samba/public/working# ls -ahlF total 1.7G drwxrwxrwx 9 101000 101000 10 Mar 13 09:18 ./ drwxrwxr-x 9 101000 101000 13 Mar 13 16:46 ../ drwxr-xr-x 2 101000 101000 55 Mar 13 09:18 0.下描き/ drwxr-xr-x 2 101000 101000 16 Mar 13 09:18 1.ペン入れ/ drwxr-xr-x 2 101000 101000 6 Mar 13 09:21 2.彩色/ drwxr-xr-x 3 101000 101000 10 Mar 13 09:18 3.QA_Review/ drwxr-xr-x 3 101000 101000 42 Mar 13 09:21 4.Done/ drwxr-xr-x 2 101000 101000 19 Mar 13 09:18 done_drawing/ -rw-r--r-- 1 101000 101000 70M Mar 13 01:16 knowhow.pur -rw-r--r-- 1 101000 101000 1.6G Mar 9 22:03 myboard.pur drwxrwxrwx 1 root root 0 Mar 13 17:26 .zfs/
.zfs
という隠しディレクトリができてることがわかります。この中身を見てみると。。。
root@liella:/tank/samba/public/working# cd .zfs/ root@liella:/tank/samba/public/working/.zfs# ls -ahlF total 17K drwxrwxrwx 1 root root 0 Mar 13 17:26 ./ drwxrwxrwx 9 101000 101000 10 Mar 13 09:18 ../ drwxrwxrwx 2 root root 2 Mar 13 17:26 shares/ drwxrwxrwx 2 root root 2 Mar 13 22:00 snapshot/ root@liella:/tank/samba/public/working/.zfs# cd snapshot/ root@liella:/tank/samba/public/working/.zfs/snapshot# ls -ahlF total 264K drwxrwxrwx 2 root root 2 Mar 13 22:00 ./ drwxrwxrwx 1 root root 0 Mar 13 17:26 ../ drwxrwxrwx 8 root root 10 Mar 13 09:18 autosnap_2022-03-13_00:22:35_daily/ drwxrwxrwx 8 root root 10 Mar 13 09:18 autosnap_2022-03-13_00:22:35_hourly/ drwxrwxrwx 8 root root 10 Mar 13 09:18 autosnap_2022-03-13_00:22:35_monthly/ drwxrwxrwx 8 root root 10 Mar 13 09:18 autosnap_2022-03-13_01:00:01_hourly/ drwxrwxrwx 8 root root 10 Mar 13 09:18 autosnap_2022-03-13_02:00:24_hourly/ drwxrwxrwx 8 root root 10 Mar 13 09:18 autosnap_2022-03-13_03:00:24_hourly/ drwxrwxrwx 8 root root 10 Mar 13 09:18 autosnap_2022-03-13_04:00:24_hourly/ drwxrwxrwx 8 root root 10 Mar 13 09:18 autosnap_2022-03-13_05:00:24_hourly/ drwxrwxrwx 8 root root 10 Mar 13 09:18 autosnap_2022-03-13_06:00:24_hourly/ drwxrwxrwx 8 root root 10 Mar 13 09:18 autosnap_2022-03-13_07:00:24_hourly/ drwxrwxrwx 8 root root 10 Mar 13 09:18 autosnap_2022-03-13_08:00:01_hourly/ drwxrwxrwx 8 101000 101000 10 Mar 13 09:18 autosnap_2022-03-13_09:00:01_hourly/ drwxrwxrwx 8 101000 101000 10 Mar 13 09:18 autosnap_2022-03-13_10:00:01_hourly/ drwxrwxrwx 8 101000 101000 10 Mar 13 09:18 autosnap_2022-03-13_11:00:24_hourly/ drwxrwxrwx 8 101000 101000 10 Mar 13 09:18 autosnap_2022-03-13_12:00:24_hourly/ drwxrwxrwx 8 101000 101000 10 Mar 13 09:18 autosnap_2022-03-13_13:00:01_hourly/
はい、このように、snapshotが見えます。
なので、この.zfs領域をSambaで公開してそれをWindowsから見ればOKです。こんな感じで見れます。
ここで問題発生
ここで問題発生。なんかスナップショットのファイル名が妙ちくりんな名前になってます。これは、Windowsがファイル名に:
を使えないことに起因します。sanoidが取るスナップショット名に:
が入っちゃってるので、Sambaが変換をかけてこうなっちゃうんですね。
sanoidのほうでsnapshotの名前を:
を使わないなにか別のフォーマットに変えられないのか?と思ったんですが、これは無理です。sanoidにその機能はないとのこと。
なのでsamba側でなんとかする
なので、samba側でなんとかします。sambaにはwindowsでは表示できない記号がファイル名に使われてた場合、それを置き換える機能vfs objects = catia
というものがあって、それを使います。
[snapshot] comment = zfs snapshots vfs objects = catia mangled names = no catia:mappings = 0x22:0xa8,0x2a:0xa4,0x2f:0xf8,0x3a:0xf7,0x3c:0xab,0x3e:0xbb,0x3f:0xbf,0x5c:0xff,0x7c:0xa6 path = /samba/public/working/.zfs writable = no guest ok = no
この0x22:0xa8,0x2a:0xa4,0x2f:0xf8,0x3a:0xf7,0x3c:0xab,0x3e:0xbb,0x3f:0xbf,0x5c:0xff,0x7c:0xa6
ってのが変換テーブルなわけですが、これの内訳はこういう意味です。
0x22:0xa8 = ダブルクオーテーション (") -> ウムラウト(¨) 0x2a:0xa4 = アスタリスク(*) -> 汎用通貨記号(¤) 0x2f:0xf8 = スラッシュ(/) ->スラッシュ付きオー(⊘) 0x3a:0xf7 = コロン(:) ->除算記号(÷) 0x3c:0xab = 山括弧左(<) ->二重山括弧左(《) 0x3e:0xbb = 山括弧右(>) ->二重山括弧右(》) 0x3f:0xbf = クエスチョンマーク(?) ->逆さクエスチョン(¿) 0x5c:0xff = Yenマーク(\) ->Yの分音記号(ÿ) 0x7c:0xa6 = 垂直線(|) ->分割垂直線(¦)
この設定で。いい感じに表示できます。
2つ注意点。
この変換テーブルをいじらないほうがいいです。例えば、÷(除算記号)はいやだから_
(アンダーバー)に変換したい!と思ってもいじっちゃダメです。理由はあらゆるファイルの_
がすべて:に変換されてしまうので、_
を含むファイルやディレクトリをみようとした瞬間全体がおかしくなります。_
はファイルパスとしてわりかし普通に使うので変換先として使うのはやめましょう。また、このvfs objects = catia
をsambaの[global]
セクションに入れるのもやめましょう。理由はsnapshot以外のすべての領域において万が一除算記号(÷)といった記号がファイル名に使われてしまうと、上述した理由でこれまたSamba全体がおかしくなるからです。snapshotの部分は除算記号(÷)などがパスに使われることはないと保証できますので(sanoidはそんな記号使わないから)snapshot領域のみにvfs objects = catia
を適用しましょう。
はい、これで一時間おきに自動的にスナップショットがとられていつでも過去のデータを参照することができるようになります!
これでHappyお絵かきライフが捗るんじゃぁ~
次はバックアップだねぇ。。。