Though I, of course, use version control for any kind of serious development, and configuration management to build my hosts, I still find ZFS snapshots invaluable. I have a script I wrote well over ten years ago which snapshots every dataset on my machine, and I often find myself digging something out of a snapshot.
To make this easier, I wrote
zr
, and I’ve
found it so useful that I thought I’d share it. Let’s have a quick
demo.
zr
Restores Files
Say you accidentally delete Slaapkamers met Slagroom. I know. Nightmare, right?
$ ls -1
01.sonic_youth.slaapkamers_met_slagroom.flac
02.sonic_youth.stil.flac
03.sonic_youth.herinneringen.flac
$ rm 01.sonic_youth.slaapkamers_met_slagroom.flac
$ ls -1
02.sonic_youth.stil.flac
03.sonic_youth.herinneringen.flac
$ zr 01.sonic_youth.slaapkamers_met_slagroom.flac
current file unknown mtime unknown size
------------------------------------------------------------------------------
0 sunday 2018-06-06 08:17:14 +0000 130711565
1 april 2018-06-06 08:17:14 +0000 130711565
2 friday 2018-06-06 08:17:14 +0000 130711565
3 march 2018-06-06 08:17:14 +0000 130711565
4 tuesday 2018-06-06 08:17:14 +0000 130711565
5 thursday 2018-06-06 08:17:14 +0000 130711565
6 monday 2018-06-06 08:17:14 +0000 130711565
7 wednesday 2018-06-06 08:17:14 +0000 130711565
8 saturday 2018-06-06 08:17:14 +0000 130711565
choose file to promote [add 'd' for diff, 'k' to keep] > 0
promoting /storage/flac/.zfs/snapshot/sunday/eps/sonic_youth.slaapkamers_met_slagroom/\
01.sonic_youth.slaapkamers_met_slagroom.flac
$ ls -1
01.sonic_youth.slaapkamers_met_slagroom.flac
02.sonic_youth.stil.flac
03.sonic_youth.herinneringen.flac
As you can see, when it’s given a filename, zr
offers you a list
of files of the same name in any snapshots of the file’s parent
dataset. I’m not normally a big fan of coloured output from
commands, but here I find it useful. Blue files are different from
the “real” one. In this case, they’re all blue because the real one
doesn’t exist any more.
All you do is enter the number of the file you want to recover, and
zr
will pop it back where it was, replacing or overwriting the
“real” one.
If you’ve deleted a file and just want the newest snapshotted
version back, you can run zr -a <filename>
and zr
will
automatically recover it for you.
If the real file still exists, zr
will show you the modification
time and byte size of what it calls the “current file”, then a list
of all the similarly named files it finds in snapshots. Any
versions of the file which look the same as the live one are
struck through, to suggest you ignore them. (I chose not to
simply omit identical files because that would suggest there aren’t
any snapshotted versions, which would confuse the user.)
zr
considers files identical if they have the
same modification time and size. I originally wrote it when I was
trying various transcoding methods on a bunch of massive Bluray
rips, which were very time-consuming to SHA sum.
$ zr inspector.d
current file 2019-02-12 16:39:47 +0000 723
------------------------------------------------------------------------------
0 thursday 2019-02-12 16:39:47 +0000 723
1 tuesday 2019-02-12 16:39:47 +0000 723
2 monday 2019-02-12 16:39:47 +0000 723
3 saturday 2019-02-12 16:39:47 +0000 723
4 april 2019-02-12 16:39:47 +0000 723
5 march 2019-02-12 16:39:47 +0000 723
6 wednesday 2019-02-12 16:39:47 +0000 723
7 friday 2019-02-12 16:39:47 +0000 723
8 sunday 2019-02-12 16:39:47 +0000 723
9 february 2019-01-22 16:31:33 +0000 665
If you want to see how a snapshot file differs from the live one,
append d
to its number, and the two copies will be run through
diff(1)
.
You can promote a file from a snapshot without getting rid of the
existing one. Append k
to the number, and the original will have
.orig
appended to its name.
zr
can accept multiple arguments, and will loop through the files,
showing you the restoration candidates for each one. It can recover
plain files or entire directories.
zp
Promotes Files
Complementary to zr
, is zp
. This is useful if you are digging
around in your .zfs/snapshot
directories for something. When you
find the thing you want, zp
it back to life.
$ ls /storage/flac/eps/quickspace.superplus
ls: cannot access '/storage/flac/eps/quickspace.superplus': No such file or directory
$ pwd
/storage/flac/.zfs/snapshot/monday/eps
$ ls -d quickspace.superplus
quickspace.superplus
$ zp quickspace.superplus
restoring quickspace.superplus to /storage/flac/eps
$ ls /storage/flac/eps/quickspace.superplus
01.quickspace.superplus.flac 03.quickspace.scubaplus.flac front.jpg
02.quickspace.proplus.flac 04.quickspace.standard_8.flac
zp
only works in a snapshot directory.
$ pwd
/storage/flac/eps
$ zp broadcast.microtronics_volume_01
ERROR: /storage/flac/eps is not a snapshot. Skipping.
zr
and zp
are written in Ruby. They don’t need anything beyond
stdlib, and work with 2.3 upwards.
Other Friends
zr
and zp
live in a pretty ancient Github
repo with some shell scripts I
wrote in the mid-late 2000s. They all work great – I’ve been using
them for over a decade – but please don’t judge me on them!