是否有像 diff -r 这样的工具可以使用哈希值将目录树与清单文件进行比较?

是否有像 diff -r 这样的工具可以使用哈希值将目录树与清单文件进行比较?

我的情况如下。我有两个冷存储存档卷,它们(应该)包含相同的数据集。这些卷包含不经常访问的备份。我担心,最终,bitrot 会进入其中一个或两个卷,并巧妙地破坏其中包含的数据。我知道我可以查看diff -r这两个卷并找到两者之间已更改或消失的文件,但我无法得到有关哪个卷具有“良好”副本的有用提示。这些是 USB 磁盘,将它们转换为类似 ZFS 的东西似乎……很麻烦。

我想要的是一个可以递归遍历目录树并编写清单文件的工具,其中包含路径和文件名以及文件内容的哈希值。我会在将数据写入每个卷后立即运行此工具,并将生成的清单文件存储在温存储中,可能在某种修订控制下。

我希望能够从这个文件中运行与此完全相同的程序diff -r- 它会告诉我文件是否被添加、删除或内容是否发生变化。只不过它不是将一个卷与另一个卷进行比较,而是将一个卷与已知良好的清单文件进行比较。使用这种方法,我应该能够判断几个月/几年后我从磁盘上读取的数据是否与我最初放入的数据相同。

我认为类似的东西已经存在了。我可以使用以下命令获得近似清单文件的内容:

find /mnt/my-volume -type f -exec md5sum {} + > manifest.txt

但到目前为止,我还没有想出一个好的方法来解析这个文件并递归检查每个哈希值。此外,不太重要的是,这不会告诉我空目录是否出现或消失。(我想不出这有什么关系,但如果知道它发生了就好了。)

我这样做对吗,或者是否有更合适的工具可以做这种事情?

答案1

你说得对,这样的工具确实已经存在。虽然我看到你的帖子被标记为“linux”,但也许一个面向 BSD 的解决方案会有所帮助。

FreeBSD 的 mtree(8) 实用程序可以完全按照您的要求进行操作。

认为:

$ find .
.
./c
./c/file3
./b
./b/file2
./a
./a/file1

要创建该文件层次结构的清单(包括每个文件的 sha256 哈希值),可以执行以下操作:

$ mtree -c -K sha256 > /tmp/manifest.txt
$ cat /tmp/manifest.txt
#          user: diego
#       machine: myhost.example.com
#          tree: /data/home/diego/foo
#          date: Wed Mar 28 10:31:17 2018

# .
/set type=file uid=1001 gid=1001 mode=0710 nlink=1 flags=uarch
.               type=dir nlink=5 time=1522257963.738221000

# ./a
/set type=file uid=1001 gid=1001 mode=0600 nlink=1 flags=uarch
a               type=dir mode=0710 nlink=2 time=1522257932.680802000
    file1       size=29 time=1522257932.682389000 \
                sha256digest=6b4114c4f12e63c0ca44073de5ca0a2b39fedaceaa533af3dfdc89f00039c973
# ./a
..


# ./b
b               type=dir mode=0710 nlink=2 time=1522257937.929131000
    file2       size=29 time=1522257937.930666000 \
                sha256digest=9f7a0a49475bb6f98e609a4e057f0bc702c5e4706be5bd656a676fd8d15da7ef
# ./b
..


# ./c
c               type=dir mode=0710 nlink=2 time=1522257942.064315000
    file3       size=29 time=1522257942.065882000 \
                sha256digest=bd617f47217ef0605d3aff036778d10bf18cb2f415c45e8e362e2c091df19491
# ./c
..

然后可以通过将清单导入 mtree 来验证清单中的文件层次结构:

$ mtree < /tmp/manifest.txt || echo fail

添加,删除,重命名或修改文件将导致验证失败:

$ touch foo
$ mtree < /tmp/manifest.txt || echo fail
.:      modification time (Wed Mar 28 10:34:56 2018, Wed Mar 28 10:37:01 2018)
extra: foo
fail
$ rm foo; touch b/file2; mtree < /tmp/manifest.txt || echo fail
.:      modification time (Wed Mar 28 10:34:56 2018, Wed Mar 28 10:39:39 2018)
b/file2: 
        modification time (Wed Mar 28 10:25:37 2018, Wed Mar 28 10:39:39 2018)
fail
$ mv c/file3 c/FILE3; rm a/file1; date >> b/file2; mtree < /tmp/manifest.txt || echo fail
.:      modification time (Wed Mar 28 10:34:56 2018, Wed Mar 28 10:39:39 2018)
c:      modification time (Wed Mar 28 10:25:42 2018, Wed Mar 28 10:41:59 2018)
extra: c/FILE3
b/file2:
        size (29, 58)
        modification time (Wed Mar 28 10:25:37 2018, Wed Mar 28 10:47:31 2018)
        sha256digest (0x9f7a0a49475bb6f98e609a4e057f0bc702c5e4706be5bd656a676fd8d15da7ef, 0x569c17bd1a1ca2447fd8167f103531bf3a7b7b4268f0f68b18506e586e7eea94)
a:      modification time (Wed Mar 28 10:25:32 2018, Wed Mar 28 10:41:59 2018)
./a/file1 missing
./c/file3 missing
fail

答案2

md5sum -c manifest.txt遵守存储在中的路径manifest.txtfind程序将替换{}找到的文件的完整路径,包括在find命令行中指定的任何搜索位置,即对于文件,./a/b/c/d/e它将替换./a/b/c/d/e命令 find ./a -type f -exec md5sum {} \;

可能的问题是绝对路径,因此更合适的“清单创建命令”是:

cd /mnt/my-volume; find  -type f -exec md5sum {} + > manifest.txt

sed但是,你总是可以使用mainfest.txt 内部的路径进行修复

相关内容