Администрирование сайта. Backup базы данных с помощью PHP скрипта и ограничения хостинга

Владимир | | PHP, Разное.

Логотип для backup базы данных
Недавно я столкнулся с небольшой проблемой. Нужно было организовать автоматическое создание резервных копий базы данных.

Задача, конечно, стандартная, а, учитывая объем базы (меньше 1МБ), может быть решена без специального софта и оборудования.

Так что я выбрал самый простой способ (осуществляется в три этапа):

1) создание дампа БД;
2) упаковка дампа в архив;
3) отправка архива на eMail.

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

Т.е. все, что нужно сделать – написать скрипт и запускать его с помощью cron.

Скрипт я решил сделать на PHP, и сразу же столкнулся с проблемой.

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

Причина оказалась очень простой. В настройках PHP на сервере хостера были отключены функции: shell_exec(), exec() и т.п.

Поэтому пришлось делать backup в два этапа.

1) Создание дампа БД
Для этого планировщик я просто добавил команду:
mysqldump -uuser_name -hhost_name -puser_password db_name > /path_to_tmp/db_backup/mydbdump.sql

В результате выполнения этой команды, создается файл mydbdump.sql с дампом базы, который будет размещен в папке /path_to_tmp/db_backup/. В параметрах команды, естественно, нужно указать настоящие имена базы, пользователя, пароль и путь к папке /tmp.

Примечание. Для папки /path_to_tmp/db_backup/ должны быть установлены права на запись.

2) Упаковка дампа в архив и отправка по eMail

Эти операции выполняются одним скриптом.

<?php
/**
 * Эту функцию я взял на сайте
 * http://www.weberdev.com/get_example-4173.html
 */
function mail_attachment($filename, $path, $mailto, $from_mail, $from_name, $replyto, $subject, $message) {
    $file = $path.$filename;
    $file_size = filesize($file);
    $handle = fopen($file, "r");
    $content = fread($handle, $file_size);
    fclose($handle);
    $content = chunk_split(base64_encode($content));
    $uid = md5(uniqid(time()));
    $name = basename($file);
    $header = "From: ".$from_name." <".$from_mail.">\r\n";
    $header .= "Reply-To: ".$replyto."\r\n";
    $header .= "MIME-Version: 1.0\r\n";
    $header .= "Content-Type: multipart/mixed; boundary=\"".$uid."\"\r\n\r\n";
    $header .= "This is a multi-part message in MIME format.\r\n";
    $header .= "--".$uid."\r\n";
    $header .= "Content-type:text/plain; charset=iso-8859-1\r\n";
    $header .= "Content-Transfer-Encoding: 7bit\r\n\r\n";
    $header .= $message."\r\n\r\n";
    $header .= "--".$uid."\r\n";
    $header .= "Content-Type: application/octet-stream; name=\"".$filename."\"\r\n"; // use diff. tyoes here
    $header .= "Content-Transfer-Encoding: base64\r\n";
    $header .= "Content-Disposition: attachment; filename=\"".$filename."\"\r\n\r\n";
    $header .= $content."\r\n\r\n";
    $header .= "--".$uid."--";
    if (mail($mailto, $subject, "", $header)) {
//        echo "mail send ... OK"; // or use booleans here
    } else {
        echo "mail send ... ERROR!";
    }
}

//размещение и имя файла с дампом базы
$fileName = '/path_to_tmp/db_backup/mydbdump.sql';
//размещение архива с дампом
$archivePath = '/home/simpleco/tmp/db_backup/';
//имя архива
$archiveName = 'rssevents_backup_'.date('Y_m_j_G_i').'.zip';

//создаем архив $zip = new ZipArchive(); if ($zip->open($archivePath.$archiveName, ZIPARCHIVE::CREATE) === TRUE) { //добавляем в архив файл с дампом $zip->addFile($fileName, 'mydbdump.sql'); $zip->close(); // echo 'ok'; } else { echo 'failed creating zip'; } //устанавливаем переменные для отправки почты //имя и путь к файлу с архивом $my_file = $archiveName; $my_path = $archivePath; //имя отправителя $my_name = "my_name"; //обратный адрес $my_mail = "admin@simplecoding.org"; $my_replyto = "admin@simplecoding.org"; //тема письма $my_subject = "RSS events backup"; //текст письма $my_message = 'Во вложении находится дамп базы. '.date('F-j-Y G:i'); //отправляем письмо (в третьем параметре адрес получателя) mail_attachment($my_file, $my_path, "account_name@gmail.com", $my_mail, $my_name, $my_replyto, $my_subject, $my_message); @unlink($archivePath.$archiveName); @unlink($fileName); ?>

Разберем, как работает этот скрипт.

В начале (строки 6 — 35) объявлена функция mail_attachment, которая выполняет отправку письма с вложением. Признаюсь честно, писать эту функцию самому мне было лень 🙂 . Поэтому я использовал готовую – с этого сайта.

После этого, упаковываем файл с дампом в архив (строки 45 — 53). Для этого создаем объект типа ZipArchive и вызываем его метод open с параметром ZIPARCHIVE::CREATE. А с помощью метода addFile добавляем в архив файл с дампом.
И, естественно, не забываем закрыть архив (метод close).

Примечание. Подробнее почитать о создании архивов с помощью PHP можно в статье «Создание zip архивов на PHP».

Дамп упакован, добавляем его в качестве вложения к письму и отправляем (строка 70). Имена параметров функции mail_attachment говорят сами за себя, поэтому описывать я их не буду.

Завершающим этапом, удаляем файлы с дампом и архивом (строки 72, 73).

Теперь осталось только загрузить этот скрипт на сервер и добавить команду для cron.

php -q /path_to_backup_script/dbbackup.php

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

Как видите, решение получилось не очень красивое, но работоспособное. Конечно, использовать его для больших баз данных не получится. Но, с другой стороны, если ваша база содержит десятки или сотни мегабайт информации, то вряд ли она находится на shared хостинге 🙂 .

Удачи!

А как вы делаете бэкапы?