| « Несколько патчей для ядра CentOS5/RHEL5 2.6.18-128.1.10 | BIND 9.6.0-P1 и TTL » |
Как правильно инкрементально бэкапить TAR'ом Linux'овые файловые системы
LinuxУ многих начинающих администраторов Linux встает вопрос о бэкапе. Если этот вопрос обычно решается просто - регулярно tar'ом сворачиваются архивы всех данных, то по мере роста объемов встает вопрос об инкрементальном бэкапе, который решить уже не так просто.
Об инкрементальном бэкапе с помощью tar я расскажу вам по ссылке "Читать далее".
...
Итак, перед нами стоит задача, сбэкапить наш сервер, и не просто сбэкапить, а сделать полный бэкап, и каждый день делать из него разностные бэкапы.
В общем случае, чтобы сделать бэкап любого типа, надо выполнить следующую команду на каждой файловой системе (к примеру, если у нас /var - это отдельная точка монтирования, значит /var надо бэкапить отдельно):
/bin/tar --create --ignore-failed-read --one-file-system --preserve-permissions --recursion --preserve-order --sparse --totals --wildcards --verbose --gzip --file=файл_бэкапа --listed-incremental=файл_метаданных --exclude-from=файл_исключений путь_который_бэкапим
Вкратце опишу, что значит каждый из параметров в данной строке.
1. /bin/tar - собственно, путь к нашему архиватору, если у вас архиватор в другом месте - укажите правильный путь.
2. --create - говорит, что мы создаем архив.
3. --ignore-failed-read - игнорируем файлы, которые не удалось прочитать, вместо останова с ошибкой - бэкап обычно идет автоматически, и лишние сбои бэкапа нам ни к чему.
4. --one-file-system - запрещает бэкапу выходить за пределы файловой системы. Вы спросите, почему бы нам не убрать эту опцию, и не бэкапить все целиком, указав в качестве пути корень (/). Да потому, что в этом случае в бэкап попадет все содержимое системных файловых систем - /dev /proc /sys, и т.д., чего нам в принципе не нужно, и что может послужить поводом для лишних ошибок в процессе развертывания архива. Не-корневые файловые системы со вложенными файловыми системами вы можете смело бэкапить рекурсивно и целиком, убирая этот параметр, но корневую файловую систему без грамотного создания списка исключений так бэкапить нельзя.
5. --preserve-permissions - эта опция говорит архиватору, что мы хотим сохранить все разрешения сохраняемых файлов.
6. --recursion - мы выполняем бэкап всех файлов и каталогов по указанному пути, а также всех файлов и каталогов всех подкаталогов.
7. --preserve-order - при бэкапе мы сохраняем порядок файлов в каталогах, чтобы после восстановления иметь более-менее точные копии и самих каталогов тоже.
8. --sparse - файлы с наличием "пустот" сохраняем именно с указанием мест и длин пустот, а не как файлы с огромным набором нулей.
9. --totals - в конце процесса выводим информацию о том, сколько данных мы сохранили.
10. --wildcards - разрешаем использовать маски (* и ?) в списке исключений - см. ниже.
11. --verbose - вывод подробной информации о процессе. Если вы не ведете лог, или вас не привлекает перспектива видеть весь список сохраняемых файлов на экране - уберите данный параметр.
12. --gzip - сжимаем архив с помощью GZIP. Если не нужно - уберите. --bzip2 не рекомендую, на практике он не дал выигрыша более 10% при сжатии разнородных данных, а вот потери во времени составили около 80%. Однако, если в сжимаемой файловой системе полно текстовых файлов - логи, например - можете попробовать, на тексте он дает ощутимое преимущество.
13. --file=файл_бэкапа - этот параметр указывает путь к создаваемому файлу бэкапа. Убедитесь, что сам этот путь не попадет в бэкап - а лучше - добавьте путь к файлам бэкапа в список исключений.
14. --listed-incremental=файл_метаданных - этот файл управляет говорит, что мы создаем именно бэкап, и управляет уровнем нашего бэкапа. Подробнее смотрите ниже.
15. --exclude-from=файл_исключений - этот файл содержит список исключений - файлов и каталогов, которые не попадут в бэкап. Пути указываются относительно основного пути бэкапа, без начального слеша. Т.е. если мы бэкапим корень (/) и хотим исключить всю папку /backup - пишем просто backup. Допускаются маски, причем на любых уровнях. Допустим, мы бэкапим каталог /www, в котором находятся подкаталоги пользователей, в которых находятся подкаталоги logs, файлы из которых мы не хотим включать в бэкап. Дописываем в файл исключений строчку */logs/*. Вуаля, сами каталоги вида пользователь/logs в бэкап попадают, а вот файлы из них, и подкаталоги - нет.
16. путь_который_бэкапим - это корневой путь, который мы бэкапим. Если бэкапим каталог /www - так и указываем: /www.
Ну вот, параметры разобрали. А теперь к самому интересному. К инкрементальности. Напоминаю про параметр --listed-incremental=файл_метаданных.
Суть в следующем:
1. Если указанного файла не существует - выполняется полный бэкап, а сам файл - создается и заполняется.
2. Если указанный файл существует - выполняется инкрементальный бэкап от момента, определяемого файлом, а сам файл - обновляется.
Итак, мы хотим сделать полный бэкап в понедельник, во вторник - инкрементальный бэкап от состояния понедельника, в среду - от вторника, и т.д. Для этого нам надо:
1. В понедельник бэкапим данные с параметром --listed-incremental=/backup/meta/monday0. При этом файла /backup/meta/monday0 существовать не должно.
2. Во вторник копируем (с заменой) файл /backup/meta/monday0 в файл /backup/meta/tuesday. Затем бэкапим данные с параметром --listed-incremental=/backup/meta/tuesday. Вуаля, мы имеем архив, представляющий собой разность данных между состоянием на момент нашего бэкапа во вторник, и состоянием на момент бэкапа на понедельник.
3. В среду копируем файл /backup/meta/tuesday в файл /backup/meta/wednesday. Затем бэкапим данные с параметром --listed-incremental=/backup/meta/wednesday.
4. И так далее.
Отмечу, что для развертывания бэкапа файлы метаданных и исключений не нужны - их сохранять не обязательно. Они нужны только непосредственно для процесса инкрементального бэкапа.
Чтобы развернуть такой бэкап, допустим, на четверг - нам потребуется развернуть полный бэкап на понедельник, затем - бэкап на вторник, затем - бэкап на среду, и наконец - на четверг. Как разворачивать - читайте в конце статьи.
Теперь предположим другой случай. Мы хотим делать полный бэкап в понедельник, а во вторник, среду, и т.п. - делать разность от понедельника. Все делается точно так же, но копию файла метаданных во вторник, среду и т.п. вы делаете перед бэкапом не из файла предыдущего дня, а из файла понедельника. Просто?
Развернуть такой бэкап можно будет в два этапа - сначала файл полного бэкапа на понедельник, а потом - файл бэкапа на нужный нам день. Куда проще, чем в прошлом случае, но и объем данных возрастает.
Ну и более сложный пример - допустим мы хотим делать полный бэкап каждый месяц, каждую неделю делать разность от ежемесячного бэкапа, а каждый день - от прошлого дня. С учетом предыдущих двух примеров вы и сами легко найдете решение. Попробуйте сделать это самостоятельно, а потом сравните с тем, что указано здесь.
Итак, решение. Каждый месяц делаем полный бэкап с файлом метаданных month, которого не существует. Каждую неделю в понедельник копируем (с заменой) файл month в файл monday, и делаем недельный бэкап с указанием этого файла. Каждые вторник-воскресенье копируем файл предыдущего дня (во вторник - monday) в файл текущего дня, и выполняем бэкап с указанием этого файла. Собственно, и все.
Получилось?
Развернуть такой бэкап тоже несложно. Сначала разворачиваем полный (ежемесячный) бэкап на нужный месяц. Потом - недельный бэкап на нужную неделю в этом месяце. А потом - по очереди все дни до нужного нам включительно. Вот и все.
Вы скажете - архиватор сохраняет только имеющиеся файлы. А что делать, если файл удалился? Как раз для этого и придуманы файлы метаданных и команда --listed-incremental. При сохранении бэкапа в файл архива добавляется список изменившихся (в том числе и удаленных) файлов. И при развертывании следующего уровня бэкапа все файлы, удалившиеся на его момент, также будут удалены из файловой системы. Поэтому при развертывании бэкапов будьте осторожны, и не развертывайте бэкапы поверх уже имеющихся данных, взятых не из бэкапа предыдущего уровня.
Итак, с процессом бэкапа мы разобрались. Теперь я обещал рассказать вам, как разворачивать созданные бэкапы. При развертывании надо не забыть передать архиватору набор параметров, подобный тому, что мы указывали при архивации. Команда развертывания выглядит следующим образом.
/bin/tar --extract --ignore-failed-read --preserve-permissions --listed-incremental=/dev/null --recursion --preserve-order --sparse --verbose --gzip --file=файл_бэкапа --directory=путь_для_развертывания
Так же вкратце опишу, что значит каждый из параметров в данной строке.
1. /bin/tar - собственно, путь к нашему архиватору, если у вас архиватор в другом месте - укажите правильный путь.
2. --extract - говорит о том, что мы разворачиваем архив.
3. --ignore-failed-read - игнорируем файлы, которые не удалось прочитать, вместо останова развертывания с ошибкой - даже если что-то не развернулось (бывают файлы хитрого типа - например файлы устройств, которые на целевой системе могут и не развернуться), сбои нам ни к чему, проще почитать лог.
4. --preserve-permissions - эта опция говорит архиватору, что мы хотим восстановить все разрешения восстанавливаемых файлов.
5. --listed-incremental=/dev/null - заметьте, как изменился параметр. При восстановлении файл метаданных роли не играет, однако имя файла все равно требуется. Поэтому мы указываем /dev/null, на функциональность это не повлияет. Указывать --listed-incremental необходимо, поскольку при этом не только восстанавливаются заархивированные файлы и каталоги, но и удаляются занесенные в бэкап удаленные файлы и каталоги (об этом я писал выше).
6. --recursion - мы выполняем развертывание всех файлов и каталогов, а также всех файлов и каталогов всех подкаталогов.
7. --preserve-order - при восстановлении мы сохраняем порядок файлов в каталогах.
8. --sparse - файлы с наличием "пустот" восстанавливаем именно в первозданном виде, а не как файлы с огромным набором нулей.
9. --verbose - вывод подробной информации о процессе. Если вы не ведете лог, или вас не привлекает перспектива видеть весь список восстанавливаемых файлов на экране - уберите данный параметр.
10. --gzip - если архив был сжат с помощью GZIP, не забудьте про этот параметр.
11. --file=файл_бэкапа - этот параметр указывает путь к развертываемому файлу бэкапа.
12. --directory=путь_для_развертывания - путь, куда восстанавливаются файлы. Здесь зарыт небольшой подводный камень. Допустим, мы бэкапили каталог /www/users. Можно предположить, что при восстановлении надо указать тоже /www/users. А вот и нет. Дело в том, что в бэкапе сохраняются полные пути без лидирующего слеша (/). Т.е. все пути сохранились, как www/users/*. Поэтому если мы укажем здесь /www/users - все развернется, как /www/users/www/users. В нашем случае достаточно просто указать /, или использовать опцию --strip-components=N для исключения N начальных элементов пути.
Вот, собственно, и все, что я хотел вам рассказать. Удачного архивирования ![]()
Трекбек адрес этой записи
URL трекбека (щелкните правой кнопкой мыши и скопируйте ссылку)
/dev/null указывать обязательно, иначе опция нормально работать не будет. Проверено на практике в версии tar на CentOS 5.x, за остальные возможные версии tar не ручаюсь.
Ещё раз спасибо за статью, оказалось очень полезно.
ОС: CentOS.
Я использую данную каманду в cron поэтому сделать /folder/тут_то_что_мне_нужно текущим я не могу.
Иначе получется, что распаковывать архив мне надо в корневом каталоге, чтобы всё попало на свои места.
Спасибо.
--strip-components NUMBER, --strip-path NUMBER
strip NUMBER of leading components from file names before
extraction
(1) tar-1.14 uses --strip-path, tar-1.14.90+ uses --strip-compo-
nents
P.S. у меня debian lenny, если это имеет значение.
2. Вы исключили /srv, /media и /mnt - вы уверены, что для конкретного конфига иксов там не нужна какая-либо структура?
Бэкапил таким способом далеко не один сервер, все восстанавливается нормально. Возможно, в вашем случае что-то все-таки отличается после восстановления. Как уже говорил - гляньте логи, они многое скажут.
Я, кстати, для целей исключения вторичных файловых систем использую --one-file-system, и бэкаплю вторички отдельно, почему вы пошли по пути радикального исключения каталогов?
пробовал использовал маски */log/* и x/log/* что-бы сохранить директорию x/log без вложений, но при этом в архив не попадает и сам каталог x/log
Создал папку ~/test и создал в ней папку "folder" и файл "file"
(опущу некоторые параметры)
tar cv --listed-incremental=~/backup/meta/monday --file=~/backup/full ~/test/
В папке backup создается архив full. Все хорошо. Теперь добавляю в папку test файл "file2". Копирую в папке ~/backup/meta файл monday и переименовываю его в tuesday.
Кстати, в статье ни говорится что делать с --file: менять или оставлять как было. Ну наверное менять ))
tar cv --listed-incremental=~/backup/meta/tuesday --file=~/backup/ink ~/test/
В итоге в архиве ink лежит файл "file2" (как и должно быть). Но почему то лежит и папка "folder" которая не менялась.
Вот собственно вопрос, почему она добавляется?
Извиняюсь за длинный пост.