Печать

Притащил мне юзер, значит, флешку. "Не открывается", говорит, "а там файлы очень нужные", такие дела. На самом деле флешка открывалась, но при попытке скопировать файлы компьютер вешался намертво. Скорее всего, выдернули не вовремя из разъёма - можно было бы просто ткнуть её себе в комп и попытаться натравить на раздел вендовый scandisk. Но файлы то "очень нужные", есть вероятность что флешка "немного умирает", так что пришлось действовать осторожно, чтобы не убить :).
дохлая флешка
Образ снять можно по-разному. Под windows есть несколько простых и бесплатных программок, но они не заточены на то, чтобы снимать данные с диска, на котором читаются не все блоки. Если такая программа примется каждый не читаемый сектор читать по нескольку раз - диск может помереть окончательно, унеся с собой все ещё не прочитанные байты, даже те, которые можно было бы прочитать до запуска программы. Гугление по форумам подсказывает, что есть R-Studio, есть WinHEX - но они платные, кряки искать не охота, да и не алё как-то ломаный софт на работе использовать. Есть такая неплохая штука, как Non-Stop Copy, но это немного не то т.к. работает на уровне файлов. В итоге, бесплатной и "проверенной временем" софтины под Windows для этой цели - при поверхностном гуглении обнаружить не удалось, поэтому стал смотреть в сторону linux-ового софта.

Вариант с dd отметаем сразу - его недаром в народе прозвали Disk Destroyer - вполне может и добить полуживое устройство теми же самыми повторными попытками прочитать один и тот же сбойный блок. Но есть как минимум две известные софтины, умеющие именно то, что нужно - сначала прочитать то, что ещё можно прочитать, и только потом более вдумчиво ковырять проблемные места. Называются они, что характерно, практически одинаково - dd_rescue и ddrescue (GNU ddrescue). Обе программы более-менее активно развиваются до сих пор, но духи (хабр, гугл и прочий инет) говорят, что ddrescue умеет всё что нужно "из коробки", а вот dd_rescue приходится "прокачивать" скриптом на bash, если это не сделать - dd_rescue работать будет жутко медленно. У dd_rescue, как говорят, есть ощутимое преимущество в способности по-всякому сжимать поток и засылать его в pipe, но мне оно не надо. Значит, берём ddrescue. Установить в Debian её можно как-то так:

apt-get install gddrescue


Теперь нужен компьютер с linux. Идеально, конечно, загрузить что-то вроде Debian на реальном и живом компьютере, но в принципе сойдёт и минимальная установка, живущая внутри VirtualBox - по крайней мере, мне этот вариант вполне удобен, хотя виртуализация порой добавляет немного проблем - о встретившихся виртуальных граблях расскажу по ходу повествования.

DDRescue GUI
Для GNU ddrescue существует GUI на питоне (в репозиториях отсутствует, можно взять отсюда), но у меня он нормально не заработал (возможно, дело в версии python), так что пришлось читать документацию к консольной утилите :). Опций там много разных, и со всем этим разным вдумчивый читатель может ознакомиться самостоятельно, набрав в консоли info ddrescue (или pinfo ddrescue, что имхо гораздо удобнее). Те же, кто менее вдумчив, или кому нужно просто ехать, а не шашечки - сразу зайдут в раздел examples документации и обнаружат, что типовые параметры запуска достаточно просты.

ddrescue -n /dev/hda ./filename.ddr ./logfilename.log

Так запускается первый проход по диску. С диска /dev/hda пишется образ в filename.ddr, лог (он важен!) сохраняется в logfilename.log. Опция -n заставит программу бережнее относиться к плохим блокам - не пытаться повторять чтение или искать в плохом блоке читаемые куски меньшего размера. Теоретически можно в первый проход использовать ещё и опцию -d чтобы программа работала с диском напрямую, не обращаясь к кешу операционной системы, но для этого нужно либо задать правильный размер сектора опциями, либо понадеяться, что размер по умолчанию соответствует реальному для устройства :). В моём случае (с флешкой) размер в 512 байт по умолчанию подошёл, т.е. в первый проход данные нормально читались с опцией -d.
Сам процесс чтения и записи образа сопровождается выводом в консоль информации о скорости и прогрессе выполнения, так что GUI не сильно то и нужен.

