Aquí está mi situación. Tengo dos volúmenes de archivos de almacenamiento en frío que (deberían) contener conjuntos de datos idénticos. Estos volúmenes contienen copias de seguridad a las que se accede con poca frecuencia. Me preocupa que, eventualmente, bitrot llegue a uno o ambos y corrompa sutilmente los datos contenidos en ellos. Sé que puedo buscar diff -r
en los dos volúmenes y encontrar archivos que han cambiado o desaparecido entre los dos, pero no obtengo ninguna indicación útil sobre qué volumen tiene la copia "buena". Estos son discos USB, y convertirlos a algo como ZFS parece... oneroso.
Lo que me gustaría es una herramienta que recorra de forma recursiva el árbol de directorios y escriba un archivo de manifiesto que contenga la ruta y el nombre del archivo junto con un hash del contenido del archivo. Ejecutaría esta herramienta inmediatamente después de escribir los datos en cada volumen y almacenaría el archivo de manifiesto resultante en un almacenamiento cálido, tal vez bajo algún tipo de control de revisión.
Desde este archivo me gustaría poder ejecutar algo que funcione exactamente igual diff -r
: me diría si se agregaron, eliminaron archivos o si se modificó su contenido. Solo que en lugar de comparar un volumen con otro, compararía un volumen con el archivo de manifiesto en buen estado. Usando este método, debería poder saber si los datos que estoy leyendo del disco dentro de meses/años son idénticos a los datos que puse originalmente en él.
Tendría que pensar que algo como esto ya existe. Puedo obtener algo parecido a un archivo de manifiesto usando:
find /mnt/my-volume -type f -exec md5sum {} + > manifest.txt
pero hasta ahora no he encontrado una buena manera de analizar este archivo y verificar cada hash de forma recursiva. Además, algo menos importante, esto no me dirá si apareció o desapareció un directorio vacío. (No se me ocurre por qué importaría, pero sería bueno saber que ocurrió).
¿Estoy en el camino correcto con esto o existe una herramienta más adecuada que pueda hacer este tipo de cosas?
Respuesta1
Tienes razón, esa herramienta ya existe. Si bien veo que su publicación está etiquetada como 'linux', tal vez una solución orientada a BSD sea edificante.
Utilidad mtree(8) de FreeBSDpuede hacer exactamente lo que estás pidiendo.
Suponer:
$ find .
.
./c
./c/file3
./b
./b/file2
./a
./a/file1
Para crear un manifiesto de esa jerarquía de archivos, incluido un hash sha256 de cada archivo, se haría lo siguiente:
$ 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
..
Luego se puede verificar la jerarquía de archivos con el manifiesto canalizando el manifiesto a mtree:
$ mtree < /tmp/manifest.txt || echo fail
Los archivos agregados, eliminados, renombrados o modificados harán que la verificación falle:
$ 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
Respuesta2
Respetarían md5sum -c manifest.txt
las rutas almacenadas en manifest.txt
. El find
programa sustituye {}
la ruta completa al archivo encontrado, incluida cualquier ubicación de búsqueda especificada en la find
línea de comando, es decir, ./a/b/c/d/e
sustituirá el archivo ./a/b/c/d/e
por el mismo comando.
find ./a -type f -exec md5sum {} \;
El posible problema son las rutas absolutas, por lo que el 'comando de creación de manifiesto' más apropiado es:
cd /mnt/my-volume; find -type f -exec md5sum {} + > manifest.txt
sin embargo, siempre puedes arreglar las rutas sed
dentro de mainfest.txt