Вычислить md5sum каждой части потока в 1 МБ из канала
Я хочу сделать контрольные суммы больших файлов и потоков в 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 всех частей файла.
6 ответов
Что-то простое, как этот скрипт на Perl, вероятно, будет достаточно.
$amount = 1_000_000;
while (read(STDIN, $buffer, $amount) > 0) {
open MD5, "|md5";
print MD5 $buffer;
close MD5;
}
Поместите это в foo.pl
и вызвать его как perl foo.pl
в конце вашего трубопровода.
разделение от coreutils (по умолчанию в большинстве дистрибутивов Linux) имеет --filter
опция, которую вы можете использовать:
7z e -so image.7z | split -b 1000000 --filter=md5sum
Передайте вывод в этот скрипт Python 2, например 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()
rsync
работает так, вычисляя контрольную сумму, чтобы увидеть, есть ли различия в частях файла перед отправкой чего-либо.
Я не уверен, насколько хорошо он будет работать с файлами такого большого размера, хотя я никогда не слышал о том, чтобы у него было какое-либо ограничение размера файла.
Было легко написать небольшой хэш 1MB, используя rhash
инструменты (librhash
библиотека). Существует простой Perl-скрипт, который создает контрольные суммы каждой 1-мегабайтной части стандартного потока ввода. Нужно Crypt::Rhash
привязки из 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;
}
Этот общедоступный скрипт выведет десятичное смещение, затем +
затем размер блока, затем md5 и sha1 суммы ввода.
Например, 2 МБ нулей имеют суммы:
$ 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
Мне кажется, что вы ищете такой инструмент.
Из файла Readme BigSync:
Bigsync - это инструмент для постепенного резервного копирования одного большого файла в медленное место назначения (например, сетевой носитель или дешевый NAS). Наиболее распространенными случаями bigsync являются образы дисков, виртуальные операционные системы, зашифрованные тома и необработанные устройства.
Bigsync будет читать исходный файл по частям, вычисляя контрольные суммы для каждого. Он будет сравнивать их с ранее сохраненными значениями для файла назначения и перезаписывать измененные фрагменты, если контрольные суммы различаются.
Таким образом, мы сводим к минимуму доступ к медленным целевым носителям, что и составляет смысл существования BigSync.