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

Основано на реальных событиях (обожаю этот жанр кино!)

Учитывая просто отвратительную надёжность современных HDD, статья описывает ставшую уже тривиальной борьбу с последствиями выхода HDD из строя.

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

Кому интересен ответ только на главный вопрос, можно сразу перейти к практике использования программы precizer.

Выделенный жирным текст можно читать отдельным слоем и получить краткое представление о затронутых темах.

А тем временем…

В «кино» снимались

Аппаратная составляющая. Как всё организовано

Общая схема Disaster Recovery Center домашнего масштаба
Общая схема Disaster Recovery Center домашнего масштаба

Железо дома

Компактная машинка Dell OptiPlex XE2 SFF, размером с видеомагнитофон конца эпохи (да, я видел настоящих динозавров и вот такое тоже...). На борту LibreBoot в компании с Gentoo (это вообще тема для отдельной статьи). Этот PC выполняет роль одновременно кинотеатра и домашнего сервера с одним ёмким 3.5" HDD и NVME под систему. Железка была куплена по цене одного похода в кафетерий. Выпущена 13 лет назад и поставлялась в девственно новом состоянии и с полной комплектацией: фирменной клавой, мышкой и слюнявчиком для офисного планктона. Небольшой апгрейд CPU на самый крутой того же поколения i7-4790K, скромная, но современная видеокарта AMD RX 6400 и 32Gb памяти превратили заурядное старьё в образчик комфорта со всеми преимуществами современных технологий: теперь можно подключить многоканальную звуковую систему вместе с телевизором по HDMI и отдавать декодирование видео 4K на попечение видеокарты.

Dell OptiPlex XE2 SFF
Dell OptiPlex XE2 SFF

Почти тот же видеомагнитофон, но с чуть лучшим звуком и бо́льшим разрешением. Вся прелесть аппаратного решения начала особенно радовать после замены штатных кулеров на почти бесшумные Noctua, благодаря чему сам компьютер перестал быть слышным даже во время просмотра фильма «Тихое место». Общая производительность неожиданно приятно удивила. Бенчмарки показали суммарную разницу по баллам всего в 23% с рядом торчащим лептопом i7 12 поколения, используемым для работы, а производительность каждого ядра индивидуально оказалась хоть и ниже, но совсем незначительно. Лишнее подтверждение, что закон Мура вовсе не закон и давно не работает. Зацените разницу — 4 поколение против 12! Вот так прогресс за 13 лет! (ну да, ну да... полноценный проц против ноутбучного, и размер в попугаях. мгу-у-у.. оке-е-ей..)

Железо на удалённой стороне

Raspberry Pi 5 16gb с переходником USB 3.1 на 3.5 HDD и штатной ОС с закосом под Debian. Переходник копеечный, но обеспечивает скорость обмена данными выше возможностей SATA HDD дисков, что полностью покрывает потребность. Единственный нюанс — для 3.5" дисков нужен отдельный блок питания (включается в сам USB-SATA переходник).

Raspberry Pi 5 в алюминиевом корпусе пассивного охлаждения
Raspberry Pi 5 в алюминиевом корпусе пассивного охлаждения

Изначально Raspberry покупалась для мультимедийных нужд и малинка вполне могла бы стать полноценным 4K видеоцентром, если бы хватило терпения в борьбе с допиливанием Debian до требований по безопасности и заработал бы многоканальный звук. Но нет, терпения не хватило после месяца ежедневных страданий стараний именно над звуком. На последних волевых были предприняты попытки поставить фаворитную ОС Gentoo в которой всё работает, но и там меня тоже поджидало разочарование в виде сложностей адаптации вшитой U‑Boot, файловой системы и загрузки Gentoo с microSD: в один прекрасный момент операционка переставала грузиться; чёрный экран и ни слова пояснений. После чего попытки приспособить малинку были признаны провальными и поэтому был куплен полноценный PC с нормальным процом, выбором по BIOS и полным спектром доступных операционных систем под архитектуру x86-64. А тем временем…

В процессе поиска решений была исследована система LibreELEC (bare-metal Kodi) и откровенно приятно удивила своей завершённостью программно-аппаратного комплекса. Как у профессионала у меня завышенные требования к функционалу домашнего сервера и поэтому для моих нужд LibreELEC оказался слишком ограниченным и негибким в плане расширения (там нет пакетов, каждый индивидуально вкомпиливается в образ из специально пропатченных многотонажными патчами сорцов! Бррр!). Но если нужен просто хороший мультимедийный центр только для музыки и кино на малинке, то решение определённо очень, очень привлекательное и работает даже с полной поддержкой многоканальности поверх HDMI искаропки! (смотреть в сторону проброса raw потока поверх stereo 2.0 в ALSA; ну да, забористо... но работает же!)

В результате всех мытарствований Raspberry Pi нашёл своё место как backup-сервер: потребление Ватт железкой сопоставимо с потреблением самого HDD диска; компактный размер — в алюминиевом корпусе с пассивным охлаждением точно повторяет размер пачки сигарет, бесшумный. Прекрасно справляется с каскадной шифрацией/дешифрацией разными алгоритмами в режиме реального времени (veracrypt) без деградации производительности для HDD. Другими словами — процессор шифрует поток данных быстрее, чем диск может его читать/писать (узкое место тут скорее сама физическая основа диска). Даже поддерживает аппаратное ускорение для целого ряда популярных алгоритмов (увы, для этого придётся потратить много времени для переконфигурирования ядра, оно старательно покоцано самими разработчиками малинки). Несомненно, Raspberry Pi 5 — крайне интересное решение и может гораздо больше, но сейчас играет роль третьего плана, только как backup-сервер. А тем временем…

