Aqui está minha situação. Eu tenho dois volumes de arquivo de armazenamento frio que (deveriam) conter conjuntos idênticos de dados. Esses volumes contêm backups acessados com pouca frequência. Estou preocupado que, eventualmente, o bitrot chegue a um ou ambos e corrompa sutilmente os dados contidos neles. Eu sei que posso encontrar diff -r
os dois volumes e encontrar arquivos que foram alterados ou desapareceram entre os dois, mas não recebo nenhuma indicação útil sobre qual volume possui a cópia "boa". Estes são discos USB, e convertê-los para algo como ZFS parece... oneroso.
O que eu gostaria é de uma ferramenta que percorra recursivamente a árvore de diretórios e escreva um arquivo de manifesto contendo o caminho e o nome do arquivo junto com um hash do conteúdo do arquivo. Eu executaria essa ferramenta imediatamente após gravar os dados em cada volume e armazenaria o arquivo de manifesto resultante em armazenamento quente, talvez sob algum tipo de controle de revisão.
A partir deste arquivo, eu gostaria de poder executar algo que funcionasse exatamente como diff -r
- ele me diria se os arquivos foram adicionados, removidos ou se seu conteúdo foi alterado. Somente em vez de comparar um volume com o outro, ele compararia um volume com o arquivo de manifesto em bom estado. Usando esse método, devo saber se os dados que estou lendo no disco meses/anos no futuro são idênticos aos dados que coloquei originalmente nele.
Eu teria que pensar que algo assim já existe. Posso obter algo parecido com um arquivo de manifesto usando:
find /mnt/my-volume -type f -exec md5sum {} + > manifest.txt
mas até agora não descobri uma boa maneira de analisar esse arquivo e verificar cada hash recursivamente. Além disso, um pouco menos importante, isso não me dirá se um diretório vazio apareceu ou desapareceu. (Não consigo imaginar por que isso importaria, mas seria bom saber que isso ocorreu.)
Estou no caminho certo com isso ou existe uma ferramenta mais apropriada que possa fazer esse tipo de coisa?
Responder1
Você está certo, essa ferramenta já existe. Embora eu veja que sua postagem está marcada como 'linux', talvez uma solução orientada a BSD seja edificante.
Utilitário mtree(8) do FreeBSDpode fazer exatamente o que você está pedindo.
Suponha:
$ find .
.
./c
./c/file3
./b
./b/file2
./a
./a/file1
Para criar um manifesto dessa hierarquia de arquivos, incluindo um hash sha256 de cada arquivo, seria necessário:
$ 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
..
Pode-se então verificar a hierarquia do arquivo em relação ao manifesto canalizando o manifesto para o mtree:
$ mtree < /tmp/manifest.txt || echo fail
Arquivos adicionados, excluídos, renomeados ou modificados causarão falha na verificação:
$ 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
Responder2
Eles md5sum -c manifest.txt
honrariam os caminhos armazenados em manifest.txt
. O find
programa substitui {}
o caminho completo do arquivo encontrado incluindo qualquer local de pesquisa especificado na find
linha de comando, ou seja, para o arquivo ./a/b/c/d/e
ele substituirá o mesmo ./a/b/c/d/e
pelo comando
find ./a -type f -exec md5sum {} \;
O possível problema são os caminhos absolutos, então o 'comando de criação de manifesto' mais apropriado é:
cd /mnt/my-volume; find -type f -exec md5sum {} + > manifest.txt
no entanto, você sempre pode corrigir os caminhos sed
dentro de mainfest.txt