Жёсткий диск редко уходит мгновенно. Чаще он подаёт предупреждения заранее - подвисает на ровном месте, замирает при копировании больших файлов, выдаёт странные щелчки или просто начинает читать в десять раз медленнее обычного. Именно в этот момент ещё остаётся шанс вытащить почти всё содержимое, если действовать аккуратно и не делать классических ошибок вроде запуска fsck или попытки скопировать файлы напрямую через файловый менеджер. Утилита GNU ddrescue создана как раз для таких ситуаций, и за двадцать с лишним лет своего существования она спасла больше данных, чем любой коммерческий аналог из тех, что обещают чудеса за деньги.
История у этой программы любопытная. Изначально автор Антонио Диас Диас писал её как замену классическому dd с расширенной обработкой ошибок, но довольно быстро инструмент превратился в стандарт де-факто для всех, кто занимается восстановлением информации без специализированного оборудования. Сегодня её используют и системные администраторы, и судебные эксперты, и обычные пользователи, у которых внезапно засыпал внешний диск с фотографиями последних десяти лет.
Почему обычный dd губит то, что ещё можно было спасти
Между dd и ddrescue лежит пропасть, хотя имена похожи. Обычный dd останавливается на первой же ошибке чтения. Сбойный диск может содержать всего несколько повреждённых секторов на гигабайты живых данных, но dd ничего из этого не вытащит, как только наткнётся на первую проблему. Это поведение разумно для копирования здоровых носителей, но катастрофично, когда речь идёт о спасении информации с уже умирающего накопителя.
ddrescue работает иначе. Алгоритм спроектирован так, чтобы сначала забрать всё лёгкое, а трудное оставить на потом. Логика тут не техническая прихоть, а вопрос выживания диска. Каждое обращение к битому сектору заставляет контроллер запускать внутренний цикл коррекции ошибок, и пока этот цикл крутится, головки тратят ресурс, а температура подшипников ползёт вверх. Часами биться об один и тот же кластер - значит почти гарантированно угробить остальной диск до того, как с него снимут образ. Многие любители теряют последний шанс на восстановление именно из-за того, что запускают агрессивные утилиты на и так еле живом носителе.
Программа разбивает работу на пять фаз. Сначала идёт быстрое копирование крупными блоками, при котором проблемные участки просто пропускаются и помечаются особым статусом. Затем подключается так называемая обрезка краёв - алгоритм пытается определить, где именно проходит граница между читаемым и нечитаемым внутри подозрительной зоны. Третья фаза называется sweeping и представляет собой ещё один проход по нетронутым участкам уже без ограничения по скорости. Четвёртая - scraping, посекторное вычитывание оставшихся областей. И только в самом конце наступает фаза retrying - повторные попытки прочесть то, что не далось ни в одном из предыдущих заходов.
Такая последовательность не случайна. Она построена на простом наблюдении: чем дольше диск работает в стрессовом режиме, тем меньше шансов получить с него хоть что-то. Поэтому всё ценное забирается в первую очередь, а самые сложные участки откладываются на потом, когда уже не страшно потерять остальное.
Что нужно проверить до того, как подключать пациента к стенду
Прежде чем запускать ddrescue, стоит понять, с чем именно имеешь дело. Не каждая поломка лечится посекторным клонированием. Если диск стучит, пищит, скрежещет или вообще не определяется в BIOS, домашний эксперимент бесполезен и даже вреден. Такие симптомы указывают на физический отказ блока головок или двигателя, и тут поможет только лаборатория с чистой комнатой и запасными донорами на разборку.
А вот если накопитель крутится, опознаётся системой, но при чтении тормозит или сыплет ошибками в dmesg - это та самая ниша, где ddrescue показывает максимум возможностей. Перед запуском полезно снять показания SMART и трезво оценить ситуацию. Делается это так:
sudo smartctl -a /dev/sdX
В выводе нужно обращать внимание на несколько ключевых атрибутов. Reallocated Sector Count (ID 5) показывает количество секторов, уже выведенных из строя и заменённых из резервной области. Current Pending Sector Count (ID 197) считает секторы, которые диск пометил для переназначения, но ещё не переписал. Каждая попытка чтения такого сектора запускает внутренний цикл коррекции, который может застопорить контроллер на десятки секунд. Offline Uncorrectable (ID 198) указывает на сектора, которые диск признал нечитаемыми при фоновом сканировании. UDMA CRC Error Count (ID 199) часто сигнализирует не о проблемах диска, а о плохом шлейфе или окисленных контактах SATA, и это стоит исключить в первую очередь.
Если значение Current Pending переваливает за сотню, имеет смысл понизить порог скорости чтения, чтобы ddrescue быстрее пропускал зависающие зоны на первом проходе и возвращался к ним позже, когда здоровая часть диска уже окажется в безопасности на другом носителе. Параллельно полезно посмотреть, как система видит диск физически, и убедиться, что устройство опознано под ожидаемым именем:
lsblk -o NAME,SIZE,MODEL,SERIAL,TYPE
sudo fdisk -l /dev/sdX
Тройная проверка имени устройства - это не паранойя, а здравый смысл. Перепутав исходный диск с приёмным, можно за секунду затереть остатки данных безвозвратно. Серийный номер из вывода lsblk стоит сверить с этикеткой на корпусе накопителя, особенно если в системе подключено несколько похожих дисков.
Подготовка целевого носителя и зачем нужен mapfile
Целевой диск должен быть как минимум того же объёма, что и больной, а лучше с запасом. Образ создаётся сектор в сектор, и попытка ужать его в меньший контейнер обречена на провал. Файловая система на приёмнике должна выдерживать большие файлы, так что FAT32 с её лимитом в четыре гигабайта сразу отпадает - ext4, XFS или NTFS подойдут. Сам ddrescue устанавливается в большинстве дистрибутивов из репозиториев, но имя пакета может смущать новичков:
sudo apt update
sudo apt install gddrescue
ddrescue --version
В Debian и Ubuntu пакет называется gddrescue, чтобы отличать его от другой утилиты с похожим именем, но сам бинарник после установки доступен как ddrescue. В дистрибутивах семейства Red Hat пакет так и зовётся - ddrescue, и ставится через dnf. Версия должна быть не ниже 1.25, в более старых выпусках отсутствуют некоторые полезные опции вроде корректной работы с большими бэд-блоками.
Третий аргумент команды ddrescue - это mapfile, и именно он превращает разовое копирование в управляемый процесс. Без него никакой полноценной работы не получится. Mapfile фиксирует статус каждого участка диска, и его содержимое можно расшифровать. В нём встречаются строки с шестнадцатеричными адресами и символами статуса. Плюс означает успешно прочитанный блок, минус - блок, который восстановить не удалось. Помимо этих двух обозначений во время работы появляются и другие, отражающие промежуточные фазы алгоритма: вопросительный знак для нетронутых областей, звёздочка для нетримированных, косая черта для нескрапленных.
Главное практическое следствие существования mapfile - возможность прерывать процесс и возобновлять его. Если больной диск отвалится посреди ночи, утром достаточно повторить ту же команду, и ddrescue продолжит ровно с того места, где остановился, не перечитывая уже снятое. Это особенно ценно при работе с большими накопителями, где полный прогон может растянуться на сутки или больше.
Первый проход без агрессии и второй с повторными попытками
Грамотная стратегия восстановления делится на два этапа, и смешивать их в одну команду - распространённая ошибка новичков. На первом проходе задача одна: забрать всё, что читается без сопротивления. Никаких повторов, никакого долбления в одну точку. Команда выглядит так:
sudo ddrescue -f -n -b 4096 /dev/sdX /mnt/backup/disk.img /mnt/backup/rescue.map
Разберём её по частям. Флаг -f нужен, если выход направлен на блочное устройство, а не в файл, и означает принудительную перезапись цели. Флаг -n отключает фазу скрапинга и заставляет утилиту пропускать всё, что не даётся с первого раза - именно это и обеспечивает быстрый забор лёгких данных без износа диска. Параметр -b 4096 устанавливает размер сектора в четыре килобайта, что соответствует физическому размеру блока на современных накопителях формата Advanced Format и работает быстрее значения по умолчанию в 512 байт. /dev/sdX - это больной диск, и важно трижды убедиться, что буква правильная.
Если ядро Linux начинает захлёбываться от потока ошибок и кеширование мешает корректной работе, имеет смысл сразу добавить флаг прямого доступа к устройству, минуя страничный кеш:
sudo ddrescue -f -n -d --idirect /dev/sdX /mnt/backup/disk.img /mnt/backup/rescue.map
После первого прохода в большинстве случаев восстанавливается от 95 до 99,9 процентов содержимого, причём за разумное время. Реальный пример с терабайтного диска показывает результат вроде такого: спасено 999 690 МБ, ошибок чтения 45, процент восстановления 99,94, время работы 19 часов и 7 минут. Это типичная картина для накопителя с локальными дефектами поверхности, и тут можно облегчённо выдохнуть - основная масса данных уже в безопасности.
Второй проход уже посвящён борьбе за оставшиеся доли процента, и здесь подход меняется:
sudo ddrescue -d -r3 /dev/sdX /mnt/backup/disk.img /mnt/backup/rescue.map
Параметр -d включает прямой доступ к устройству в обход буферов ядра, что особенно полезно, когда драйверы начинают истерить от количества ошибок. -r3 задаёт три попытки на каждый битый сектор. Больше ставить обычно бессмысленно: если сектор не прочитался за три раза, он почти наверняка не прочитается и за тридцать, а износ диска при этом только растёт. Опытные восстановители иногда ставят -r1 для особо тяжёлых случаев, считая, что лишний стресс важнее призрачного шанса дочитать ещё несколько килобайт.
Для совсем сложных случаев бывает полезен ещё один вариант второго прохода, с принудительным повторным сканированием всех участков, помеченных как нетримированные и нескрапленные:
sudo ddrescue -d -r3 --try-again /dev/sdX /mnt/backup/disk.img /mnt/backup/rescue.map
Опция --try-again помечает все блоки с промежуточными статусами как нетронутые перед началом работы, что заставляет ddrescue ещё раз попробовать прочитать их с чистого листа. Это имеет смысл, если между проходами диск отдохнул в холодильнике или просто остыл, и появилась надежда на временное улучшение состояния поверхности. Да, охлаждение действительно иногда помогает - тепловое расширение влияет на позиционирование головок, и холодный диск порой читает то, что горячий не отдавал.
Чтение прогресса в реальном времени и что означают строчки на экране
Во время работы ddrescue выводит регулярно обновляющуюся сводку, и в ней важно понимать каждое поле. Картинка выглядит примерно так:
GNU ddrescue 1.27
Press Ctrl-C to interrupt
ipos: 1000 GB, non-trimmed: 3145 kB, current rate: 71761 kB/s
opos: 1000 GB, non-scraped: 0 B, average rate: 14452 kB/s
non-tried: 511377 kB, bad-sector: 0 B, error rate: 0 B/s
rescued: 999690 MB, bad areas: 0, run time: 19h 7m 58s
pct rescued: 99.94%, read errors: 45, remaining time: 8s
time since last successful read: 0s
Copying non-tried blocks... Pass 1 (forwards)
Поле ipos показывает текущую позицию чтения на входе, opos - на выходе. Параметр rescued отражает общий объём успешно скопированного. Значение non-tried означает, сколько байт ещё не пробовали прочесть. Non-trimmed - объём блоков, которые попали в категорию подозрительных, но ещё не обрезаны по краям. Non-scraped - блоки, ждущие посекторного вычитывания. Bad-sector - подтверждённо нечитаемые секторы. Параметр errors указывает количество отдельных групп ошибок, причём одна группа может содержать как один битый сектор, так и тысячи подряд.
Особое внимание стоит обращать на current rate. Если на здоровом участке скорость падает с привычных 80-150 МБ/с до считанных килобайт, это явный признак, что диск увяз в проблемной зоне. В такой момент имеет смысл прервать процесс через Ctrl-C, посмотреть в логи системы через dmesg и подумать, не пора ли перейти ко второму проходу с более агрессивным пропуском зависающих участков. Параметр минимальной скорости чтения помогает не зависнуть в проблемной зоне:
sudo ddrescue -f -n -d --min-read-rate=1M /dev/sdX /mnt/backup/disk.img /mnt/backup/rescue.map
Здесь ddrescue будет пропускать вперёд участки, где скорость падает ниже мегабайта в секунду, помечая их для последующего прохода. Это эффективный способ обойти проблемные зоны быстро, не давая диску застрять в коррекции ошибок на каждом подозрительном секторе.
Состояние mapfile можно проверить отдельно, не прерывая основного процесса. Достаточно открыть второй терминал и выполнить:
ddrescuelog -t /mnt/backup/rescue.map
Эта команда выдаёт краткий отчёт по всем категориям блоков - сколько спасено, сколько в каждом из промежуточных статусов, сколько окончательно потеряно. Удобно для оценки ситуации без остановки основной операции. Тех, кому хочется визуализации, выручит утилита ddrescueview - она открывает mapfile и показывает состояние диска в виде цветной карты, где каждая клеточка соответствует области накопителя.
Извлечение файлов из готового образа и работа с повреждённой файловой системой
Когда оба прохода закончены, оригинальный диск нужно сразу отключить. Все дальнейшие манипуляции выполняются только с копией. Это правило кажется очевидным, но именно его нарушение чаще всего приводит к потере того, что ещё можно было спасти. Каждое дополнительное обращение к умирающему диску - это лотерея, в которой выигрыш скромный, а проигрыш катастрофический.
Образ монтируется в режиме только для чтения. Если на исходном диске была единственная партиция, занимающая весь объём, всё просто:
sudo mount -o loop,ro /mnt/backup/disk.img /mnt/recovery
Для полного дискового образа со схемой разделов потребуется указать смещение нужной партиции. Сначала смотрим разметку:
sudo fdisk -l /mnt/backup/disk.img
Допустим, fdisk сообщает, что нужная партиция начинается с сектора 2048. Тогда смещение в байтах будет равно 2048, умноженным на 512:
sudo mount -o loop,ro,offset=$((2048*512)) /mnt/backup/disk.img /mnt/recovery
Смещение в 2048 секторов по 512 байт - стандарт для современных дисков с разметкой GPT и большинства MBR-разметок последнего десятилетия, но если у диска нестандартная разбивка, реальное значение всегда покажет fdisk -l. Для разметки с несколькими партициями удобнее использовать другой подход через инструмент kpartx или losetup, которые автоматически создают устройства для каждого раздела внутри образа:
sudo losetup -f -P --show /mnt/backup/disk.img
После выполнения этой команды появятся виртуальные устройства типа /dev/loop0p1, /dev/loop0p2 и так далее, по одному на каждую партицию, и их можно монтировать как обычные блочные устройства.
Если файловая система повреждена и обычное монтирование не срабатывает, в дело идут TestDisk для восстановления структуры разделов и PhotoRec для извлечения файлов по сигнатурам без опоры на разметку. PhotoRec работает грубо, теряет имена и каталоги, но способен вытащить документы, фотографии и видео из месива, в которое превратилась файловая система. Это последняя линия обороны, когда всё остальное не сработало.
Для повреждённой ext4 разумно сначала сделать копию образа и запускать e2fsck уже на копии копии:
cp /mnt/backup/disk.img /mnt/backup/disk-work.img
sudo e2fsck -y -f -v /mnt/backup/disk-work.img
Так оригинальный битый кусок остаётся нетронутым, а попытки починить файловую систему не уничтожат данные при неудачном раскладе. Тот же принцип действует и для NTFS с её собственными утилитами восстановления - ntfsfix запускается строго на копии, и только после проверки результата можно решать, что делать дальше.
Когда ddrescue упирается в потолок и почему не стоит этого стыдиться
У домашнего восстановления есть пределы. Профессиональное оборудование вроде комплексов DDI или PC-3000 полностью отключает подсистему SMART на время снятия образа, чтобы диск не тратил ресурсы на фоновое логирование и сканирование дефектов, конкурируя с хостом. ddrescue таких возможностей не имеет, и против действительно тяжёлых случаев его инструментария не хватает. Если диск отваливается через минуту после старта, перегревается до отключения или требует холодного перезапуска после каждой ошибки, домашних средств уже мало.
Есть гибридные варианты вроде ddru_ntfsbitmap и ddru_diskdomain - надстройки над ddrescue, которые позволяют сначала вытаскивать только используемые блоки файловой системы, экономя ресурс диска на пустых областях. Эта техника особенно полезна для дисков с большим свободным пространством, где нет смысла тратить часы на чтение неинициализированных секторов. Сначала программа анализирует таблицу bitmap файловой системы, потом передаёт ddrescue список реально занятых блоков, и только их и читает.
Тем не менее в подавляющем большинстве бытовых ситуаций ddrescue справляется. Накопитель с двумя десятками битых секторов, диск после некорректного отключения питания, носитель с подросшим Reallocated Count и медленным чтением - всё это типовые задачи, которые решаются за несколько часов или, в худшем случае, за сутки работы. Опыт показывает, что около 90 процентов случаев потери данных в быту попадают именно в эту категорию.
Главные принципы при работе с ddrescue коротко выглядят так:
- всегда использовать mapfile, даже если кажется, что прогон будет быстрым и единственным;
- никогда не подключать больной диск через USB-карман с агрессивным контроллером, лучше прямое SATA-подключение;
- первый проход без повторов, второй проход с прямым доступом и ограниченным числом ретраев;
- оригинальный носитель отключается сразу после снятия образа и не используется для дальнейших манипуляций;
- все попытки чинить файловую систему делаются на копии образа, а не на нём самом.
Ценность ddrescue не в магии и не в каких-то секретных алгоритмах. Вся её сила в правильно построенной последовательности действий, которая не нагружает умирающий диск сверх необходимого. Утилита не воскресит накопитель и не вернёт его в строй, но шанс забрать данные у неё выше, чем у большинства платных альтернатив. А mapfile, который остаётся после работы, превращает процесс в управляемую процедуру с понятной отчётностью, где видно каждый сектор и его судьбу. Для технически подкованного пользователя это лучший бесплатный инструмент в категории, и знакомство с ним стоит держать в активной памяти ещё до того, как диск начнёт хрустеть и тормозить - тогда в критический момент не придётся изучать матчасть с нуля под давлением утекающего времени.