Делаем бэкап базы данных MySQL на PHP
Можно, конечно, полагаться на случай, что пронесет, а можно просто написать небольшой скрипт, установить его в CRON и больше не парится за то, что ваш сайт в один прекрасный момент ляжет и его придется с визгом и матом долго и нудно поднимать. При работе с популярными движками сайтов, бэкап базы сделать конечно в разы проще, там на это счет написанна несметная куча модулей, которые за вас все сохранят, заархивируют да еще и на мыло отправят. Но как правило они используют API самих движков, а это уже не три строчки кода (на тот случай если захочится позаимствовать такое решение у Drupal или Joomla).
Потому если движок самописный или просто если нужно что-то очень простое и понятно как работающее — то данный снипет является решением всех проблем.
backup_tables('localhost','username','password','*'); // можно либо перечислить все таблицы, которые нужны или отметить звездочкой, что нужно делать дамп всей базы function backup_tables($host,$user,$pass,$name,$tables = '*') < $link = mysql_connect($host,$user,$pass); mysql_select_db($name,$link); // Если бекапим все таблицы if($tables == '*') < $tables = array(); $result = mysql_query('SHOW TABLES'); while($row = mysql_fetch_row($result)) < $tables[] = $row[0]; >> else < $tables = is_array($tables) ? $tables : explode(',',$tables); >// проходим по массиву таблиц foreach($tables as $table) < $result = mysql_query('SELECT * FROM '.$table); $num_fields = mysql_num_fields($result); $return.= 'DROP TABLE '.$table.';'; $row2 = mysql_fetch_row(mysql_query('SHOW CREATE TABLE '.$table)); $return.= "nn".$row2[1].";nn"; for ($i = 0; $i < $num_fields; $i++) < while($row = mysql_fetch_row($result)) < $return.= 'INSERT INTO '.$table.' VALUES('; for($j=0; $jelse < $return.= '""'; >if ($j <($num_fields-1)) < $return.= ','; >> $return.= ");n"; > > $return.="nnn"; > // пишем результат в файл $handle = fopen('db-backup-'.time().'-'.(md5(implode(',',$tables))).'.sql','w+'); fwrite($handle,$return); fclose($handle); >
Простой бэкап сайта средствами PHP
В этой статье я попытаюсь разъяснить создание простого скрипта для полного бэкапа сайта (файлы + база данных MySQL) средствами PHP, который будет отправлять отчет на почту и удалять старые архивы.
Для начала нужен FTP доступ к файловой системе, где расположен сайт. Предположим, что сайт у нас находится по адресу /home/my_site/www. Создаем папку backup в my_site:
И конечно же, сам файл backup.php:
touch /home/my_site/www/backup.php
Открываем backup.php любым редактором и создаем переменные:
$backup_folder = '/home/my_site/backup'; // куда будут сохранятся файлы $backup_name = 'my_site_backup_' . date("Y-m-d"); // имя архива $dir = '/home/my_site/www'; // что бэкапим $delay_delete = 30 * 24 * 3600; // время жизни архива (в секундах) $db_host = 'example.com'; $db_user = 'root'; $db_password = 'password'; $db_name = 'database'; $mail_to = 'my_email@example.com'; $mail_subject = 'Site backup'; $mail_message = ''; $mail_headers = 'MIME-Version: 1.0' . "\r\n"; $mail_headers .= 'Content-type: text/html; charset=iso-8859-1' . "\r\n"; $mail_headers .= 'To: me ' . "\r\n"; $mail_headers .= 'From: my_site ' . "\r\n";
Пишем функцию для бэкапа файлов:
function backupFiles($backup_folder, $backup_name, $dir) < $fullFileName = $backup_folder . '/' . $backup_name . '.tar.gz'; shell_exec("tar -cvf " . $fullFileName . " " . $dir . "/* "); return $fullFileName; >
function backupDB($backup_folder, $backup_name) < $fullFileName = $backup_folder . '/' . $backup_name . '.sql'; $command = 'mysqldump -h' . $db_host . ' -u' . $db_user . ' -p' . $db_password . ' ' . $db_name . ' >' . $fullFileName; shell_exec($command); return $fullFileName; >
И для удаления старых архивов:
function deleteOldArchives($backup_folder, $delay_delete) < $this_time = time(); $files = glob($backup_folder . "/*.tar.gz*"); $deleted = array(); foreach ($files as $file) < if ($this_time - filemtime($file) >$delay_delete) < array_push($deleted, $file); unlink($file); >> return $deleted; >
В общем все, осталось выполнить данные функции и отправить письмо:
$start = microtime(true); // запускаем таймер $deleteOld = deleteOldArchives($backup_folder, $delay_delete); // удаляем старые архивы $doBackupFiles = backupFiles($backup_folder, $backup_name, $dir); // делаем бэкап файлов $doBackupDB = backupDB($backup_folder, $backup_name); // и базы данных // добавляем в письмо отчеты if ($doBackupFiles) < $mail_message .= 'site backuped successfully
'; $mail_message .= 'Files: ' . $doBackupFiles . '
'; > if ($doBackupDB) < $mail_message .= 'DB: ' . $doBackupDB . '
'; > if ($deleteOld) < foreach ($deleteOld as $val) < $mail_message .= 'File deleted: ' . $val . '
'; > > $time = microtime(true) - $start; // считаем время, потраченое на выполнение скрипта $mail_message .= 'script time: ' . $time . '
'; mail($mail_to, $mail_subject, $mail_message, $mail_headers); // и отправляем письмо
Элементарные PHP скрипты для резервного копирования данных
В ответ недавнему топику о бэкапах на Bash. Топик полезный, без сомнений, однако я хочу продемонстрировать более гибкий способ…
Основной недостаток приведенного способа в топике выше — ненадобность. Ну честно, кому надо бэкапить файлы и базу одновременно? Т.е. бэкапить каждый день и файлы и базу — глупо, но и делать раз в месяц это глупо. Поэтому мой пример я разбил на 2 части. Отдельно делаем бэкап базы ежедневно и отдельно делаем бэкап файлов раз в неделю.
Соответственно, нам понадобится php на сервере. Что в наше время уже не роскошь, а банальщина.
Итак, для себя я решил, что локально бэкапы хранятся в /usr/backup/
Создаем php скрипт /usr/backup/backup_db:
#!/usr/local/bin/php
$exс=array(‘information_schema’, ‘mysql’);
$db_pass=’password’;
$db_user=’root’;
system(‘mkdir -p /usr/backup/mysql/’.date(‘d.m.Y’).’/’);
$db=mysql_connect(«localhost», $db_user, $db_pass);
$sql=mysql_query(«SHOW DATABASES»);
while($a=mysql_fetch_assoc($sql)) $base=$a[‘Database’];
if(!in_array($base, $exс)) exec(‘/usr/local/bin/mysqldump -u’.$db_user.’ -p’.$db_pass.’ —opt ‘.$base.’ | /usr/bin/gzip > /usr/backup/mysql/’.date(‘d.m.Y’).’/’.$base.’.gz’);
>
>
Как видим, все просто и примитивно. Отмечу, что $exс — массив с исключениями. Сюда добавляем базы, которые не хотим бэкапить каждый день. Остальные базы, что видет пользователь $db_user, мы бэкапим, причем каждую отдельно и кладем их в директорию /usr/backup/mysql/дата/база.gz
Это намного удобней, чем создавать под каждый проект отдельный файл бэкапов. Например, у меня 2 сервера и на каждом 10+ проектов. Не так и много, но кол-во постоянно обновляется. Кто-то ушел, кто-то пришел, появился новый сервер итп. Мне достаточно скопировать один файл и бэкапы всех проектов собираются автоматом. Это удобно.
Соответственно добавляем в крон строку (для FreeBSD. Для Linux, насколько помню, другая. Пожалуйста, поправте, линуксойды):
0 5 * * * root /usr/backup/backup_db
Которая говорит о том, что каждый день в 05:00 собираем новый бэкап базы и гзипем его.
Ну и не забываем про код и картинки… /usr/backup/backup_www…
У кого как, у меня все проекты лежат в /usr/local/www/…
#!/usr/local/bin/php
$exс=array(‘test.ru’);
$dir=’/usr/local/www/’;
system(‘mkdir -p /usr/backup/www/’.date(‘d.m.Y’).’/’);
$d=opendir($dir);
while(($file=readdir($d))!==false) if($file!=’.’ && $file!=’..’ && is_dir($dir.’/’.$file) && !in_array($file, $exс)) exec(‘tar cpzvf /usr/backup/www/’.date(‘d.m.Y’).’/’.$file.’.tar.gz —exclude=*.log* —exclude=*.svn* ‘.$dir.$file);
>
>
Как видим, скрипт бэкапт все, кроме log файлов и svn файлов. Насчет svn может быть я и не прав, но пока проблем с этим небыло. Так же массив $exс является исключениями.
Для данного скрипта в крон пишем несколько другое правило:
0 5 * * 6 root /usr/backup/backup_www
таким образом бэкапим скрипты и статику в 5 утра в выходной.
Я использую данные скрипты не только на своих серверах, но и на клиентских. Правда, на клиентских дополняю их еще и копированием архивов на третьи сервера для пущего страху. На некоторых серверах отдельные таблицы в нужных базах бэкаплю каждый час итп. PHP дает гибкость, которой так не хватает в bash`е.
p.s. после добавления данных в крон не забываем его ребутить. И не забываем ставить chmod +x для backup_db и backup_www
p.p.s. любые дополнения и критика приветствуются.
Как реализовать бэкап сайта/бд посредством PHP?
Сайт содержится локально на компьютере. Необходимо делать бэкап данных каждый день, а также бэкап всех файлов каждую неделю. Возможно ли написать скрипт на PHP, который будет автоматически реализовывать данный функционал.
Простой 2 комментария
Возможно, хотя непонятно зачем это делать на PHP.
Достаточно одной команды архиватору — вот эту папку заархивируй, добавь в название дату, и помести вон в ту папку. Или отправь по почте, например.
Ну и в планировщик задач это добавить.
А вообще для бекапа есть специаллизированный софт, который не только позволит бекапить, но и разворачивать из бекапа обратно с минимальными усилиями.
Еще лучше, если у вас будет запасной сайт, на который можно переключиться за секунды. Но это уже история следующего уровня.
А зачем делать так, чтобы резервная копия зависела от работы сайта?!
Проще через теневое копирование и специализированное ПО для резервного копирования по расписанию запускать задание.
Пых сам себя не запустит, все равно придется планировщик пристегивать.
А планировщику, в свою очередь, незачем прописывать исполнение команд пыха, есть более естественные инструменты.
Для локального компьютера, на самом деле, главная сложность в том, что он, в отличие от сервера, включен не постоянно, поэтому просто задав планировщику бэкап каждый день и каждую неделю, можно элементарно ничего не получить, потому что компьютер в это время не работал.
Просто локальный сервер — это обычно сервер разработки, его можно бэкапить, просто сделав себе соответствующие скрипты и запуская их после окончания работы вручную.
Постоянно же работающий сервер логичнее бэкапить снаружи — дотягиваясь до него с бэкап-сервера и забирая данные туда, куда основной вовсе доступа не имеет. Из банальных соображений безопасности.
Суточного бакапа тебе будет достаточно? Если в момент смерти сайта ты сможешь восстановить только ‘вчерашнюю’ копию, с потерей всех сегодняшних изменений и данных?
Резервное копирование обычно разделяют на две составляющие (потому что технологии так устроены), это резервное копирование базы данных и резервное копирование файлов. Если копировать файлы базы данных как файлы, можно не восстановить корректно их потом (потому что в момент копирования эти файлы могут использоваться), то же самое относится и к просто файлам, если в момент проведения резервной копии эти файлы начнут изменяться, можно получить кашу из частично измененных файлов.
Чтобы решить эти проблемы используют снапшоты, на выбор — либо на уровне виртуальной машины (если она используется либо у провайдера), либо разделов (например если используется lvm), либо файловой системы (если используется btrfs/zfs/ntfs, с оговорками).
Перед резервным копированием делают снапшот файловой системы, замораживая ее состояние, делают копирование, после чего снапшот удаляют/отключают. Самые быстрые снапшоты на основе файловой системы и у виртуальной машины (правда некоторые делают это вместе с оперативной памятью, что медленнее).
Самый интересный механизм резервного копирования базы данных — это онлайн репликация базы на соседнюю машину. Все изменения будут копироваться в тот же миг как они были совершены на исходной машине (можно настроить master-master репликацию, тогда изменения будут гарантированно синхронизированы), что позволяет использовать копию практически моментально, не теряя данных вообще (это не учитывает сценарий ошибки администратора или разработчика! т.е. обычные резервные копии это не отменяет, но очень хорошо защищает от остальных проблем с оборудованием и связью).
Для файловых систем существует так же онлайн репликация (кластерные файловые системы), они так же позволяют делать онлайн копию на соседней машине, создавая таким образом оперативную копию, с возможностью ввести ее в строй после сбоя основной практически мгновенно (не советую размещать файлы базы данных тут).
Ну и конечно есть механизмы онлайн резервирования целой виртуальной машины, когда за резервирование системы в целом отвечает вииртуализация (заранее построенный отказоустойчивый распределенный кластер), возможно создание такой системы, что в момент сбоя даже не перестанет работать приложение, оно прозрачно и оперативно переедет на другую ноду в крастере.