Пакетная запись дисков, pktcddvd и бакапы.

Энное время назад у меня приказал жить один жесткий диск. С бакапами, которые я, как несложно догадаться с некоторых достаточно давних пор всегда делаю. Причем накрылся после двух лет работы в режиме «включилось раз в неделю мосфетом питание, сделался инкрементальный бакап, питание отключилось». Причем судя по анализу трупика накрылся движочек, вращающий этот мелкий ноутбучный хард от врубаний/вырубаний. Даром что вестерн джигитал.
Это заставило меня почесать голову и всерьез подойти к проблеме бакапов. Можно считать меня редкостным параноиком, но хранить что-то у гугла/дропбокса в облаке — «не наш метод ™». И вот тут-то я увидел на столе покрытую пылью, cdrw болванку, года 3 использующуюся как подставка под чашку.


Сначала была мысль делать инкрементальные бакапы на мультисессионный DVD/CD, примерно как puppy linux, и потихоньку дописывать в конец. А при чтении собирать unionfs’ом. Но так как это требует менять болванки достаточно сравнительно часто — этот вариант отпал. Ибо я ленив. Да и писать три тонны скриптов для этого дела было лениво. Так что юзаем rw диски и точка.
В общем, попутно я еще вспомнил про фичу как пакетная запись, которая 7 лет назад под виндой у меня так и не заработала.

Пакетная запись: Это такой вундеркостыль, который позволяет писать данные на болванку, как на обычную флешку. Разумеется, на rw диски. По сути — программная прослойка.
Так как настройка этого дела под более или менее свежим дистрибутивом линуха оказалась нетривиальной, я и пишу эту заметку.
Итак, нам потребуется пакетик udftools. Сия штука написана аж в 2002м году, и с тех пор мало менялась, потому без пачки патчей написанных мейнтейнерами не собирается. Абилдик udftools и патчи лежат у меня на гитхабе, счастливые обладатели Agilia Linux качают из стейбла.

Теперь нам потребуется носитель. cdrw или dvdrw. По понятным причинам заляпанный кофе cdrw был дохлым чуть больше, чем полностью, так что в ближайшем «анашане» были куплены 2 cd-rw и 2 dvd-rw диска для экспериментов, а с чердака на даче извлечено 3 предположительно живых резака, один их которых, usbшный, мне с ходу и дал хороший результат (так как обладал единственным непросевшим лазером)

Итак. Что нам потребуется?
Баш, прямые руки, udftools, модуль ядра pktcddvd.
Начинаем с настройки устройства. Главный трюк — юзать /dev/sr0 напрямую НЕЛЬЗЯ. Хотя UDF и смонтируется, причем даже на запись, записанные данные будут коррапчены, а лог загажен io error’ами. Насколько я понял теорию, рандомная запись должна происходить достаточно жирными пакетами (32k?), и сориентированными по определенным адресам.
Теперь краткий рецепт:

Для форматирования болванки cdrw юзаем cdrwtool, например:

cdrwtool -q -d /dev/sr0

Для DVD+/-RW dvd+rw-format. Чтобы юзать пакетную запись надо переключить диск в Restricted Overwrite Mode заместо Sequential, что делается примерно так (на новой болванке)

dvd+rw-format -force=full /dev/sr0

А вот теперь начинается магия!
Для работы нам необходимо сделать следующее:

pktsetup pkt0 /dev/sr0

Эта магия создаст над приводом некоторую прослойку, которая будет собирать пакетики воедино. И уже монтировать надо не /dev/sr0 а /dev/pktcdvd/pkt0 (Заместо pkt0 любое имя).
Только так мы сможем полноценно писать данные туда.

Отрубать это безобразие после unmount’а надо тоже хитро, вот таким вот заклинанием:

umount /media/bck
sync
pktsetup -d pkt0
eject /dev/sr0

sync вообще необязателен, но пусть уж будет.
Все эти волшебные костыли я собрал в не менее волшебный скрипт под названием pktcdtool, который и должен будет делать всю грязную работу.

Вообще, пакетная запись мне до жути напомнила NAND. В идеале, использование jffs2 или иной FS ориентированной для MTD девайсов (особенно нанда, в котором сектора могут невозбранно фейлить), дало бы крайне устойчивый результат, но это надо лезть в кишки pktcddvd, так как натягивать jffs2 через еще один слой абстракции показалось мне не слишком хорошим решением. В идеале — сделать слой, который из /dev/sr0 сделает нам /dev/mtd0, поверх которого можно юзать привычные тулзы. Тут мы получаем и контроль бэд блоков, и ориентированные на это FS с распределением износа… Но для бакапов и это сойдет.

Теперь сами бакапы. Бакапить мне особо много не надо и 4.7 гигабайт DVD+RW болванки более чем хватает (эстэты могут заюзать блюрей). Но вот сценарии бакапа совершенно различные. Для гит репозиториев — сделать pull, а новые отклонировать. Предварительно еще сделать gc чтобы убрать мусор и сжать. Для баз данных 1С — затарить и положить (Да, да, 1C 7.7, это не восьмерка, где можно базу натянуть на постгрес). Снять и сжать дамп mysql, postgresql и прочего.
В общем, штатного решения не нашлось, потому бакапом занялись опять баш скрипты. За один вечер я родил нечто под названием pckbackupsuite, который на деле прост, как пробка.
По крону раз в сутки, часика эдак в три ночи, запускается pbck_exec, который:

  • Монтирует UDF болванку, не покидающую привод долгое время.
  • Выполняет пачку скриптов из backup.d
  • Размонтирует болванку, синкает кэш и т.п.

Смеха ради, стадии выполнения резервного копирования отображаются на POST карте, при помощи этой утилиты.

Для контроля износа болванки самый первый скрипт, 00-warmup сохраняет счетчик бакапов в .backup_count. В теории — болванка выдерживает до 1000 циклов перезаписи, хотя на практике поцарапается быстрее. Соответственно, где-то 800 бакапов — критический момент, когда болванку надо убрать на полку и взять свежую. Даже при бакапе каждую ночь это уже пара лет с гаком.

Так как в нашем случае, DVD+RW на воздухе будет всего 3 раза (вставляем в привод, убираем на полку, достаем в случае проблем), то царапин особенно много не будет. А вот износ лазером контролировать надо.

В чем профит такого странного решения?

  • Бакапы не слетят, если сдохнет механика привода.
  • DVD штука дешевая, нескольких штук хватит на долго.
  • Надо куда-то девать старые приводы.

Ну и, наконец, сия тулза, пока что ничерта не документированная, Под GPLv3 лежит у меня на гитхабе.

Добавить комментарий

Этот сайт использует Akismet для борьбы со спамом. Узнайте, как обрабатываются ваши данные комментариев.