Возникает логичный вопрос: почему просто не поставить два диска и не связать их в RAID1, зазеркалив данные без вот этого всего лишнего железного хлама, который нужно купить, настроить и потом ещё и обеспечить интернетом, удалённым доступом и бесперебойным питанием? Отвечаю кратко и по-делу: это не просто система резервирования или бэкапирования. Это полноценный Disaster Recovery Center домашнего масштаба со 100% доступностью данных без дополнительных телодвижений по их восстановлению из архивов или backup-бэкэндов. С одной локацией может случиться разное: ограбление, пожар, затопление или банальное упало-разбилось. Зеркальный рейд не спасает ни от одной из этих неприятностей, увы, не таких уж и редких. С DRC данные доступны сразу = подключился и получил. Например просто смонтировав шару с любой точки мира по sshfs и мгновенно получив доступ ко всему содержимому диска. Удобно! И к удобному быстро привыкаешь!

Синхронизация между дисками основного сервера и backup организована через rsync поверх ssh. Является ли это узким местом в безопасности? С учётом ограниченных возможностей по выбору алгоритмов (отсутствие каскадной шифрации, например) и критических дыр в безопасности ssh однозначно является узким местом, но не больше, чем проприетарные прошивки неизвестного происхождения на всех hardware компонентах, участвующих в каждом из этапов хранения и передачи данных. Не забывайте также про свои маршрутизаторы с китайскими, плохо скрытыми бэкдорами на каждом шагу. Определённо, пустить трафик хотя бы через OpenVPN было бы ещё более разумной идеей, но это планы на будущее.

Способ хранения бэкапов: периодическая синхронизация, копия 1-в-1 с учётом фильтров ненужного. Обе программы: и rsync, и precizer умеют гибко управлять фильтрами, выбирая что можно проигнорировать, а что — нет.

Я не люблю всё усложнять! (ага... Именно поэтому предпочитаю Gentoo и LibreBoot, ха-ха!) За годы админства с меня хватило и ленточных накопителей с их обманчивой надёжностью, и извращённого кекса с Bacula (его конфигами, процедурами восстановления с помощью консольных команд и отсутствием ГУЯ здорового человека). Однажды я себе так и сказал: «KISS! Хватит кошмара с дедупликацией и ротацией резервных копий ради экономии килобайт на петабайтных SAN-хранилищах!» Там где действительно нужна история и необходимость отката — точечно использовать git и синхронизировать копию в бэкап-таргет, а не разводить зоопарк снапшотов с ZFSами! Поэтому после десятилетий экспериментов прижилась именно такая схема: диск тут, диск там. Между ними rsync через интернет. Синхронизация по крону: скрипт в пяток строк с повтором при сбое и оповещением в случае фэйла. Всё! Ну а если масштабировать до уровня предприятия с Disaster Recovery, то SAN тут, SAN там; между ними оптика — всё просто! (ну да, ну да, всё именно так, только ещё плюс пару лет на настройку, интеграцию и пару киловатт в час для питания)

А тем временем…

Проблема возникла внезапно и на ровном месте. Жил себе не тужил большой, прекрасный HDD диск Toshiba MG06ACA10TE 10Tb и одним замечательным, солнечным воскресным утром шторы были наглухо закрыты от палящего назойливого солнца. Но сделано это было исключительно ради просмотра очередной серии долгожданного и поэтому заранее скачанного сериальчика и... И Ни! Че! Го! хорошего... Шторы пришлось открыть, просмотр отменить, а диск подвергнуть тщательному исследованию. Вроде как жив диск, а вроде и не совсем… Точно так же и с настроением, которое было окончательно испорчено. Некоторые файлы читались без проблем, но на других диск входил в ступор и переставал отвечать при вращающемся шпинделе. Перемонтирование - опять работает на некоторых файлах и виснет на других. S.M.A.R.T. и dmesg чуть прояснили картину и стало очевидным, что диск скорее мёртв, чем жив — многие секторы просто перестали быть доступными. Это стало понятным по пугающе растущим счётчикам в нескольких критических метриках сразу:

Current_Pending_Sector
Reallocated_Sector_Ct
Command_Timeout

В моменты «подвисаний» диск несколько раз пытается перепрочесть и релоцировать проблемные секторы, но в большинстве случаев это заканчивается ничем.

Заказ нового диска и томительное ожидание доставки стали венцом мучительного выбора производителя и модели. Теперь это Seagate ST28000NM000C-3WM103 25TB. Прошлая Тошиба выбиралась исходя из критериев предельно возможной надёжности и долговечности (исследования статистики имели место быть) ну и конечно — максимально доступной ёмкости среди представленных на рынке безгелиевых дисков тех времён. Согласно рекомендациям опытных и бывалых оба диска были идентичной модели, но из разных партий. Так получилось, что даже версии прошивок были разными. Цель была предельно простой — емкость 1-в-1 для периодических синхронизаций одного диска на другой. Но увы... По факту из двух купленных тогда железок одна проработала меньше двух лет, вторая жива по сей день. Да, это не дешёвое удовольствие, но восстановление ценных данных гораздо, ГОРАЗДО дороже! А иногда просто невозможно физически.

Облачные сервисы для бэкапов мной никогда не рассматривались всерьёз по целому ряду причин:

  • Скорость доступа

  • Нулевое доверие к третьей стороне. Небезосновательно!

  • 1984

  • НЕнулевая вероятность взлома аккаунта и похищения личной информации (прецедентов — масса)

  • Учётка может быть заблокирована внезапно и просто так, по чьей-то прихоти или звёзды так сложились. Прецедентов безвозвратной потери доступа — сотни тысяч.

  • И конечно ключевой — цена. Несложный расчёт покажет, что дешевле свои два диска с синхронизацией, чем хранить эквивалентный объём в облаке и рано или поздно заиметь вышеперечисленные последствия.

  • Наконец-то отключат Интернет, а мы — уставшие!

