MAATRIX / Блог / Архив распаковался с ошибкой CRC: что ещё можно вытащить

Архив распаковался с ошибкой CRC: что ещё можно вытащить

MAATRIX

Распаковка архива обрывается сообщением про несовпадение CRC — и первая мысль обычно «всё пропало». На практике это не так: контрольная сумма защищает целостность конкретных данных внутри архива, а не архив целиком, и повреждение одного блока почти никогда не убивает остальные файлы. Ниже — как вытащить максимум из битого zip или tar.gz и как проверить, что вы вообще спасли, прежде чем полагаться на эти файлы.

Что на самом деле означает ошибка CRC

CRC (cyclic redundancy check) — это контрольная сумма, которую упаковщик считает для каждого файла (в zip) или для потока данных (в gzip) при создании архива и записывает рядом с самими данными. При распаковке архиватор пересчитывает CRC заново и сравнивает с сохранённым значением. Не совпало — значит, где-то между записью и чтением данные изменились: один или несколько бит легли не так.

Причины почти всегда одни и те же: обрыв при копировании по нестабильной сети, сбойный сектор на диске-источнике, неполная докачка файла, битая флешка или облачный синк, прерванный на середине. Сам архив мог быть собран идеально — повредился уже готовый файл при передаче или хранении.

Важный момент: CRC — это детектор ошибки, а не корректор. Архиватор не может «догадаться», какими были правильные байты, он только видит, что они не совпадают с ожидаемыми. Поэтому исправить повреждённый блок нельзя (кроме случаев, когда в архиве заранее заложена избыточность, об этом — в разделе про профилактику), а вот прочитать всё остальное — можно, и в большинстве архивов повреждённых записей меньше, чем целых.

Отдельно стоит разделять два разных сценария:

  • Zip-архив хранит каждый файл со своим сжатием и своей CRC независимо. Повреждение одной записи не мешает распаковать остальные — они физически отделены друг от друга внутри контейнера.
  • Tar.gz — это tar-архив (последовательность файлов без сжатия), пропущенный через gzip как единый поток. Здесь всё сложнее: gzip сжимает данные последовательно, и повреждение в середине потока может сделать нечитаемым всё, что идёт после точки повреждения, даже если сами файлы дальше по архиву целые. Файлы до повреждения обычно спасти удаётся полностью.

Это отличие определяет, какую тактику восстановления выбирать дальше.

Первым делом: работайте с копией, а не с оригиналом

Прежде чем запускать что-либо с флагами принудительного извлечения, скопируйте битый архив в отдельное место:

cp povrezhdenny.zip povrezhdenny.zip.orig

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

Если источник — большой файл на медленном или ненадёжном канале (например, докачивался по FTP или через нестабильный VPN), и вы подозреваете, что докачка прервалась, — сначала сверьте размер файла с ожидаемым (если он был указан на сервере-источнике или в сопроводительном файле). Разница в байтах часто объясняет CRC-ошибку куда точнее, чем разбор архива вручную.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать сервер

ZIP: как вытащить файлы, игнорируя ошибку контрольной суммы

Штатный unzip при встрече с CRC-ошибкой не останавливает весь процесс — он сообщает об ошибке для конкретной записи и продолжает с следующими файлами:

unzip -o povrezhdenny.zip -d vosstanovleno/

В выводе увидите что-то вроде:

  inflating: vosstanovleno/otchet.pdf
    caution: filename not matched:  ...
   skipping: vosstanovleno/foto_012.jpg  incorrect data check
  inflating: vosstanovleno/foto_013.jpg

Файлы, для которых CRC не сошлась, будут пропущены (или извлечены частично — зависит от версии unzip и типа повреждения), но остальные распакуются нормально. Код возврата у команды будет ненулевым — это ожидаемо, ориентируйтесь на список в логе, а не на код завершения.

Если нужно вытащить именно повреждённые записи с усилием — попробуйте 7-Zip, он в ряде случаев извлекает больше данных из частично битого потока за счёт другой реализации инфлейта:

7z x povrezhdenny.zip -ovosstanovleno2/ -y

