← Back to list

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

Хочу поделиться коротким вариантом скрипта на PHP, который делает архивы базы данных и файлов сайта, и заливает их по WebDAV. Возможно…

Igor Data · 2017-01-23 03:07 · 1 claps · 4.6 min read
#php #backup #yandex-disk #webdav
Open on Medium ↗

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

Хочу поделиться коротким вариантом скрипта на 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
  }
}

메타데이터
post_id
a9710bc0853a
slug
резервное-копирование-веб-проектов-на-яндекс-диск-без-ооп-и-натурщиц-a9710bc0853a
url
https://medium.com/@igordata/%D1%80%D0%B5%D0%B7%D0%B5%D1%80%D0%B2%D0%BD%D0%BE%D0%B5-%D0%BA%D0%BE%D0%BF%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5-%D0%B2%D0%B5%D0%B1-%D0%BF%D1%80%D0%BE%D0%B5%D0%BA%D1%82%D0%BE%D0%B2-%D0%BD%D0%B0-%D1%8F%D0%BD%D0%B4%D0%B5%D0%BA%D1%81-%D0%B4%D0%B8%D1%81%D0%BA-%D0%B1%D0%B5%D0%B7-%D0%BE%D0%BE%D0%BF-%D0%B8-%D0%BD%D0%B0%D1%82%D1%83%D1%80%D1%89%D0%B8%D1%86-a9710bc0853a
canonical_url
https://medium.com/@igordata/%D1%80%D0%B5%D0%B7%D0%B5%D1%80%D0%B2%D0%BD%D0%BE%D0%B5-%D0%BA%D0%BE%D0%BF%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5-%D0%B2%D0%B5%D0%B1-%D0%BF%D1%80%D0%BE%D0%B5%D0%BA%D1%82%D0%BE%D0%B2-%D0%BD%D0%B0-%D1%8F%D0%BD%D0%B4%D0%B5%D0%BA%D1%81-%D0%B4%D0%B8%D1%81%D0%BA-%D0%B1%D0%B5%D0%B7-%D0%BE%D0%BE%D0%BF-%D0%B8-%D0%BD%D0%B0%D1%82%D1%83%D1%80%D1%89%D0%B8%D1%86-a9710bc0853a
author_url
https://medium.com/@igordata
status
ok
fetched_at
2026-06-25 12:15:08