ddrescue -dr3 /dev/hda ./filename.ddr ./logfilename.log

Второй проход - с прямым доступом к диску и уже не осторожничаем, каждый сбойный блок пытаемся прочитать по три раза. Программа при этом пользуется данными, сохранёнными в первом проходе в лог-файл, при этом те данные, которые уже были успешно вынуты с проблемного диска - повторно не читаются, ddrescue просто пытается вытянуть с диска всё, что ещё возможно.

Всё, теперь можно или пытаться использовать продвинутые возможности ddrescue чтобы спасти ещё немного данных (если спасено не всё), либо скармливать полученный файл любой программе для препарирования образов диска и вынимать оттуда информацию. В принципе, можно просто переписать образ на исправный диск с помощью dd

dd if=./filename.ddr of=/dev/hdb bs=10M

Запишет содержимое образа на диск /dev/hdb блоками по 10 мегабайт (если оставить размер блока по умолчанию - снизится скорость копирования). Теперь можно натравливать на диск любые проверялки файловых систем и монтировать это дело стандартными средствами операционок.

Как вариант (если считалось всё или почти всё) - можно починить файловую систему прямо в образе (образ стоит забекапить перед этим), затем смонтировать сам образ и вынуть оттуда выжившие файлы. И тут нужно обратить внимание на следующее - если образ снимался с устройства целиком - значит, в файле образа лежит не только раздел с файловой системой, но и MBR (либо GPT для EFI) - т.е. таблица разделов и, возможно, код загрузчика. Поэтому просто так взять и натравить на полный образ диска какой-нибудь mount или dosfsck - нельзя. Либо сразу создавайте образы с отдельных разделов, либо придётся читать таблицу разделов и задавать до них смещения. Проще всего просмотреть таблицу разделов, натравив на файл образа linux-овый fdisk.

fdisk -uc ./filename.ddr

Опция u заставляет fdisk отображать смещения в секторах, а не в цилиндрах (чтобы не пересчитывать цилиндры в байты); опция c отключает устаревший режим MSDOS, который, в общем-то, не мешает, но документация рекомендует его отключать. В результате получим что-то типа такого:

# fdisk -uc ./filename.ddr
You must set cylinders.
You can do this from the extra functions menu.

Command (m for help): p

Disk ./filename.ddr: 0 MB, 0 bytes
32 heads, 63 sectors/track, 0 cylinders, total 0 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x06392f78

       Device Boot      Start         End      Blocks   Id  System
./rescue.ddr1   *          63     7553951     3776944+   b  W95 FAT32

Command (m for help): q

Красным выделены команды, которые нужно дать с клавиатуры. Команда p заставит вывести информацию по разделам, команда q - завершить работу fdisk. Как видно, в одном секторе 512 байт, а первый и единственный раздел файловой системы внутри образа - начинается с 63 сектора, т.е. первый байт файловой системы смещён от начала файла образа на 63*512=32256 байт.
Однако fdisk не умеет работать с GPT (это новый формат таблицы разделов для EFI - более нового аналога BIOS) который, в частности, вместо MBR по умолчанию использует Windows 8. Поэтому альтернативный вариант - программа parted (не путать с gparted!). Скорее всего, она уже установлена, но если нет - что-нибудь вроде apt-get install parted спасёт отца русской демократии :). Натравливаем parted сразу на образ:

# parted ./filename.ddr
GNU Parted 2.3
Using ./filename.ddr
Welcome to GNU Parted! Type 'help' to view a list of commands.
(parted) unit s
(parted) print
Model:  (file)
Disk ./filename.ddr: 7555528s
Sector size (logical/physical): 512B/512B
Partition Table: msdos

