Резервное копирование сайтов в Яндекс Диск



Благодаря статье Михаила Воеводского заметил, что тема резервного копирования востребована в сообществе. Решил поделиться своим скриптом резервного копирования написанным на Python. Примечателен он тем, что полностью удовлетворяет закону импортозамещения заливает файлы на Яндекс Диск, раскладывая их по папочкам вида ГГГГ-ММ-ДД. Это не все его приятные особенности, вот список:

  • Умеет удалять старые бекапы с ЯДиска, если они старее чем N дней (настраивается в config.yaml)
  • Умеет удалять старые логи с сервера
  • Раскладывает бекапы на ЯДиске по папкам вида: ГГГГ-ММ-ДД
  • Бекапит системные папки: /etc/, /var/log/, /root/

В итоге, на Яндекс Диске, в папке для бекапов указанной в config.yaml, мы получаем список файлов, похожий на этот:

Не обращайте внимания на имена пользователей u1-u15 — это у меня на сервере панелька назначает их автоматически. Если вы называете пользователей в системе по-другому, то и на Яндекс Диске они будут называться также.

Примечание

Сервер обязательно должен быть настроен по этой инструкции:

  • На каждый сайт создаётся свой пользователь в системе (1 сайт = 1 пользователь)
  • Все сайты-пользователи располагаются в /var/www/
  • Имя пользователя сайта, название и имя пользователя БД одинаковые

Инструкция по установке в Linux Ubuntu, Debian и т.п.

У вас уже должен быть установлен на сервере Python 3.

  1. Устанавливаем менеджер пакетов для Python 3:
    apt-get install python3-pip
  2. Устанавливаем пакеты для Python, от которых зависим скрипт:
    pip3 install requests
    pip3 install pyyaml
  3. Закидываем папку с бекапером куда-нибудь на сервер, например в /root/scripts/py/
  4. Настраиваем config.yaml. В конфиге указывается:
    • Имя/пароль mysql root
    • Имя/пароль от Яндекс Диска
    • Временная папка, в которую закидывать бекапы на сервере
    • Папка на Яндекс Диске, где будут лежать бекапы
    • Что бекапить (системные папки, базу, файлы)
    • Удалять ли старые логи
    • Сколько дней хранить бекапы на Яндекс Диске (более старые будут удаляться)
    На самом деле файл config.yaml хорошо оснащён комментариями (благо формат yaml позволяет), поэтому разобраться там будет совершенно легко.
  5. Вызываем
    sudo crontab -e
    и прописываем ежедневный запуск в 2 часа ночи:
    0 2 * * * /usr/bin/env python3 /root/scripts/py/YaDiskBackuper/backuper.py

Вот собственно и всё. Теперь вы можете запустить скрипт и проверить, корректно ли он работает. В консоли от рута запускаем:
sudo python3 /root/scripts/py/YaDiskBackuper/backuper.py
Замените путь до скрипта на свой.

На сервере заходим во временную папку с бекапами, заходим на Яндекс Диск и наблюдаем, появляются ли там файлы.
26 june 2016, 14:04    Павел Гвоздь   
26    1079 +14

