Вычислить md5sum каждой части потока в 1 МБ из канала

1668
osgx

Я хочу делать контрольные суммы больших файлов и потоков в unix / linux, и я хочу получить много контрольных сумм из каждой большой части файла / потока, каждые 1 МБ или каждые 10 МБ.

Например, у меня есть образ диска, сжатый образ диска и копия исходного диска. Некоторые части изображений могут быть изменены. Диск составляет 50 ГБ, и есть около 50000 блоков по 1 МБ. Поэтому для каждого файла я хочу получить 50 000 md5sum или sha1sums, чтобы получить обзор изменений. Одиночная md5sum не поможет мне найти смещение модификации.

Эта задача проста для несжатого образа диска, с использованием ddинструмента в forцикле в bash со смещением вычислений и выбором (пропуском) каждой 1 МБ части файла. То же самое с диском:

for a in `seq 1 50000`; do echo -n "$a: "; dd if=image.src bs=1M count=1 skip=$a | md5sum; done 

Но теперь я хочу сравнить сжатый образ и несжатый, не распаковывая его на диск. У меня есть 7zраспаковщик, который может распаковать образ на стандартный вывод с высокой скоростью, до 150-200 МБ / с (варианты 7z e -so image.7z |). Но что я могу написать после |символа, чтобы получить md5sum всех частей файла.

2

6 ответов на вопрос

6
Cristian Ciupitu

split from coreutils (the default on most Linux distributions) has a --filter option which you can use:

7z e -so image.7z | split -b 1000000 --filter=md5sum 
Острота. Я не знал об этом. Kyle Jones 9 лет назад 0
2
Kyle Jones

Something simple like this Perl script probably would suffice.

$amount = 1_000_000; while (read(STDIN, $buffer, $amount) > 0) { open MD5, "|md5"; print MD5 $buffer; close MD5; } 

Put this in foo.pl and invoke it as perl foo.pl at the end of your pipeline.

Классная версия, спасибо. Я только что закончил свою работу, используя `Crypt :: Rhash` (md5 + sha1 + tiger - все еще довольно быстро). Вы можете изменить мой код для лучшей читаемости и стиля. osgx 9 лет назад 0
И сценарий показывает, что мои изображения похожи на мой жесткий диск, но не совпадают. Я почти уничтожил 50 ГБ уникальных данных. osgx 9 лет назад 0
0
Luis

It seems to me that you're looking for this kind of a tool.

From the Readme file of BigSync:

Bigsync is a tool to incrementally backup a single large file to a slow destination (think network media or a cheap NAS). The most common cases for bigsync are disk images, virtual OSes, encrypted volumes and raw devices.

Bigsync will read the source file in chunks calculating checksums for each one. It will compare them with previously stored values for the destination file and overwrite changed chunks if checksums differ.

This way we minimize the access to a slow target media which is the whole point of bigsync's existence.

«Bigsync будет читать исходный файл по частям, вычисляя контрольные суммы для каждого» - эта часть верна, но я не хочу ничего менять. osgx 9 лет назад 0
0
osgx

It was easy to write small 1MB hasher using rhash tools (librhash library). There is simple perl script which creates checksums of each 1MB part of standard input stream. It needs Crypt::Rhash bindings from cpan:

$ cpan (cpan) install Crypt::Rhash $ cat rhash1M.pl #!/usr/bin/perl # Compute md5 and sha1 sum of every 1 MB part of stream use strict; use local::lib; use Crypt::Rhash; my ($buf, $len, $i); my $r=Crypt::Rhash->new(RHASH_MD5|RHASH_SHA1); # we can add more hashes, like RHASH_TIGER etc binmode STDIN; $i=0; while($len= read STDIN,$buf,1024*1024){ print "$i+$len: \t"; # print offset $r->update($buf); print "md5:",$r->hash(RHASH_MD5), " sha1:", $r->hash(RHASH_SHA1),"\n"; $r->reset(); # reset hash calculator $i+=$len; } 

This public domain script will output decimal offset, then +, then block size, then md5 and sha1 sums of input.

For example 2 MB of zeroes has sums:

$ dd if=/dev/zero of=zerofile bs=1M count=2 $ ./rhash1M.pl < zerofile 0+1048576: md5:b6d81b360a5672d80c27430f39153e2c sha1:3b71f43ff30f4b15b5cd85dd9e95ebc7e84eb5a3 1048576+1048576: md5:b6d81b360a5672d80c27430f39153e2c sha1:3b71f43ff30f4b15b5cd85dd9e95ebc7e84eb5a3 
0
localhost

rsync works like this, computing a checksum to see if there are differences in parts of the file before sending anything.

I'm not sure how well it would function with files this large, although I have never heard of it having any file size limitation.

0
Cristian Ciupitu

Pipe the output to this Python 2 script, for example 7z e -so image.7z | python md5sum.py:

import sys, hashlib CHUNK_SIZE = 1000 * 1000 for chunk in iter(lambda: sys.stdin.read(CHUNK_SIZE), ''): print hashlib.new('md5', chunk).hexdigest() 
Какой вход? Как это работает? Что делает пользователь, от шага 1 до шага * x *? Это некачественный ответ как есть. Canadian Luke 9 лет назад 1
Пожалуйста, добавьте больше информации к этому сообщению (что делает каждая строка и т. Д. Просто добавьте комментарии). Я нажал «Looks Good» в очереди LQP, потому что я вижу, как это можно легко исправить, но это LQP. Frank 9 лет назад 0
@CanadianLuke, я объяснил, как его использовать. Cristian Ciupitu 9 лет назад 0