Сегодня мы напишем небольшой скрипт бэкапа базы данных (дампа). Его действия будут предельно простыми и без особых наворотов, однако он будет легко устанавливаться и выполнять свои задачи "как часы" :)
Задача: написать код для подключения в cron, который:
Начнем с конфигурации — вынесем все параметры скрипта в константы:
// Сколько последних dump-ов будем хранить define ("FILES_TO_KEEP", 5); // Период между бэкапами в секундах define ("BACKUP_PERIOD", 20); // Параметры подключения к базе данных define ("DATABASE_CONF", 'mysql://root:qwe@localhost/egl_payment'); // Папка для хранения backup-ов define ("BACKUP_FOLDER", './backup' );
Называть файлы бэкапов мы будем в соответствии c шаблоном, в котором будет зашито время создания файла (так получать это время проще и правильнее, чем с помощью функций операционной системы):
backup-13-02-2009_15-02-05.sql
Нам нужно получить список файлов из директории для хранения бэкапов:
clearstatcache();
$b_dir = dir(BACKUP_FOLDER);
$b_files = array();
while($file = $b_dir->read()) {
if (preg_match("/^backup-(\d+)-(\d+)-(\d+)_(\d+)-(\d+)-(\d+)/i", $file, $a)) {
array_push($b_files, array('n' => $file,
't' => mktime($a[4], $a[5], $a[6], $a[2], $a[1], $a[3])));
}
}
$b_dir->close();
Этот список мы создаем в виде массива, каждый элемент которого массив с двумя элементами — имя файла и timestamp времени его создания.
Нам необходимо будет отсортировать массив по возрастанию времени, поэтому напишем функцию пользовательской сортировки:
function cmp_file_times($t1, $t2) {
if ($t1['t'] == $t2['t']) return 0;
return ($t1['t'] > $t2['t']) ? 1 : -1;
}
Теперь напишем основной кусок программы, проверяющий количество существующих файлов, их время создания, и, в зависимости от этого, делающий новый бэкап:
$now = time();
$b_count_files = count($b_files);
if ($b_count_files) {
// Сортируем файлы по возрастанию времени создания
usort($b_files, "cmp_file_times");
// Если последний файл создан достаточно давно
if ($b_files[$b_count_files - 1]['t'] <= $now - BACKUP_PERIOD) {
// Если есть лишние файлы, удаляем нужное кол-во самых старых:
if ($b_count_files >= FILES_TO_KEEP) {
for ($i = 0; $i < $b_count_files - FILES_TO_KEEP + 1; $i ++) {
unlink(BACKUP_FOLDER."/".$b_files[$i]['n']);
}
}
backup();
}
}else {
backup();
}
Остался последний шаг — написать функцию бэкапа backup(). В принципе в нее можно включить все что угодно, хоть архивирование всего сайта. Это будет домашним заданием. А сейчас мы напишем простенький дамп базы данных MySQL с последующим gzip-ованием.
function backup() {
global $now;
$file = BACKUP_FOLDER."/backup-".date("d-m-Y_H-i-s", $now).".sql";
$db = parse_url(DATABASE_CONF);
$db['path'] = substr($db['path'], 1);
$q = "mysqldump -u".$db['user']." -p".$db['pass']." -h".$db['host']." ".$db['path']." > ";
exec($q.$file."; gzip -f ".$file);
}
Все готово! Весь скрипт вместе можете посмотреть в прикрепленном файле с посту. Вам остается только включить его в cron.php, указать нужные параметры и создать директорию для бэкапов.
Да, чуть не забыл. Если директорию для файлов вы создадите под DOCUMENT_ROOT сервера, то необходимо защитить ее от чтения с помощью htaccess. Делается это примерно таким образом — создайте в директории бэкапов файл .htaccess со следующим содержанием:
order allow,deny deny from all
Теперь дампы вашей базы данных (а впрочем и любые другие файлы в папке бэкапов) защищены от скачивания через HTTP. Все!
| Прикрепленный файл | Размер |
|---|---|
| cron.php.txt | 1.43 кб |
Комментарии
У меня не работает(((
что именно не работает?
Вопрос (я не спец, как вы понимаете), а если идет чтение-запись в базу, и база бекапится без остановки сервера. Если в базу активно пишутся логи (юзеров которые постят сообщения), дамп будет битый? У меня так постоянно бъется.
Спасибо огромное) Очень помогло - прекрасно работает)
Отправить комментарий