Comments (18)

  1. Наумов Алексей 27 june 2016, 11:19 # 0
    Привет! Попробовал. При запуске руками из консоли через пару секунд увидел сообщение «Enter password:».

    Проверил пароли, вроде все верно… Это к чему запрос относится? Файлы, кстати, на Яндекс.Диск начали появляться… логи и папка etc по крайней мере :)
    1. Павел Гвоздь 27 june 2016, 11:33 # 0
      Привет! Странно, сейчас проверил у себя, запроса нет. Может пароль от root юзера просит? Потому что в скриптах такого запроса нет.
      А файлы сайтов и базы появились на Яндекс Диске?
      1. Наумов Алексей 27 june 2016, 11:53 # 0
        Да, они начали появляться, правда я потом консоль закрыл и все остановилось :)

        Решил подождать пока сработает крон…
    2. Алексей Добряков 27 june 2016, 21:25 # 0
      Можно сделать проще без установки питонов
      1. Павел Гвоздь 27 june 2016, 22:05 # 0
        Как на счёт подробностей?
      2. Alex Vakhitov 28 june 2016, 16:58 # 0
        По моему лучше было бы загрузить пакет в pypi и сделать скрипт исполняемым, чтобы не мучатся. Ну и провести рефакторинг чтобы все работало на python 2, тогда сразу на любой версии ubuntu можно будет запускать. Ну и исправить нейминг :) уже давно не видел кэмэлкейс в именах файлов и модулей, а лучше просто добавить этот пакет который вы используете как зависимость
        1. Павел Гвоздь 28 june 2016, 17:01 # 0
          Покажи, как надо, пожалуйста, в соседнем топике.
          1. Alex Vakhitov 28 june 2016, 17:12 # +1
            Ну показывать если честно лень, для себя мне это не нужно учитывая что есть официальный консольный ЯД, и таки вещи по мне проще реализовать на bash. Но решение имеет право на жизнь и каждый пункт можно легко реализовать с помощью гугла, пофакту нужно просто настроить все в setup.py прри формирования пакетаю
        2. Наумов Алексей 17 august 2016, 10:32 # 0
          Привет!
          Есть небольшая проблемка, не сохраняются бекапы баз, файлы все ок, а вот баз нет.

          Пароль в конфиге root пользователя проверил 3-ды, верный.

          Куда еще посмотреть можно?..
          1. Павел Гвоздь 17 august 2016, 17:12 # +1
            Можно попробовать вручную подобную операцию проделать в терминале сервера:

            mysqldump --skip-lock-tables -u[[+mysqlUser]] -p[[+mysqlPassword]] [[+dbName]] | bzip2 -c > filename.sql.bz2
            1. Наумов Алексей 18 august 2016, 09:39 # +1
              Попробовал, увидел ошибку… связанную с тем, что мой пароль начинается с символа "&", экранирует ли скрипт пароль при выполнении команды? Может быть в этом дело?, см. superuser.com/questions/123928/escaping-a-password-using-mysqldump-console
              1. Наумов Алексей 18 august 2016, 09:40 # +1
                Ну а сама команда, когда я заключил пароль в кавычки, выполнилась успешно.
                1. Павел Гвоздь 19 august 2016, 09:13 # 0
                  Об этом речь? — github.com/gvozdb/YaDiskBackuper/commit/45dc46e5967b99a4322c74a129573e9c1c019661

                  Сообщи, пожалуйста, когда проверишь скрипт.
                  1. Наумов Алексей 19 august 2016, 09:19 # 0
                    Да, про это.

                    Бекапы раз в неделю)

                    Сообщу позже, если не забуду)))
            2. Воеводский Михаил 28 january 2017, 18:15 # 0
              Сталкивался ли кто-нибудь с ошибкой выполнения скрипта?

              Есть 2 сервера на Ubuntu 16.04.1, настроенные аналогично, отличия в них:
              1) На площадке Flops с установленной по умолчанию системой для работы в облаке
              2) Выделенный сервер на другой площадке с системой, установленной из официального образа

              В первом случае скрипт создания бэкапов вываливается с ошибками, во втором работает без запинки.
              На обоих серверах python3 версии 3.5.1-3, модуль requests версии 2.13.0.

              Вывод ошибок:
              # python3 /root/scripts/py/YaDiskBackuper/backuper.py
              Traceback (most recent call last):
              File "/usr/local/lib/python3.5/dist-packages/requests/utils.py", line 792, in check_header_validity
              if not pat.match(value):
              TypeError: expected string or bytes-like object
              During handling of the above exception, another exception occurred:
              Traceback (most recent call last):
              File "/root/scripts/py/YaDiskBackuper/backuper.py", line 72, in <module>
              disk.ls( path_webdav_today )
              File "/root/scripts/py/YaDiskBackuper/YaDiskClient/YaDiskClient.py", line 83, in ls
              resp = self._sendRequest("PROPFIND", path, {'Depth': 1})
              File "/root/scripts/py/YaDiskBackuper/YaDiskClient/YaDiskClient.py", line 54, in _sendRequest
              return s.send(req.prepare())
              File "/usr/local/lib/python3.5/dist-packages/requests/models.py", line 257, in prepare
              hooks=self.hooks,
              File "/usr/local/lib/python3.5/dist-packages/requests/models.py", line 303, in prepare
              self.prepare_headers(headers)
              File "/usr/local/lib/python3.5/dist-packages/requests/models.py", line 443, in prepare_headers
              check_header_validity(header)
              File "/usr/local/lib/python3.5/dist-packages/requests/utils.py", line 796, in check_header_validity
              "not %s" % (value, type(value)))
              requests.exceptions.InvalidHeader: Header value 1 must be of type str or bytes, not <class 'int'>
              Поддержка Flops ничего существенного, естественно не говорит, ибо речь идет не только о стандартном ПО из пакетов.
              Поскольку Питон не знаю от слова совсем, отладка превращается почти в метод научного тыка. Понимаю лишь общую логику выполнения, не более того.

              Надеюсь на помощь более опытных в Питоне товарищей.
              1. Наумов Алексей 05 march 2017, 21:13 # 0
                Павел, привет.

                А можно спросить совета о доработке, как выкинуть из бекапа некоторые жестко прописанные директории?
                У меня есть сайт (среди десятков других на сервере), где имеется фото архив на несколько Гб, не хочу его бекапить каждый раз. Как бы прописать эту директорию в игнор? Т.е. сам сайт пусть идет в бекап, но без этой директории с фотографиями.
                1. Павел Гвоздь 06 march 2017, 22:42 # +2
                  На самом деле особо великой сложности нет. Я бы создал файлик в корне юзера, в котором бы указывалось, какие папки исключать при запаковке, в формате: 1 строка — 1 директория. А на стороне бекапера получал бы содержимое этого файла и передавал необходимые параметры (--exclude="") в tar.
                  1. Наумов Алексей 07 march 2017, 09:28 # 0
                    Благодарю за наводку!
                    Теперь с питоном разобраться бы)
                You need to login to create comments.