Number    Start        End                Size                Type        File system    Flags
1                63s            7553951s        7553889s    primary    fat32                boot

(parted) q

Командой unit s включаем отображение размеров в секторах, иначе parted выдаст округлённо-приближённо-человекочитаемые цифры типа "32,3kB"", из которых получить точное число байт несколько проблематично. Командой print - получаем таблицу разделов. Командой q - выходим из parted. Собственно, здесь тоже видно, что размер сектора 512 байт, а смещение раздела - 63 сектора.

Теперь можно манипулировать разделом. Если нужно просто примонтировать его - достаточно примерно такой команды:

mount -t vfat -o loop,offset=32256 /root/temp/filename.ddr /mnt/temp

Монтирует файловую систему типа vfat (fdisk и parted выше недвусмысленно намекали, что файловая система раздела - fat32) из файла образа /root/temp/filename.ddr в каталог /mnt/tmp. Каталог, понятное дело, должен существовать. Опция loop заставляет mount самостоятельно подключить образ на loopback device (представить его в виде блочного устройства), а offset задаёт ранее добытое нами смещение в файле образа до начала раздела. Смещение в принципе можно записать в виде $((63*512)) - тогда bash самостоятельно вычислит 32256 и подставит в команду. Если образ снимался прямо с раздела - опцию offset нужно убрать.

Однако если образ не удалось снять с диска целиком и в нём остались "белые пятна" из не прочитавшихся блоков - файловая система может либо вообще не подмонтироваться, либо ошибки могут возникнуть в процессе работы с разделом. Теоретически подлатать раздел можно утилитой проверки вроде dosfsck, но для этого придётся руками подключить раздел из образа в виде блочного устройства:

losetup -o 32256 /dev/loop0 /root/temp/filename.ddr

Команда представляет раздел из образа /root/temp/filename.ddr со смещением (указано опцией -o) в виде устройства /dev/loop0. Если в образе несколько разделов и какие-либо разделы идут после того, с которым вы собираетесь работать - крайне рекомендуется установить ограничение размера опцией --sizelimit. В противном случае в устройстве /dev/loop0 будут видны не только байты нужного раздела, но и всех что идут за ним. Смещение конца раздела вычисляется точно так же как и для начала - смотрим что fdisk\parted выдаёт в End и умножаем количество секторов на размер сектора.
Теперь с устройством /dev/loop0 можно работать точно так же, как с каким-нибудь /dev/sda1 - монтировать, натравливать утилиты проверки файловых систем, утилиты для восстановления данных... в общем, что угодно. Например, попытаемся восстановить файловую систему:

dosfsck -a /dev/loop0

Опция -a заставит исправлять ошибки автоматически. Подмонтировать можно примерно так:

mount -t vfat /dev/loop0 /mnt/temp

Если блочное устройство больше не нужно и его надо отсоединить - используем опцию -d.

losetup -d /dev/loop0


Несколько слов о работе через VirtualBox.

В общем, по-быстрому поковырять флешку удобнее может быть с виртуальной машины. Но с целью чего-то посерьезнее держать наготове системник, в том числе с установленным дистрибутивом linux - на мой взгляд, всё же оптимальный вариант. Кстати, вместо виртуалки можно установить на windows cygwin - там, помнится, была уже скомпиллированная под windows версия ddrescue.

Ну и о судьбе флешки, с которой всё началось - мне повезло и образ спокойно считался в режиме прямого доступа к диску в первом же проходе, без единой ошибки. Но сама флешка при этом умерла - не удаётся ни переформатировать файловую систему, ни восстановить scandisk-ом или dosfsck-ом, файлы же на флешке перестали видеться после первой же попытки починить файловую систему.

Файловая система внутри образа была немного повреждена. После восстановления с помощью dosfsck выяснилось, что несколько файлов побиты, но ничего важного среди них не было (только логи и конфиги portable-программы). Все хранившиеся там вордовские и прочие офисные документы уцелели и вернулись к своему владельцу.


 


 

www.38i.ru