Pull to refresh

Резервное копирование веб-проектов на Яндекс.Диск без ООП и натурщиц

Reading time 6 min
Views 40K
Позавчера хабраюзер vasiatka в посте №206752 поделился с хабрасообществом, а следовательно и со всем остальным миром, продуманным и весьма развитым классом для работы с Яндекс.Диском. Некоторое время назад я тоже стал использовать этот сервис для хранения там бэкапов. Хочу поделиться значительно более коротким вариантом скрипта на php, который делает архивы базы данных и файлов сайта, и заливает их по WebDAV. Возможно кому-то и он придётся по душе.

Если кто-то хочет сразу взглянуть на полный листинг — он внизу.

Описание


Скрипт, который я предлагаю вашему вниманию, довольно лаконичный. Если исключить задание параметров и вывод отчета, то останется что-то около тридцати строк. И хотя параметры и их названия говорят сами за себя, я всё же опишу их с комментариями.

С какими облаками работает этот скрипт


Так как загрузка файлов происходит по протоколу WebDAV, то скрипт должен уметь работать с любыми хранилищами такого рода.
Я протестировал только Яндекс и Mail.Ru, загрузка происходит успешно, но папку загрузки нужно создать на облаке заранее. На 2013.12.22 поддержка этого протокола у Mail.Ru нигде не афишируется, и заявлена только как работающая в тестовом режиме. Используйте с осторожностью.

Настройки


Логин и пароль, и путь на облаке

Логин указывается в полной форме, т.е. с собачкой и доменом. Пароль указывается как и любой уважающий себя пароль — целиком.
$WebDAV = [
  'login'=>'',
  'password'=>'',
  'url'=>'https://webdav.yandex.ru/backups/sites/',//для Яндекса
  'url'=>'https://webdav.cloud.mail.ru/backups/sites/',//для Mail.Ru
];
Путь к облаку и путь к целевой папке надо указывать целиком. Папку, куда вы планируете складывать свои драгоценные архивы, стоит создать самостоятельно заранее. Я проверил, и это точно, что она не сможет появиться автоматически. Если этого не сделать, загрузка всё равно будет идти. В случае Яндекса, судя по весу результата, загруженные файлы просто склеиваются в один большой. В случае Mail.Ru не появится ничего. Обязателен закрывающий слеш.

Локальный путь для создания архивов

Хотя архивацию и заливку на сервис можно сделать одной строкой, в моём скрипте прежде чем загрузить файл, требуется его где-то создать. Путь для создания архивов задаётся в этой переменной.
$backupPath

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

Список баз данных

Записывайте в массив $databases те базы, которые вы хотите архивировать. Вероятно стоит создать пользователя в БД без прав изменения и записи для такого использования.
$databases = [['login' => '', 'password' => '', 'dbname' => '']];


Список сайтов

Стандартный вид одного из членов массива $sites — списка архивируемых сайтов.
    'name' => 'site1.ru',
    'path' => '/var/www/site1.ru',
    'exclude' => []

Первый параметр — название сайта. Просто строка, которая будет приписываться к имени архива вашего сайта.
Второй — путь к файлам сайта.
Третий — список директорий, которые стоит исключить из архивации. Исключение отдельных файлов я не предусмотрел, но вы можете легко это добавить самостоятельно. Если вы создаёте архивы внутри одного из своих сайтов, то можете исключить это хранилище.
Пример:
    'exclude' => [
      $backupPath, //Исключить папку с бэкапами, если она находится внутри одного из сайтов
      '/var/www/site2.ru/temp' //Исключим что-нибудь еще
    ]


На этом конфигурация скрипта заканчивается, и он готов трудиться во благо революцииобщества… вебадмина.

Если база данных небольшая, а файлы весят не слишком много, то можно вызывать скрипт кроном хоть каждый час. Файлы с одинаковыми именами будут перезаписываться и в локальном хранилище, и на Яндекс.Диске. На следющий день будет создаваться файл с новой датой и примерно таким именем:
site1.ru.2013-12-20.zip
Если же вы хотите давать архивам уникальное имя каждый раз, то стоит заменить строку
$date = date('Y-m-d');
на
$date = date('Y-m-d-H-i-s');
и тогда дата будет с указанием времени вплоть до секунд.

Слушайте, и не говорите, что не слышали


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

Собственно всё


Спасибо, что уделили внимание и прочли этот пост. Надеюсь, кому-то моя поделка облегчит жизнь, душевное спокойствие, и даже возможно спасёт в тяжелую минуту. Удачи!

UPD: Спасибо lolipop за упоминание Mail.Ru. Изменил скрипт так, чтобы он работал и с их терабайтным хранилищем. Теперь будет, чем его забить! И хотя в ходе поисков поначалу я встречал информацию, что поддержки WebDAV у них нет, после я обнаружил упоминание нужного адреса тут. Пока только в тестовом режиме. Жаль, что это выяснилось только сейчас — у меня топик уже уплыл из списка новых. И те, кто его уже прочел, наверное об этом не узнают. А в свете акции с целым терабайтом места это весьма актуально.

