ハッシュを使用してディレクトリ ツリーとマニフェスト ファイルを比較する diff -r のようなツールはありますか?

ハッシュを使用してディレクトリ ツリーとマニフェスト ファイルを比較する diff -r のようなツールはありますか?

私の状況は次のとおりです。コールド ストレージ アーカイブ ボリュームが 2 つあり、それらには (おそらく) 同一のデータ セットが含まれています。これらのボリュームには、あまりアクセスされないバックアップが含まれています。いずれは、ビット ロットがボリュームの 1 つまたは両方に侵入し、その中に含まれるデータが微妙に破損するのではないかと心配しています。2 つdiff -rのボリュームを調べて、2 つのボリューム間で変更または消失したファイルを見つけることはできますが、どちらのボリュームに「正常な」コピーがあるかを示す役立つ情報が得られません。これらは USB ディスクであり、ZFS のようなものに変換するのは... 面倒なようです。

私が欲しいのは、ディレクトリ ツリーを再帰的に調べて、パスとファイル名、およびファイルの内容のハッシュを含むマニフェスト ファイルを書き込むツールです。各ボリュームにデータを書き込んだ直後にこのツールを実行し、結果のマニフェスト ファイルをウォーム ストレージ (おそらく何らかのリビジョン管理下) に保存します。

このファイルから、まったく同じように動作する何かを実行できるようにしたいと思いますdiff -r。つまり、ファイルが追加、削除されたか、またはその内容が変更されたかどうかを通知してくれるものです。ただし、1 つのボリュームを他のボリュームと比較するのではなく、1 つのボリュームを既知の正常なマニフェスト ファイルと比較します。この方法を使用すると、数か月/数年後にディスクから読み取るデータが、最初にディスクに保存したデータと同一であるかどうかを判断できるはずです。

このようなものは既に存在していると思います。マニフェスト ファイルに近いものを取得するには、次の操作を実行します。

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.txtプログラムfindは、コマンドライン{}で指定された検索場所を含む、見つかったファイルへの完全なパスを置き換えますfind。つまり、ファイルの場合は、コマンドと ./a/b/c/d/e同じものを置き換えます。./a/b/c/d/efind ./a -type f -exec md5sum {} \;

考えられる問題は絶対パスなので、より適切な「マニフェスト作成コマンド」は次のようになります。

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

sedただし、 mainfest.txt内のパスを修正することは常に可能です。

関連情報