7z тоже сообщит про CRC-ошибки в конце работы списком, но постарается вытащить максимум байт из каждой записи, а не просто пропустить её целиком.

Ещё один рабочий вариант для zip — попытка «починки» самого контейнера штатной утилитой zip (не unzip):

zip -FF povrezhdenny.zip --out popravlenny.zip

-FF — режим агрессивного восстановления структуры архива: zip пытается заново пройти по файлу, найти валидные локальные заголовки записей и пересобрать из них новый архив, отбрасывая то, что не удаётся распознать. Это не чинит повреждённые данные внутри файлов, но иногда спасает архив, который вообще не открывался из-за битого центрального каталога (это отдельная от CRC проблема, но нередко идёт с ней в связке).

TAR и TAR.GZ: свои нюансы восстановления

С обычным несжатым .tar всё похоже на zip: tar при ошибке чтения одной записи может остановиться, но с флагом попытается продолжить:

tar --ignore-failed-read -xvf arhiv.tar -C vosstanovleno/

--ignore-failed-read заставляет tar не прерывать процесс при ошибке чтения конкретного члена архива, а продолжать со следующим. Полезно, если повреждение — это выпавший кусок данных, а не сдвиг всей структуры записей.

С .tar.gz (или .tgz) ситуация сложнее из-за особенности gzip-потока, о которой шла речь выше. Если повреждение находится не в начале файла, часто рабочая стратегия — сначала распаковать gzip отдельно, максимум насколько получится, и только потом разбирать tar:

gzip -dc arhiv.tar.gz > arhiv.tar

Штатный gzip остановится на первой найденной ошибке потока и вернёт ненулевой код, но при этом в arhiv.tar уже будет записано всё, что удалось декодировать до точки обрыва — это не пусто, а частичный результат, и его стоит проверить. Дальше пробуем читать получившийся .tar:

tar --ignore-zeros -tvf arhiv.tar

--ignore-zeros полезен, когда tar натыкается на блок нулевых байт раньше конца потока (обычный признак «конец архива») и в норме прекращает чтение там — эта опция заставляет его читать дальше, если после нулевого блока всё же есть данные.

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

Проверяйте каждый извлечённый файл отдельно

Это шаг, который часто пропускают — а зря. «Файл извлёкся без ошибки» и «файл корректен» — разные утверждения. При принудительном извлечении с игнорированием CRC архиватор может записать на диск файл нужного размера, но с повреждённым содержимым внутри (несколько бит не в тех местах), и не всегда честно сообщит об этом отдельно от общей CRC-ошибки записи.

Практический подход — проверять каждый вытащенный файл его собственным способом:

  • Изображения — открыть просмотрщиком или прогнать через identify (ImageMagick): identify -verbose foto.jpg упадёт с ошибкой на битом JPEG, а не просто покажет искажённую картинку.
  • PDFpdfinfo dokument.pdf (пакет poppler-utils) корректно откроет метаданные только у читаемого файла; для битого выдаст ошибку парсинга.
  • Видеоffprobe -v error video.mp4 покажет ошибки декодирования потока, если они есть, без полного перекодирования.
  • Архивы внутри архива (если у вас zip с вложенным zip или tar.gz) — проверяются рекурсивно тем же способом: unzip -t vlozhenny.zip.
  • Базы SQLitesqlite3 baza.db "PRAGMA integrity_check;" — один из немногих способов быстро понять, что файл базы не просто открылся, а действительно цел структурно.
  • Текстовые и табличные форматы (CSV, JSON, XML) — попытка распарсить штатным парсером языка, на котором вы работаете, или через python3 -c "import json; json.load(open('f.json'))" для JSON.
  • Произвольные бинарники — если у вас есть контрольная сумма файла из независимого источника (список хэшей, приложенный к оригинальной поставке, или копия на другом носителе) — сравните: sha256sum fajl.bin.

Если после проверки часть файлов оказалась битой по содержимому, а не только помечена CRC-ошибкой при распаковке — трезво разделите их на две группы: то, что можно перекачать или пересоздать из другого источника, и то, что было только в этом архиве. Для второй группы дальнейшее восстановление на уровне байтов — это уже не задача архиватора, а задача восстановления данных с повреждённого носителя (если проблема была в диске-источнике) или анализа конкретного формата файла экспертными инструментами — тема отдельного разговора, выходящая за рамки работы с самим архивом.