UPD: Спасибо vk2 за правильное замечание, что ваш пароль и логин будет виден на сервере в списке процессов.

UPD: Спасибо kosenka, указал, что обязателен закрывающий слеш в пути WebDAV. Действительно, это же папка. Упустил я, но теперь исправил и в примере, и в скрипте.
Так же подсказал, что если curl ругается на сертификат, ему надо указать ключ -k, что позволит ему подключаться к сайтам без или с неправильным сертификатом.
Еще он справедливо заметил, что zip есть далеко не на каждом хостинге. Постараюсь добавить в ближайшее время строчку для кошерного gzip.

Полный листинг


$WebDAV = [
  'login'=>'',
  'password'=>'',
  //url включает в себя и путь к папке на облаке, в которую вы хотите залить свои файлы
  //'url'=>'https://webdav.yandex.ru/backups/sites/',//Папку обязательно нужно создать руками заранее, иначе загрузит всё в один файл.
  'url'=>'https://webdav.cloud.mail.ru/backups/sites/',//Папку обязательно нужно создать руками заранее, иначе загрузки не будет вообще.
];

$backupPath = 'path to backups'; //папка, куда складывать бэкапы локально на сервере, прежде чем залить по WebDAV
$databases = [['login' => '', 'password' => '', 'dbname' => '']];
$sites = [
//конфиг обычного сайта:
  [
    'name' => 'site1.ru',
    'path' => '/var/www/site1.ru',
    'exclude' => []
  ],
//конфиг с демонстрацией возможных вариантов
  ['name' => 'site2.ru',
    'path' => '.', //Вы можете использовать 'path' => '.' чтобы архивировать сайт, внутри которого лежит данный скрипт.
    'exclude' => [ //Если требуется исключить какие-то папки, то это можно сделать сдесь. Исключение отдельных файлов я не предусмотрел, но вы можете легко это добавить самостоятельно.
      $backupPath, //Исключить папку с бэкапами, если она находится внутри одного из сайтов
      '/var/www/site2.ru/temp' //Исключим что-нибудь еще
    ]
  ],
];
// Конфигурационная часть на этом заканчивается.
/////////////////////////////////////////////////////////////////////////////////////////
//Если не прописать в дату часы и минуты, то имена файлов будут совпадать, и файл на Яндекс.Диске будет перезаписан.
//Соотв. можно делать бэкап каждый час, при этом файлы не будут излишне плодиться.
//На следующий день будет создан новый файл.
$date = date('Y-m-d');
$errors = [];
$success = [];
$files_to_send = [];

foreach ($databases as $db) {
  $filename = "$backupPath/bases/{$db['dbname']}.$date.sql.gz";
  $output = `mysqldump --user={$db['login']} --password={$db['password']} {$db['dbname']} | gzip -f > $filename`;
  if (!file_exists($filename)) {
    $errors[] = 'Dump ' . $db['dbname'] . ' failed: ' . $output;
  } else {
    $success[] = 'DB ' . $db['dbname'] . ' dumped';
    $files_to_send[] = $filename;
  }
}

foreach ($sites as $site) {
  $filename = "$backupPath/files/{$site['name']}.$date.zip";
  $exclude = '';
  if ($site['exclude']) {
    $exclude = '-x ' . implode('\* -x ', $site['exclude']) . '\*';
  }
  $cmd = "zip -r \"$filename\"  {$site['path']} $exclude";
  echo $cmd . "<br>\n";
  $output = `$cmd`;
  if (!file_exists($filename)) {
    $errors[] = 'Site backup ' . $site['name'] . ' failed: ' . $output;
  } else {
    $success[] = 'Site ' . $site['name'] . ' saved';
    $files_to_send[] = $filename;
  }
}

foreach ($errors as $e) {
  echo 'Ошибка: ' . $e . "<br>\n";
}
echo "<br>\n";

foreach ($success as $s) {
  echo 'ОК: ' . $s . "<br>\n";
}
echo "<br>\n";

echo "Следующие файлы будут загружены:<br>\n";
foreach ($files_to_send as $f) {
  echo $f . "<br>\n";
}
echo "<br>\n";

if (!empty($files_to_send)) {
  foreach ($files_to_send as $file) {
    echo shell_exec("curl --user {$WebDAV['login']}:{$WebDAV['password']} -T \"$file\" {$WebDAV['url']}") . "<br>\n";//если ругается на сертификат, можно добавить ключ -k
  }
}

К началу поста ↑
Tags:
Hubs:
+42
Comments 48
Comments Comments 48

Articles