Откуда обоснованное недоверие к третьей стороне? Хотя бы оттуда, что нет ни одного сервиса, обеспечивающего каскадное шифрование на стороне клиента открытым ПО, прошедшим сторонний аудит. Что уже говорить про использование post-quantum алгоритмов… Помню, какой-то из провайдеров громко пукнул на весь интернет о бета-версии подобной опенсорсной софтины. Готовый бинарник 500 мегабайт. ШТА?! Сходил за исходниками. Открыл. Код на JavaScript и запускается как браузерное приложение в каком-то движке, который нужно отдельно тянуть как блоб с их сайта (ну кто бы мог сомневаться!). Закрыл. Удалил навсегда. Остальной рекламный пердёж улетал фтопку настолько быстро, что даже название той шарашкиной конторы вспомнить уже не представляется возможным. Думаю, не только у меня воспоминаний об этом эксперименте не осталось. Что в результате? А воз и ныне там — все SaaS нагибаются регуляторами и ни одно нормальное(?) правительство не позволит такой роскоши, как подкрепить защиту конституционных прав граждан реальными действиями в ущерб шпионажу.

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

А тем временем…

При покупке нового диска выбора безгелиевых вариантов больше не осталось. Совсем! Они просто перестали продаваться. В результате пришлось скрипя зубами смириться с полной недоступностью понятия «долговечность» даже в теории и что диск покупается максимум на три года, при этом надо быть готовым, что даже через 2 года всё, что на нём может храниться одномоментно может перестать быть доступным раз и навсегда (есть такая особенность у гелиевых). В этот раз даже не было смысла исследовать статистику выхода дисков из строя — срок эксплуатации и так минимален и окирпичивание гарантировано производителем. На заведомо лживые маркетинговые посылы про 5 «гарантированных» лет даже не хотелось обращать внимания. Молекулы гелия настолько малы, что быстрая диффузия газа через металл корпуса диска (вот уж где действительно гарантированно) сыграет свою роль скорее рано, чем поздно. По сравнению с негелиевыми дисками диффузия это вопрос времени и никакие громкие заявления гнилых корпорастских маркетологов законы физики не отменят. С негелиевыми дисками (особенно с теми, где НЕ используется лазер для прогрева поверхности) ещё был шанс, что диск может прожить так долго, что столько даже и не нужно. Но в современных дисках как будто специально выбирают такие технологии, с заранее заложенным сроком эксплуатации, которые предполагают быстрый износ и деградацию материала носителя (прогрев лазером и улетучивающийся гелий). Простая аналогия — достаточно вспомнить шарики на детских праздниках и как быстро они перестают летать. Ведь они не сдуваются на самом деле, это гелий просачивается между молекулами материала и улетучивается! Но всё это — техническая лирика. А тем временем…

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

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

С опцией -n — сначала считываем всё, не повторяя плохие сектора, чтобы быстро получить максимум данных и карту

ddrescue -f -n /dev/sdX /path/to/imagefile.img /path/to/mapfile.map

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

ddrescue -d -r3 /dev/sdX /path/to/imagefile.img /path/to/mapfile.map

mapfile.map это просто текстовый файл с номерами секторов бэдблоков. При просмотре можно увидеть диапазоны в каком-то внутреннем адресном пространстве. Если удалось прочесть за несколько попыток, то бэдблок убирается из «карты». Очевидно, что файл карты нужно размещать где угодно, но не на проблемном диске, с которого идёт копирование.

В опциях запуска всё предельно понятно, но может смутить только /path/to/imagefile.img Да, это именно файл-образ, файл-дамп исходного диска, как его делает dd (в названии есть dd помните?) Размер образа будет равен размеру исходного диска. Место бэдблоков в файле-образе заливается нулями. Если удаётся считать бэдблок при повторных запусках ddrescue, то те нули переписываются реальными данными. Таким образом проход за проходом количество несчитываемых бэдблоков уменьшается и файл-образ заполняется данными всё больше и больше. Это если исходный проблемный диск это позволяет. Я долго играл с опциями, уменьшал скорость считывания, увеличивал попытки перечитываний бэдблоков и это в конце концов дало свой положительный эффект!

У программы ddrescue море опций чтобы помочь достичь цели и считать данные с проблемного диска. Ими можно и нужно смело экспериментировать!

Например, диск может выдавать данные из проблемных секторов охотнее при уменьшении скорости чтения, поэтому можно попытаться ограничить максимальную скорость параметром:

--max-read-rate=2M

Это не уменьшит скорость шпинделя, но действительно может быть полезным когда диск входит в ступор на штатных скоростях считывания. Однозначно, этот параметр — прекрасный повод поэкспериментировать!

Если диск очень плохой, можно использовать ключ:

--no-scrape

чтобы ddrescue не пытался слишком долго ковырять мелкие плохие блоки.

Если диск уходит в «залипание» от больших диапазонов чтения, можно уменьшить считываемый блок:

--cluster-size=64

Чем мой случай уникален и почему было потрачено столько сил для восстановления данных со старого носителя на новый? Объясняется всё просто! Как известно, люди делятся на два типа. Те, кто уже делает бэкапы, и те, кто по наивности верит в «авось» и автосейв, а потом узнаёт цену потерянных семейных фотоархивов, исходников программ, биткоинов, утерянных библиотек избранной литературы и вообще всей оцифрованной жизни за несколько десятилетий. Учитывая мой богатый админский опыт, наивность уже давно позади и бэкапы есть. Но! Они находятся от меня ровно на расстоянии половины планеты, со скоростью доступа 2,5 мебибайта в секунду максимум. Учитывая объём, копирование могло бы занять полтора месяца в идеальном случае, увы недостижимом из-за падений скорости порой до 0,5 в часы пик, к тому же повторяющийся несколько раз в разных частях Земного шара. Стыдно признавать, но был ещё момент — оригинал и копия отставали друг от друга больше чем на месяц (ну конечно не из-за лени починить скриптик, а исключительно из-за технических нюансов, хе хе!).

Поэтому использование ddrescue оказалось хорошей идеей и всего за неделю я получил 9 терабайт, восстановленных из 10 (исходный диск к моменту сбоя был почти полностью забит, поэтому это почти 9Тб полезной нагрузки). Один терабайт остался в нечитаемых бэдблоках. И никакие ухищрения с настройками опций ddrescue больше не помогали вытащить ни байта. Финальный размер imagefile.img при этом составил 9 тебибайт. Ну и ладно! Уже неплохо — есть с чем работать!

Монтируем файл образа как обычный диск:

sudo losetup -Pf --show /path/to/imagefile.img

Получим что-то вроде /dev/loop0

После этого смотрим разделы:

lsblk /dev/loop0

Например, появятся:

/dev/loop0p1
/dev/loop0p2

Монтируем нужный раздел:

sudo mkdir -p /mnt/img
sudo mount /dev/loop0p1 /mnt/img

Размонтирование и отключение:

sudo umount /mnt/img
sudo losetup -d /dev/loop0

Хорошо, ddrescue отработал, восстановлено что было возможно. И что дальше? Вот тут надо разъяснить, что ddrescue работает на уровне блоков — он не знает и не проверяет файловую систему. Там где не удалось считать кусок файла программа просто вставит нули. В том месте, где хранилась метаинформация о размещении файлов и приключился бэдблок — будет потеряна информация о размещении файлов. Простая аналогия — письмо и дырокол. В письме ссылки на книги, страницы и строки, формирующие оригинальный текст. Дырокол может в произвольных местах оставить дыры в письме. Если дыра попала на название книги, то можно попытаться понять, что это было и тем самым восстановить ссылку на кусок оригинального текста. Если дырокол чпокнет по номеру страницы или строки — то всё, целый блок текста из ссылки окончательно утерян и восстановлению не подлежит. Так же и с файловой системой. Мой случай это EXT4. Она размазывает информацию о ветках древовидной файловой структуры по всему пространству (многократно резервируя). Какие последствия это за собой несёт? Потерю метаинформации о размещении файлов! Даже если удалось считать блок байт, составляющих полный объём файла, то не факт, что удастся восстановить метаинформацию о принадлежности этого блока байт к имени файла, файла к директории, этой директории к её материнской директории и так далее по цепочке. На самом деле это очень, очень грустно! Грустно потому, что после запуска fsck оказалось, что однозначно восстановить все первоначальные связи удалось только для 70% от тех 90% секторов. Всё остальное — мешанина из разных кусков файлов в директории lost+found. Итог не впечатляет. Больше недели трудов и восстановлено только 63% от изначального объёма файлов.

И-и-и… н-н-нет! Это ещё не все проблемы! Потому что неизвестно, сколько из восстановленных 63% файлов не содержат нулей вместо реальных данных в тех местах, где на диске были бэдблоки. А также fsck при исправлении ошибок файловой системы мог просто оторвать кусок файла прикинув, что и так сойдёт, а без остального можно и обойтись — просто размер поменяется. Получается то, что на восстановленном образе существуют файлы с нулями вместо реальных данных и не существует абсолютно никакой возможности понять, в каких файлах целостность не была нарушена, а какие файлы содержат замещённые нулями блоки данных!!! Почему так? Потому, что большинство файловых систем не считает и не хранит контрольных сумм! Именно поэтому невозможно понять, файл поломан или он действительно в некоторых своих местах содержит нули совершенно легитимно. Контрольные суммы это значительные накладные расходы и по CPU и по занимаемому пространству. Если Вы счастливый обладатель другой операционной системы, то не обольщайтесь — Ваша FS тоже не поддерживает контрольные суммы, благодаря которым можно было бы дать однозначный ответ: файл поломан или нет. Увы… имеем что имеем! Исключения есть и это парочка перегруженных фичами файловых систем, так «любимых» за сложность их настройки, использования, тормознутость, требовательность к ресурсам и баги (такие монстры как *ZFS, Btrfs, ReFS). Но смогут ли они помочь в восстановлении файлов, или борьбе с теми проблемами, которые возникли в результате выхода HDD из строя? Забавно, но нет! Контрольные суммы не содержат данных и не помогут восстановлению пропавшей информации (не путать с кодами коррекции ошибок в RAID) они служат только единственной задаче, ответить на вопрос: файл в полном порядке или целостность нарушена. К тому же, контрольные суммы где-то хранятся (правильно, на битом HDD) и могут попасть точно в такие же самые места, пробитые «дыроколом» и точно так же потеряться как и остальная метаинформация о целых директориях с файлами. Именно потому, что преимущества не очевидны, а накладные расходы огромны, контрольные суммы не используются в большинстве ФС, даже для проверки целостности метаданных, не то что для проверки целостности данных внутри файлов.

Надо обратить внимание, что весь процесс восстановления, синхронизации вовсе не был трудозатратным. Только неудобство: запустить команду и очень долго ждать завершения приходилось из-за объёмов и более чем скромных скоростей HDD дисков по сравнению с Solid State альтернативами.

А тем временем…

Пора́ сделать следующий шаг и синхронизировать недостающие данные с бэкапного диска. Проверенное временем и оптимальное средство для поставленной задачи это rsync. Тот же rsync с помощью которого синхронизировались файлы с основного на бэкапный, с его помощью будет и обратная операция. Смело запускаем:

rsync -aHAX --delete-after --progress --stats --partial --append-verify --ignore-times -e 'ssh -T -o Compression=no -o Ciphers=aes128-gcm@openssh.com,aes128-ctr -o MACs=umac-128@openssh.com,hmac-sha2-256' --exclude software/install/linux/os/ --exclude 'movie/tv series/' remote_user@remote-backup-host.com:/backup/ /destination_folder_on_the_new_HDD/

Всего неделя синхронизации и картина при повторном запуске rsync выглядит вообще очень мило и обнадёживающе:

Number of created files: 0
Number of deleted files: 0
Number of regular files transferred: 0
Total transferred file size: 0 bytes
Literal data: 0 bytes
Matched data: 0 bytes
File list size: 0
File list transfer time: 0,000 seconds

Таким образом rsync сообщает, что все файлы идентичны и там и тут.

Прекрасно, да? За одним ма-а-а-леньким исключением: 100% идентичность источника и целевого диска ЭТО АБСОЛЮТНАЯ ЛОЖЬ!

Каким образом так могло получиться, что синхронизация добавила наши недостающие 37% с удалённого диска и ввела в полное заблуждение что в изначальных 63 процентах файлов (которые были восстановлены напрямую со старого диска) полный и абсолютный порядок? Очень просто — rsync сверяет путь и метаданные файлов (размер файла st_size и время последней модификации mtime) и на основании только этих трёх метрик принимает решение, идентичен файл или его нужно пересинхронизировать. Всё выглядит логично, но не для текущей ситуации, когда нужно сверять файлы байт-в-байт и только тогда принимать решение о полном соответствии или замене. Хорошо, для rsync и это не проблема, а вполне решаемая задача. С опцией -c/--checksum rsync рассчитывает контрольные суммы для каждого файла на обеих сторонах и при несовпадении действительно очень интеллектуально выбирает алгоритм и синхронизирует файл по частям (разбивает на чанки, сверяет контрольную сумму каждого чанка и синхронизирует только ту часть, CRC которой не совпала). Вроде всё идёт медленно, но уверенно. Но проходит несколько дней и процесс останавливается полностью. Что произошло? Банальный разрыв связи? Запускаем заново и… Что? Rsync весь расчёт контрольных сумм начал с самого начала? А почему не сохранить промежуточный результат между сессиями? Нет, не поддерживается? Ладно... бывает… Задача оказалась решаемой, но не в масштабе терабайтных объёмов и продолжающихся сеансов. Может есть альтернативы rsync? Да, есть, но буквально все — участники парада уродов: одна программа борется по убогости с другой и все стремятся занять первое место в конкурсе на самое отвратительное решение сделанное через ж.

А тем временем, решение нашлось! Пусть и не замена синхронизации, но альтернативный путь. И это — программа precizer

До появления этой программы в моей админской жизни была идея самостоятельно написать скрипты для хеширования и сравнения контрольных сумм стандартными системными инструментами. Но процесс обещал превратиться в бесконечный ад. Поэтому появился серьёзный повод найти радикально новый подход для поставленной задачи. Перебрав несколько инструментов (каждый со своими странностями и заморочками) я выбрал один наиболее простой и достаточно фичастый, как золотую середину между функциональностью и затраченным временем чтобы разобраться как именно им воспользоваться. Программа precizer позволяет создавать один файл со слепком всех контрольных сумм указанной директории и всеми поддиректориями. Укажем весь диск и поехали. У программы есть подготовленные исполняемые портируемые сборки как под x86-64 архитектуру, так и под arm64. Это именно то, что нужно для запуска на обеих машинах (под Gentoo, и на Raspberry Pi). Как скачать и запустить программу есть инструкция на несколько строк в README сайта.

Скачиваем и запускаем независимо на обеих машинах в tmux терминале:

# На первой машине:
./precizer /backup/

# На второй:
 ./precizer /destination_folder_on_the_new_HDD/

Это минимально необходимый набор действий. Да, вот так просто!

В результате на каждой из машин появится свой файл с базой данных контрольных сумм. По умолчанию имя файла будет совпадать с именем хоста:

# На первой машине:
first_hostname.db

# На второй:
second_hostname.db

Да, это долгий процесс сам по себе. Для расчёта контрольных сумм нужно считать каждый байт из всех 10Tb.

В случае необходимости можно прерывать процесс сколько угодно раз — с файлом базы данных ничего не случится и процесс можно продолжить с прошлого места, просто добавив опцию -u/--update чтобы сообщить программе продолжить начатое, а не запускать всё заново (согласно мануалу этот флаг сделан для защиты от случайной модификации БД):

# На первой машине:
./precizer -u /backup/

# На второй:
 ./precizer -u /destination_folder_on_the_new_HDD/

А тем временем…

Всего за неделю был завершён расчёт контрольных сумм как на стороне backup сервера, так и на стороне домашнего компьютера. Каждый байт был считан с диска и стал частью контрольной суммы, записанной в файле БД. Программа очень лояльна к разрывам и прерыванию процесса. Причём продолжит расчёт контрольных сумм ровно с того места в файле, где была прервана. Даже если это была половина 150 гигабайтового файла, то precizer не станет рассчитывать его с самого начала, а продолжит с места разрыва. Это если прервать через Ctrl+C или сигналом преднамеренного прерывания. То же самое относится ко всей файловой системе. Если уже есть база данных, то для записанных в неё файлов контрольные суммы не будут рассчитываться заново. При прерывании программа достаточно быстро доходит до точки файловой системы где была остановлена и продолжит расчёт с неё. Очень крутые фишки как по-моему!

В результате получились два .db файла с именами хостов. Каждый .db файл размером около 500 мегабайт (ого, да?! Сам не ожидал) В программе используется алгоритм SHA-512, а это 512 бит (64 байта) на один файл + путь к файлу с его именем + метаинформация. Миллион, двести тысяч файлов.

После копирования обоих файлов БД на одну из машин начинается самое интересное — можно наконец-то увидеть реальную разницу между ФС дисков. Для этого есть опция -c/--compare

./precizer -c first_hostname.db second_hostname.db

Если за эталон взять состояние на backup-машине, все те файлы, контрольные суммы которых не совпадают на новом диске нужно удалить. Для этого я взял список файлов предоставленный precizer, скопировал в текстовый файл и добавил цикл с rm, превратив его в скрипт.

После удаления «битых» файлов и повторной синхронизации rsync в финале ещё раз был использован precizer, чтобы наверняка убедиться в 100% идентичности копии. На надёжность алгоритма SHA-512 действительно можно положиться и если обе контрольные суммы совпадают, то можно быть уверенным, что файлы абсолютно идентичны.

По сравнению с rsync программа precizer сущий младенец, которому не более пары лет. Однако нельзя сказать, что программа сырая. Богатая документация и заявленное покрытие кода тестами вызывают определённое уважение, а автоматизация сборки дарит скромную надежду на стабильность работы и отсутствие грубых ошибок, свойственных новоделу.

Что понравилось в программе

Конечно мне понравился результат! Удалось чётко понять какие файлы после восстановления и последующей синхронизации оказались с «дырками» или просто подрезанными несмотря на то, что согласно FS-метаинформации данные должны быть в полном порядке. Таких файлов оказалось около сотни тысяч из общего количества более чем в миллион. Очевидно, что без precizer, вручную, мне бы просто физически не удалось бы удостовериться, что домашний диск после восстановления данных байт-в-байт идентичен эталонному на backup-сервере. Теперь, со времён инцидента, я постепенно внедряю precizer во все этапы бэкапирований. Не только в процессе восстановления, но и после синхронизации на удалённый сервер важно быть уверенным, что в бэкапе точная копия оригинала. Пока не всё автоматизировано но я к этому стремлюсь.

Скорость. Я для интереса померял как быстро считает контрольные суммы штатная системная утилита sha512sum и сравнил с precizer. Результат оказался один в один и по факту упирается в аппаратную производительность самого диска. Что интересно, та же штатная sha256sum работает помедленнее. Поэтому можно сделать вывод, что выбор алгоритма был оптимальным, хотя странно, что алгоритм только один и без выбора вариантов. Ну да это и не великая проблема — свою задачу программа выполняет. Ради интереса я также проверял совпадают ли SHA-512, созданный системной утилитой sha512sum с тем хешем, который генерирует precizer и сохраняет в БД. Ожидаемо да, совпадает.

Документация на русском языке. Удобно. Для меня время имеет значение, и на русском чтение и усваивание информации происходит раза в четыре быстрее, чем на остальных из всех трёх известных мне языков.

Что НЕ понравилось или хотелось, чтобы работало по-другому

Отсутствие прогрессбара в стиле копирования у Midnight Commander с общим прогрессом, прогрессом расчёта контрольной суммы каждого файла, средней скоростью, планируемым временем завершения. Есть малоинформативная опция --progress, но от неё мало толку. Она делает первый прогон по всему дереву файлов и выводит общую статистику: занимаемое место, количество файлов, директорий и что-то ещё по-мелочи.

Очередь вывода на экран. Так как нет прогрессбара, то невозможно понять, что происходит в текущий момент. Когда программа работает над очень большим файлом этого просто не видно. Строка о том, что файл обсчитан и добавлен в БД появляется только ПОСЛЕ расчёта контрольной суммы, а между началом этого процесса и появлением строки складывается ощущение, что программа зависла, потому что ничего не происходит и видна история только уже обработанных файлов.

Я немного поэкспериментировал с программой, примеряя её для гораздо более широкого использования, чем просто в домашних условиях и вот что заметил. Если прерывать программу штатными средствами (преднамеренное прерывание через Ctrl+C или kill -15) то действительно, данные с не до конца рассчитанным файлом сохраняются в БД. Но если использовать системный kill -9, когда само ядро бескомпромиссно отстреливает процесс, тогда нет, данные в БД не попадают даже при очень длительной работе над огромным файлом. Хотя в программе заявляется полная толерантность к сбоям, но ситуация с вырубанием питания при обсчёте большого файла не обрабатывается. Нужно отметить, что все те файлы, контрольные суммы которых уже обсчитаны и попали в базу данных, там и останутся несмотря на внезапный ребут. При повторном запуске расчёт контрольных сумм действительно не будет начат с самого начала, а продолжен только для необсчитанных файлов.

Многопоточность. Её просто нет. Заявленная суперпроизводительность упирается в один поток на одном ядре для всех дисковых операций. Для домашних нужд очевидно, большего и не надо, особенно с HDD, для которых параллельное чтение является злом во плоти. Но hero-текст на сайте заявляет поддержку от embedded до кластерных-супер-пупер-решений. Несмотря на громкие заявления пока эта фича остаётся только в roadmap (вернее, две фичи разных видов распараллеливания). С другой стороны многопоточности нет даже у rsync, которому сто лет в обед. Нет там её даже в планах.

