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

Благодаря статье Михаила Воеводского заметил, что тема резервного копирования востребована в сообществе. Решил поделиться своим скриптом резервного копирования написанным на Python. Примечателен он тем, что
- Умеет удалять старые бекапы с ЯДиска, если они старее чем N дней (настраивается в config.yaml)
 - Умеет удалять старые логи с сервера
 - Раскладывает бекапы на ЯДиске по папкам вида: ГГГГ-ММ-ДД
 - Бекапит системные папки: /etc/, /var/log/, /root/
 
В итоге, на Яндекс Диске, в папке для бекапов указанной в config.yaml, мы получаем список файлов, похожий на этот:

Не обращайте внимания на имена пользователей u1-u15 — это у меня на сервере панелька назначает их автоматически. Если вы называете пользователей в системе по-другому, то и на Яндекс Диске они будут называться также.
Примечание
Сервер обязательно должен быть настроен по этой инструкции:
- На каждый сайт создаётся свой пользователь в системе (1 сайт = 1 пользователь)
 - Все сайты-пользователи располагаются в /var/www/
 - Имя пользователя сайта, название и имя пользователя БД одинаковые
 
Инструкция по установке в Linux Ubuntu, Debian и т.п.
У вас уже должен быть установлен на сервере Python 3.
- Устанавливаем менеджер пакетов для Python 3:
apt-get install python3-pip - Устанавливаем пакеты для Python, от которых зависим скрипт:
pip3 install requests pip3 install pyyaml - Закидываем папку с бекапером куда-нибудь на сервер, например в /root/scripts/py/
 - Настраиваем config.yaml. В конфиге указывается:
- Имя/пароль mysql root
 - Имя/пароль от Яндекс Диска
 - Временная папка, в которую закидывать бекапы на сервере
 - Папка на Яндекс Диске, где будут лежать бекапы
 - Что бекапить (системные папки, базу, файлы)
 - Удалять ли старые логи
 - Сколько дней хранить бекапы на Яндекс Диске (более старые будут удаляться)
 
 - Вызываем
и прописываем ежедневный запуск в 2 часа ночи:sudo crontab -e
0 2 * * * /usr/bin/env python3 /root/scripts/py/YaDiskBackuper/backuper.py 
Вот собственно и всё. Теперь вы можете запустить скрипт и проверить, корректно ли он работает. В консоли от рута запускаем:
sudo python3 /root/scripts/py/YaDiskBackuper/backuper.pyЗамените путь до скрипта на свой.На сервере заходим во временную папку с бекапами, заходим на Яндекс Диск и наблюдаем, появляются ли там файлы.
            
                Поблагодарить автора            
            
                 Отправить деньги            
        
        
            Комментарии: 22
                Привет! Попробовал. При запуске руками из консоли через пару секунд увидел сообщение «Enter password:».
Проверил пароли, вроде все верно… Это к чему запрос относится? Файлы, кстати, на Яндекс.Диск начали появляться… логи и папка etc по крайней мере :)
                    Проверил пароли, вроде все верно… Это к чему запрос относится? Файлы, кстати, на Яндекс.Диск начали появляться… логи и папка etc по крайней мере :)
                Привет! Странно, сейчас проверил у себя, запроса нет. Может пароль от root юзера просит? Потому что в скриптах такого запроса нет.
А файлы сайтов и базы появились на Яндекс Диске?
                    А файлы сайтов и базы появились на Яндекс Диске?
                Да, они начали появляться, правда я потом консоль закрыл и все остановилось :)
Решил подождать пока сработает крон…
                    Решил подождать пока сработает крон…
                Можно сделать проще без установки питонов            
                    
                Как на счёт подробностей?            
                    
                По моему лучше было бы загрузить пакет в pypi и сделать скрипт исполняемым, чтобы не мучатся. Ну и провести рефакторинг чтобы все работало на python 2, тогда сразу на любой версии ubuntu можно будет запускать. Ну и исправить нейминг :) уже давно не видел кэмэлкейс в именах файлов и модулей, а лучше просто добавить этот пакет который вы используете как зависимость            
                    
                Покажи, как надо, пожалуйста, в соседнем топике.            
                    
                Ну показывать если честно лень, для себя мне это не нужно учитывая что есть официальный консольный ЯД, и таки вещи по мне проще реализовать на bash. Но решение имеет право на жизнь и каждый пункт можно легко реализовать с помощью гугла, пофакту нужно просто настроить все в setup.py прри формирования пакетаю            
                    
                Привет!
Есть небольшая проблемка, не сохраняются бекапы баз, файлы все ок, а вот баз нет.
Пароль в конфиге root пользователя проверил 3-ды, верный.
Куда еще посмотреть можно?..
                    Есть небольшая проблемка, не сохраняются бекапы баз, файлы все ок, а вот баз нет.
Пароль в конфиге root пользователя проверил 3-ды, верный.
Куда еще посмотреть можно?..
                Можно попробовать вручную подобную операцию проделать в терминале сервера:
                    mysqldump --skip-lock-tables -u[[+mysqlUser]] -p[[+mysqlPassword]] [[+dbName]] | bzip2 -c > filename.sql.bz2            
                Попробовал, увидел ошибку… связанную с тем, что мой пароль начинается с символа "&", экранирует ли скрипт пароль при выполнении команды? Может быть в этом дело?, см. superuser.com/questions/123928/escaping-a-password-using-mysqldump-console            
                    
                Ну а сама команда, когда я заключил пароль в кавычки, выполнилась успешно.            
                    
                Об этом речь? — github.com/gvozdb/YaDiskBackuper/commit/45dc46e5967b99a4322c74a129573e9c1c019661
Сообщи, пожалуйста, когда проверишь скрипт.
                    Сообщи, пожалуйста, когда проверишь скрипт.
                Да, про это.
Бекапы раз в неделю)
Сообщу позже, если не забуду)))
                    Бекапы раз в неделю)
Сообщу позже, если не забуду)))
                Сталкивался ли кто-нибудь с ошибкой выполнения скрипта? 
Есть 2 сервера на Ubuntu 16.04.1, настроенные аналогично, отличия в них:
1) На площадке Flops с установленной по умолчанию системой для работы в облаке
2) Выделенный сервер на другой площадке с системой, установленной из официального образа
В первом случае скрипт создания бэкапов вываливается с ошибками, во втором работает без запинки.
На обоих серверах python3 версии 3.5.1-3, модуль requests версии 2.13.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 ничего существенного, естественно не говорит, ибо речь идет не только о стандартном ПО из пакетов.Поскольку Питон не знаю от слова совсем, отладка превращается почти в метод научного тыка. Понимаю лишь общую логику выполнения, не более того.
Надеюсь на помощь более опытных в Питоне товарищей.
                После очередного обновления системы, стала появляться такая же ошибка.
Проанализировав логи, оказалось, что данный скрипт не работает с модулем requests версии 2.13.
Помог откат модуля до версии 2.10
                    Проанализировав логи, оказалось, что данный скрипт не работает с модулем requests версии 2.13.
Помог откат модуля до версии 2.10
pip3 install requests==2.10            
                Семен, огромное спасибо!            
                    
                Павел, привет.
А можно спросить совета о доработке, как выкинуть из бекапа некоторые жестко прописанные директории?
У меня есть сайт (среди десятков других на сервере), где имеется фото архив на несколько Гб, не хочу его бекапить каждый раз. Как бы прописать эту директорию в игнор? Т.е. сам сайт пусть идет в бекап, но без этой директории с фотографиями.
                    А можно спросить совета о доработке, как выкинуть из бекапа некоторые жестко прописанные директории?
У меня есть сайт (среди десятков других на сервере), где имеется фото архив на несколько Гб, не хочу его бекапить каждый раз. Как бы прописать эту директорию в игнор? Т.е. сам сайт пусть идет в бекап, но без этой директории с фотографиями.
                На самом деле особо великой сложности нет. Я бы создал файлик в корне юзера, в котором бы указывалось, какие папки исключать при запаковке, в формате: 1 строка — 1 директория. А на стороне бекапера получал бы содержимое этого файла и передавал необходимые параметры (--exclude="") в tar.            
                    
                Благодарю за наводку!
Теперь с питоном разобраться бы)
                    Теперь с питоном разобраться бы)
Traceback (most recent call last):
  File "/root/scripts/py/YaDiskBackuper/backuper.py", line 30, in <module>
    config = yaml.load( config_f )
  File "/usr/local/lib/python3.5/dist-packages/yaml/__init__.py", line 70, in load
    loader = Loader(stream)
  File "/usr/local/lib/python3.5/dist-packages/yaml/loader.py", line 34, in __init__
    Reader.__init__(self, stream)
  File "/usr/local/lib/python3.5/dist-packages/yaml/reader.py", line 85, in __init__
    self.determine_encoding()
  File "/usr/local/lib/python3.5/dist-packages/yaml/reader.py", line 135, in determine_encoding
    self.update(1)
  File "/usr/local/lib/python3.5/dist-packages/yaml/reader.py", line 169, in update
    self.check_printable(data)
  File "/usr/local/lib/python3.5/dist-packages/yaml/reader.py", line 144, in check_printable
    'unicode', "special characters are not allowed")
yaml.reader.ReaderError: unacceptable character #x009f: special characters are not allowed
  in "/root/scripts/py/YaDiskBackuper/config.yaml", position 118Была вот такая ошибка из-за русских коментов в файле config.yaml, может версия у меня старая, не знаю            
                            Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.