Бэкапиться, бэкапиться и ещё раз бэкапиться..

Вчера приезжаю с отдыха, а один из проектов, над которым работал больше месяца сгорел. Сгорел во всех смыслах, большой пожар неделю назад был в украинском дата-центре в Одессе (hosting.ua), где сервер временно размещался. К счастью бэкап проекта был, его быстро восстановили, хотя потеряли часть критически не важных данных.

Суть в том, что потеря данных может быть в любом, даже в самом навороченном дата-центре. Нельзя полагаться только на RAID, дизель-генераторы и автоматизированные системы пожаротушения. Сервер могут арестовать (по ошибке или просто за компанию с другими), может пройти короткое замыкание или начаться война, попасть метеорит, застрять таракан в лопастях вентилятора или прогрызть проводку мышь, да на него кофе в конце концов могут пролить. Где-то читал, что одна комания бэкапила данные в всемирном торговом центре с одного небоскрёба на сервер в другом небоскрёбе. А потом наступило 9 сентября 2001 года.

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

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

Я около года назад сделал небольшой PHP скрипт, который использую для бэкапа своих проектов. Файлик лежит в корне веб-сайта, делает бэкап базы и файлов и заливает данные на удалённый сервер. Для каждого нового сайта я заливаю этот скрипт в корень директории сайта и ставлю его выполнение раз в пару дней в cron. Раз в месяц я сливаю архивы с FTP к себе на домашний компьютер.

Я приведу команды для подобного бэкапа в linux. Для вызова консольных команд из PHP можно использовать команды exec или system. Можно на основе этих команд сделать bash скрипт.


Бэкап файлов

Сохраняем сайт в tar архив:
tar -cf {путь к получаемому tar архиву} {полный путь к директории сайта}

например: tar -cf site.tar /var/www/site.com/htdocs

Сжимаем полученный архив в tar.gz (т.к. tar не сжимает, а только пакует файлы в один):
gzip -c {путь к tar архиву} > {путь к получаемому tar.gz архиву}

например:
gzip -c /var/www/site.com/htdocs/site.tar > /var/www/site.com/htdocs/site.tar.gz


Бэкап MySQL базы данных

—quote-names —add-drop-table —user=’.$DBLogin.’ —password=’.$DBPassword.’ —host=’.$hostname;
$str = exec(‘mysqldump ‘.$params.’ ‘.$DBBase.’ > ‘.$path.’/tmp.sql

Сохраняем базу в SQL дамп:
mysqldump —quote-names —add-drop-table —user={юзер БД} —password={пароль к БД} —host={хост, как правило localhost} {название БД}>{путь к сохраняемому SQL дампу}

например: mysqldump —quote-names —add-drop-table —user=root —password=12345 —host=localhost site_database>/var/www/site.com/htdocs/dump.sql

Аналогично сжимаем дамп базы данных в gz архив.


Восстановление данных из архивов

Распаковка файлов из tar.gz в текущую директорию:
tar zxvf {tar.gz архив}

например:
tar zxvf archive.tar.gz

Восстановление базы из sql дампа:
mysql —host={хост} —user={юзер БД} —password={пароль к БД} {название БД}<{SQL дамп}

например: mysql —host=localhost —user=root —password=12345 site_database<dump.sql

Если дамп сжат в gz, то нужно его перед тем как скормить утилите mysql предварительно разархивировать:
gzip -d {название gz файла}


Заливаем на FTP средствами PHP:

Если бэкапить скриптом, то полученные архивы неплохо бы сразу залить на удалённый FTP. Простейший код для заливки файла по FTP в PHP:

$conn_id = ftp_connect({FTP сервер:порт});
$login_result = ftp_login($conn_id, {FTP логин}, {FTP пароль});
if ($conn_id && $login_result) $upload = ftp_put($conn_id, {путь к заливаемому файлу}, {путь сохраняемого файла по FTP}, FTP_BINARY);
ftp_close($conn_id);


Шифруем архивы средствами GPG:

Чтобы можно было использовать любой FTP хостинг, а также без опасений заливать и хранить бэкапы где угодно, неплохо бы их шифровать. Я для шифрования использую GPG — аналог симметричного шифрования PGP.

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

Для создания ключей выполняем: gpg —gen-key

  • Тип ключа (первый вопрос) выбираем по умолчанию — 1
  • Выбор размера ключа — по умолчанию 1024 (или можно 2048 байта)
  • Третий вопрос, время действия ключа выбираем 0 (никогда не истекает)
  • Четвёртый вопрос — указание личных данных (имя и мэйл). Главное имя — название ключа. У меня это backup_key.
  • В конце нужно заполнить пароль. Пароль нужен для получения доступа к секретному ключу. НЕ ЗАБЫВАЕМ ЗАПИСАТЬ!

САМОЕ ГЛАВНОЕ! Не забываем скачать и сохранить в надёжном месте у себя на компьютере секретный и публичный ключ, и пароль к секретному ключу,  а то расшифровать потом архивы самому не получиться =)

Чтобы потом импортировать ключи на новую систему, выполняем:
gpg —import {путь к asc файлу с данными ключа}

Шифрование архива средствами GPG:
gpg —recipient {название ключа} —output {получаемый шифрованный файл} —encrypt {файл для шифрования}

например: gpg —recipient backup_key —output dump.sql.gz.gpg —encrypt dump.sql.gz

Расшифрование GPG файла:

gpg -d {шифрованный файл} > {файл}

например: gpg -d dump.sql.gz.gpg > dump.sql.gz

Чтобы расшифровать архивы в Windows, можно скачать консольную GPG для Windows. Если делать шифрование средствами PHP, нужно в корневой папке апача создать папку .gnupg и положить туда публичный ключ, чтобы он мог шифровать архивы.