README явно перенасыщен информацией на все случаи жизни. Хотя стоит признать, что приведённые живые примеры это действительно удобно, такое редко где можно найти в документации на опенсорсное ПО, где в лучшем случае можно бесконечно читать описание бесконечных опций man страницы так и не поняв как их применить вместе (rsync тому пример)! Хотя… может это на самом деле преимущество, а не недостаток! Ведь можно скинуть ссылку на Readme предпочитаемому AI и вообще не читая документацию сразу получить совершенно адекватные ответы на любые вопросы и настройки опций для запуска. Я так и делал. Мега удобно!

Буду рад ответить на вопросы в коментариях. Всем успехов в IT делах!

Всем спасибо за внимание!
Всем спасибо за внимание!

Комментарии (16)


  1. Olegun
    13.06.2026 14:38

    Сообщите пожалуйста точную модель HDD, которая выбрана для бекапа.


    1. Caefah Автор
      13.06.2026 14:38

      Toshiba MG06ACA10TE 10Tb был заменён на Seagate ST28000NM000C-3WM103 25TB Добавлю, пожалуй, эти данные в статью, чтобы расставить все точки над «ё».


  1. yursdan
    13.06.2026 14:38

    Захватывающая история бэкапа )

    Для простых случаев сравнения в bash использую:

    alias rs='find . -type f -exec sha256sum -b \{\} \;'
    использование под сравнение:
    rs | sort > sums1..N
    и сравнение:
    diff sums1 sums2

    Для сложных случаев есть свой собственный велосипед с квадратными колёсами на Джаве -там суммы считаются/проверяются во все потоки, которые даёт проц и всё упирается в производительность SSD/HDD.

    Кстати, есть старый диск WD Green 800GB у которого через несколько лет эксплуатации появились бэд-блоки в начале диска. После вычисления "битого" диапазона, сделал раздел, начинающийся после оного. С тех пор уже 10 лет работает холодным бэкапом одного из "хранилищ" с периодическим (раз-два в месяц) дополнением и проверкой контрольных сумм.

    Сейчас подыскиваю диски для долгосрочного хранения важной информации (4-6 ТБ) и кучи не особо важной всячины (где-то 15-20 ТБ). Сомневаюсь насчёт гелия. Но других вариантов особо не наблюдается.


    1. Caefah Автор
      13.06.2026 14:38

      find . -type f -exec sha256sum

      Моё личное наблюдение — sha512sum работает быстрее, чем sha256sum

      К предложенной схеме с find/rs/sort/diff есть несколько вопросов:

      1. Если мне хочется проигнорировать директорию с сериалами, которые я вообще не бэкапирую и которые занимают половину диска? А если список для игнорирования состоит из трёх десятков пунктов? Лично в моём случае так и есть для rsync — передаю их параметрами в скрипте резервирования.

      2. Что если мне нужно продолжить с прерванного места?

      3. Что в плане обновлений через месяц, например, чтобы актуализировать все изменения после бэкапа? Перерасчёт с нуля всех 25Tb?

      Вопросы не праздные — я в них упёрся в тот момент, когда сам продумывал решение и хотел нагородить проверку контрольных сумм на bash скриптах и системных утилитах. Думал, что ничего сложного нет.

      там суммы считаются/проверяются во все потоки

      Каким алгоритмом рассчитываются суммы? Это алгоритм с поддержкой многопоточности или под многопоточностью подразумевается обращение к диску в несколько потоков для чтения файлов? Просто интересуюсь.


      1. yursdan
        13.06.2026 14:38

        Каким алгоритмом рассчитываются суммы?

        sha256. Это унаследованное по цепочке обработки с тех времён, когда 256 был быстрее чем 512. Применительно к велосипеду с квадратными колёсами - там "поровну", так как в роли bottleneck выступает SSD.

        В шелловском alias легко заменить 256 на 512. Ну и 256-е в терминале смотрятся эстетичнее из-за лаконичности )


      1. yursdan
        13.06.2026 14:38

        Моё личное наблюдение — sha512sum работает быстрее, чем sha256sum

        Кстати, это не обязательно везде так, в разных процах с аппаратным ускорением этих алгоритмов дела обстоят по-разному.


        1. Caefah Автор
          13.06.2026 14:38

          Мой опыт ограничивается только замерами на паре вариантов несильно старых x86_64 CPU, поэтому да, возможно мои выводы были поспешны. Спасибо за точку зрения!


      1. yursdan
        13.06.2026 14:38

        Вопросы не праздные — я в них упёрся в тот момент, когда сам продумывал решение и хотел нагородить проверку контрольных сумм на bash скриптах и системных утилитах.

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

        В моих случаях alias используется для расчёта сумм файлов для временного контроля целостности или проверки "покрытия" файлов с какого ни будь из носителей, где годами накапливались дубликаты разных pdf'ов, архивов, фотографий и видеозаписей. Делается список сумм файлов с носителя/директории, который затем используется для ответа на вопрос что уже обрабатывалось, а что новое.


  1. mih-kopylov
    13.06.2026 14:38

    Я правильно понимаю, что если бы в rsync опция -c работала с поддержкой прерывания и продолжения с того же места, то статьи бы не было?


    1. Caefah Автор
      13.06.2026 14:38

      Перед ответом я тщательно подумал над Вашим так точно заданным вопросом! И да, совершенно верно, была бы опция прерывания, — не было бы статьи, не было бы и моего личного опыта в борьбе с несовершенством цифровой реальности.

      Но! На самом деле я рад этому опыту! Есть такой термин, часто используемый в разработке: Test Oracle — тестовый Оракул. Это некая независимая сущность, призываемая для проверки результата.

      Ещё тогда, когда я уже начал использовать rsync для рабочих нужд, не до конца понимая всех нюансов его работы, я интуитивно чувствовал, что использовании единственного инструмента может таить угрозу. И потом, внезапно потеряв кусок важного дампа БД в DRC банка я в этом убедился воочию. Пришлось вникать в нюансы и строить процедуры периодического восстановления из бэкапов на архитектуре DRC. Это было чертовски сложно и долго, но действительно гарантировало восстановление работы на резервных ресурсах в случае проблем с основным DC. Это и был тот самый Оракул, который проверял результат.

      precizer в данном случае тоже является оракулом, связанным с основным инструментом синхронизации, только через данные. Простым, но от этого не менее эффективным.

      Угрозы могут идти не только от rsync. ПО или железо. Развалившийся RAID, проблемы с бэдблоками на дисках в более простых решениях, сбои на сетевом уровне, баги в ПО: как внутри rsync, так и в любом другом. Всё это несёт реальную угрозу рассинхронизации.

      После наступания на «грабли» я теперь осознаю важность тестового Оракула. Не precizer, так какой-то другой инструмент. Поэтому все мои текущие и будущие решения в обязательном порядке будут построены на этом принципе.


  1. y_u_h
    13.06.2026 14:38

    Давно забытый слог. Читал с каким-то упоением что ли. Напомнило движуху времён диал-апа (но уже после фидо). Про гелий не задумывался, купил пару на 20000 ГБ полгода назад. Как оказалось это - инвестиция, так как стоимость поднялась уже более чем в 2 раза с момента покупки. А почему не syncthing, которая как минимум два в одном - и опенсурс и может p2p работать?


    1. mydigitalhabb
      13.06.2026 14:38

      Конкретно у меня Syncthing не смог завершить синхронизацию 18Tb из Windows на Android TV приставку.

      Resilio Sync (тоже бесплатный) - смог, и уже год прекрасно работает.


    1. Caefah Автор
      13.06.2026 14:38

      Читал с каким-то упоением что ли

      От души благодарю. Значит не зря старался! Думаю, в будущем больше никто так не будет писать не потому, что весь мой айтишный опыт — продукт того самого диалапа, времён абсолютной свободы фидо, субкультуры udaff и padonkaf, а потому, что все ленятся и получается юридически выверенный, стерильный текст, выс…ый AI. Ну хорошо, может не ленятся, но экономят личный невозобновляемый ресурс — время.

      Меня когда то сильно впечатлил стиль текстов Andy Weir: добрый, умный, сложный и с циничным юмором. Наверно, это теперь неосознанно отражается в том, к чему сам стремлюсь.

      Сейчас вспоминаю и с удивлением осознаю, что раньше можно было писать обо всём и на любую тему, и за это тебе ничего не было (кроме злобных модераторов, которые могли кенсельнуть пост, конечно! :)

      А теперь каждый телефон о тебе докладывает куда нужно и там где нужно знают о тебе больше, чем ты сам.

      Хоть сейчас трава за моим окном и зеленее, чем была раньше за моим другим окном в прошлой жизни, но всё равно, поразительные и удивительные были времена! :-D

      syncthing

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

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

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

      rsync не идеален, но он работает. Он полностью надёжен и предсказуем. Не вижу смысла менять что-то архитектурно, что уже проверено годами. Улучшить — да, можно. И статья именно об этом.


  1. itoolsy
    13.06.2026 14:38

    Очень круто написано и проделано многонедельные работы, но зачем? Цель какая была всего этого изначально? Начиная с того, что на малинке надо ставить nvme сразу и забыть про флешку и далее далее далее....
    veeam просто существует.
    Более мелкие диски, не на 100500Тб - тоже. 2 копии в разных местах можно организовать, если у вас настолько серьезные данные и забыть о многонедельных попытках восстановления.


    1. Caefah Автор
      13.06.2026 14:38

      надо ставить nvme сразу

      Сейчас да, я полностью соглашусь. Тогда, когда я только пробовал свою первую Raspberry Pi, задача стояла не в том ключе, чтобы разориться на покупку nvme, а попробовать вообще подойдёт малинка для тогдашних моих нужд или нет. Возможно да, это бы решило проблему UBOOT и расширило бы выбор OS, но сейчас меня итак устраивает и без лишних трат. Малинка прекрасно работает как backup-платформа, на которой можно даже что-то запустить с минимумом энергозатрат.

      проделано многонедельные работы, но зачем?

      Ради результата. Сейчас у меня два ёмких диска на двух сторонах и я ничем не ограничен в своих желаниях хранить любой объём интересующих меня данных; синхронизация с проверкой и полная уверенность в идентичности данных; прямой доступ к данным через обе железки — к обеим точкам я могу за считанные секунды подключиться через интернет и добраться до любого файла.

      Несомненно, HDD не конкуренты NVME дискам. И вообще магнитная технология заведомо обречена на увядание. Однако обещания Samsung выпустить четыре года назад NVME диски пользовательского уровня ёмкостью 100Tb пока так и остаются обещаниями. Учитывая ≅6 кратную разницу в стоимости хранения одного мегабайта продолжаем жить с HDD и жать светлого будущего.

      забыть о многонедельных попытках восстановления

      NVME точно так же НЕ гарантируют 100% сохранности и доступности данных как и HDD. Рано или поздно, но и с любыми solid state возникнут проблемы. Даже солидных брендов. Технология увы, не совершенна. Это не просто слова, это неоднократный личный опыт.


  1. JoshMil
    13.06.2026 14:38

    “Решил я как то проверить, что будет если энтропия в системе будет нарастать бесконечно…”

    *** Длинный текст с описанием эволюции вселенной.