Профилактика: проверка архива сразу после создания

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

Практика на каждый архив, который вы создаёте для хранения или передачи:

# zip — тест без распаковки на диск
unzip -t arhiv.zip

# gzip / tar.gz — проверка потока
gzip -t arhiv.gz
tar -tzf arhiv.tar.gz > /dev/null && echo OK

# сверка контрольной суммы всего файла архива
sha256sum arhiv.tar.gz > arhiv.tar.gz.sha256

Файл с хэшем стоит хранить отдельно от архива (в другом месте, в другой системе) — тогда после копирования или передачи вы сможете в любой момент сверить sha256sum -c arhiv.tar.gz.sha256 и узнать о повреждении сразу, а не в момент, когда архив понадобился.

Для данных, которые нельзя пересобрать заново (например, единственная копия отснятого материала или итоговый экспорт из системы, которая уже изменилась) имеет смысл закладывать избыточность заранее, а не надеяться на восстановление постфактум. Общеизвестный инструмент для этого — par2 (пакет par2cmdline): он создаёт отдельные файлы восстановления, которые позволяют математически восстановить повреждённые части архива без доступа к оригиналу, если утеряно не слишком много данных. Это не замена бэкапу, а дополнительный уровень защиты для конкретного файла на конкретном носителе.

Но основа — это всё равно нормальная схема резервного копирования, а не спасение отдельных архивов постфактум. Если у вас в принципе нет процесса регулярных бэкапов с проверкой — начните с правила 3-2-1: минимум три копии, на двух разных типах носителей, одна — за пределами основной площадки. И проверяйте не только то, что бэкап создался без ошибок в логе (это не гарантирует его пригодность), а то, что из него реально можно восстановиться — тестовое восстановление хотя бы раз в месяц снимает большую часть рисков, о которых эта статья.

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

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать сервер

Нужны сами нейросети для контента?

Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.

Частые вопросы

Можно ли вообще починить CRC-ошибку, а не просто извлечь то, что уцелело?

Нет, в общем случае нельзя: контрольная сумма только обнаруживает несовпадение, но не содержит информации, достаточной для восстановления исходных байтов. Исключение — если заранее были созданы файлы избыточности (например, через par2) или если у вас есть вторая, целая копия того же архива, откуда можно взять недостающий кусок.

Почему unzip продолжает работать после ошибки, а gzip иногда просто останавливается?

Zip — контейнер с независимыми записями, gzip — последовательный поток. unzip умеет пропускать битую запись и переходить к следующей, потому что они физически разделены. gzip читает поток последовательно и при повреждении середины теряет возможность правильно декодировать то, что идёт после точки повреждения, поэтому решение — сохранить то, что декодировалось до обрыва.

Стоит ли доверять файлам, которые распаковались без единой ошибки CRC?

В подавляющем большинстве случаев да — если CRC всех записей сошлась, это сильный сигнал целостности. Но для критичных данных дополнительная проверка форматом (PDF, база, изображение) всё равно не помешает: CRC защищает от случайного повреждения байтов, но не от логических проблем в самом файле, которые существовали ещё до архивации.

Есть ли смысл пытаться распаковать один и тот же битый архив несколькими инструментами подряд?

Да, и это не превышение усилий, а разумная практика: unzip, 7z и другие реализации по-разному обрабатывают частично повреждённые данные, и один инструмент иногда вытаскивает из той же записи больше байт, чем другой. Сравните результаты по размеру и, если формат позволяет, визуально или через проверку целостности файла.

Что делать, если битый архив — это единственная копия важных данных, а восстановить не получается?

Прекратите эксперименты на исходном носителе (диск, флешка), сделайте его посекторный образ, если подозреваете аппаратную причину, и дальше работайте только с копией образа. Дальнейшее восстановление байтов из повреждённого носителя — это уже не про архиватор, а про восстановление данных как таковое, и на этом этапе разумнее привлекать профильных специалистов, чем перебирать флаги команд.

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →