Рассмотрим простое блочное устройство объемом 100 МБ в качестве простого примера. Это 204800 блоков по 512 байт каждый на общую сумму 102760448 байт.
Задача состоит в том, чтобы переместить первые 98 МБ (блоки 200704), чтобы перед ним был разрыв в 2 МБ (4096 блоков). Для этого требуется, чтобы ничего не было записано в сектор, который не был прочитан. Одним из способов достижения этого является введение буфера:
$ dd if=/dev/sdj2 count=200704 | mbuffer -s 512 -b 4096 -P 100 | dd of=/dev/sdj2 seek=4096
Предполагается, что mbuffer
перед передачей чего-либо записывающему устройству будет сохранено 4096 блоков, что гарантирует, что ничего не будет записано в область, которая не была прочитана, и что записывающее устройство отстает от читателя по размеру буфера. Буфер должен позволять читателю и записывающему устройству работать как можно быстрее в пределах этих констант.
Однако, это, кажется, не работает надежно. Я пытался использовать реальные устройства, но они никогда не работают на них, тогда как эксперименты с файлом работали на моем 64-разрядном компьютере, но не на моем 32-разрядном устройстве.
Сначала немного подготовки:
$ dd if=/dev/sdj2 count=200704 | md5sum
0f0727f6644dac7a6ec60ea98ffc6da9
$ dd if=/dev/sdj2 count=200704 of=testfile
Это не работает:
$ dd if=/dev/sdj2 count=200704 | mbuffer -s 512 -b 4096 -P 100 -H | dd of=/dev/sdj2 seek=4096
summary: 98.0 MiByte in 4.4sec - average of 22.0 MiB/s
md5 hash: 3cbf1ca59a250d19573285458e320ade
Это работает на 64-битной системе, но не на 32-битной системе:
$ dd if=testfile count=200704 | mbuffer -s 512 -b 4096 -P 100 -H | dd of=testfile seek=4096 conv=notrunc
summary: 98.0 MiByte in 0.9sec - average of 111 MiB/s
md5 hash: 0f0727f6644dac7a6ec60ea98ffc6da9
Как это можно сделать надежно?
заметки
Я прочитал другие вопросы о буферизации и посмотрел pv
, buffer
и mbuffer
. Я мог только заставить последний работать с требуемым размером буфера.
Использование промежуточного хранилища является очевидным решением проблемы, которая всегда работает, но не практична, когда не хватает достаточной резервной емкости.
Тестовые платформы под управлением Arch Linux с mbuffer
версией 20140302.
источник
mbuffer
вообще использовать ? Почему бы вместо этого не сделатьdd
чтение всего содержимого блочного устройства за один разdd bs=102760448
? Конечно, так или иначе он буферизируется в оперативной памяти.mbuffer
Должны фактически заставить второйdd
отстать для первого и вам нужна только достаточно оперативной памяти для буферизации размера сдвига. Жаль,dd
что не поддерживается чтение и запись блоков в обратном порядке, поскольку это устранит проблему!-H
аргумент включает эту функцию).Ответы:
Без буфера вы можете вернуться назад, по одному блоку за раз.
Обратите внимание, что этот пример опасен из-за отсутствия проверки ошибок.
Это также медленно из-за количества
dd
звонков. Если у вас есть свободная память, вы можете использовать больший размер блока.С буфером, остерегайтесь ловушек . Это не достаточно , чтобы гарантировать 100% предварительное заполнение с. Что вам нужно, так это минимальное заполнение на протяжении всего процесса. Буфер никогда не должен опускаться ниже,
2M
потому что иначе вы перезапишете данные, которые еще предстоит прочитать.Так что теоретически вы можете обойтись без буфера и цепочки
dd
:На практике это не работает надежно, потому что нет гарантии, что первому
dd
удастся продолжить чтение данных, в то время как последнийdd
(с2M
«буфером» между) уже записывает.Вы можете значительно увеличить свои шансы, значительно увеличив промежуточный буфер, но даже в этом случае это ненадежно.
К сожалению, я не знаю хорошей буферной программы с минимальным свойством заполнения. Вам нужен тот, который останавливает вывод, если в буфере меньше вашего запаса прочности.
источник
dd
можно использовать. Я думаю, однако, что реальное решение не в том, чтобы использовать,dd
а вместо этого выбрать что-то, что предназначено для работы в обратном направленииddrescue
. Я описал способ сделать это в ответе.ddrescue
здесь. Нет, если он рассчитывает работать на разных устройствах, и вы должны обмануть его, чтобы принять ваши аргументы. Он также может не иметь свойства «минимальное заполнение буфера» внутри (поскольку на разных устройствах он не нужен), поэтому он может повредить ваши данные. Вы должны проверить в исходном коде, действительно ли он предназначен для вашего случая использования.Вы читаете 4096 блоков, а затем записываете эти 4096 блоков на следующие 4096 блоков диска, таким образом перезаписывая вторые 4096 блоков, прежде чем их можно будет прочитать. Вам нужно прочитать 8129 блоков, чтобы получить эти 4096 секунд, прежде чем начинать запись, а затем вам нужно написать только 4096 блоков, прежде чем читать следующие 4096.
Вы не упомянули, что это за файловая система. Если это ext [234], и у вас есть последняя версия e2fsprogs, то вы можете использовать
e2image -ra -O 512 /dev/sdj2
. Это также имеет дополнительное преимущество, заключающееся в том, что вы достаточно умны, чтобы пропустить свободное место в томе.источник
ext4
для блочной копии устройства, любая файловая система должна быть неактуальной.dd
не делает.Надежное решение требует, чтобы вы гарантировали, что ничего не записывает в область, которая, возможно, не была прочитана, и единственный реальный способ добиться этого - выполнить копирование в обратном направлении.
ddrescue
Инструмент может работать в обратном направлении , но он отказывается работать с входными и выходными данными являются одинаковыми. Однако это можно обмануть, дублируя узел устройства.Я провел несколько быстрых экспериментов, и это похоже на работу. Командная строка:
Аргументы
-f
необходимо заставить его записать в существующее устройство вывода-R
говорит ему работать в обратном направлении-s
говорит ему, сколько входных данных копировать (я использовалs
суффикс для указания количества секторов)-o
говорит ему искать вперед в устройстве вывода перед записью (снова указывается в секторах сs
суффиксом)/dev/sdj11
это блочное устройство для чтения/dev/sdj11_copy
это блочное устройство для записиЯ создал
/dev/sdj11_copy
с,mknod
чтобы соответствовать параметрам/dev/sdj11
.Я только сделал несколько очень быстрых тестов, но, похоже, это нормально работает для копирования необработанного устройства. Он не работает с файлом (я не мог обмануть его, чтобы выйти за пределы файлов, являющихся одинаковыми)
Это не отвечает на мой первоначальный вопрос, в котором спрашивалось, как этого добиться,
dd
но я думаю, что, прочитав другие ответы, яdd
не смог этого сделать.источник
ddrescue
обнаружит плохой блок в этом сценарии? Если он перейдет в другую область диска (чтобы избежать плохих блоков) и продолжит копирование оттуда, он снова перезапишет еще не скопированные части ваших данных. Если он не рассчитывает на работу с одним и тем же устройством, у него нет причин принимать какие-либо специальные меры для предотвращения возможных случаев повреждения данных.ddrescue
варианты ограничения попыток восстановить плохие данные, но я не стал их использовать.