這是我的情況。我有兩個冷存儲存檔卷(應該)包含相同的資料集。這些磁碟區包含不經常存取的備份。我擔心,最終,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.txt
。該find
程式會取代{}
找到的文件的完整路徑,包括在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 內的路徑