Резервные копии на Яндекс.Диск

Цель нашей компании - предложение широкого ассортимента услуг на постоянно высоком качестве обслуживания.

Задать вопрос
Наши специалисты ответят на любой интересующий вопрос по услуге

Выкладывать бекапы проектов (сайтов) на Яндекс.Диск может понадобиться по нескольким причинам, например, из-за нехватки места на сервере (хостинге, VDS, VPS) или для повышения безопасности хранения бекапов (на случай, если сервер без рейда и он выйдет из строя).

В связи с этим я написал для себя и решил выложить для других небольшой bash-скрипт для бекапа на Яндекс.Диск. Функции скрипта:
— Создание на сервере бекапа проектов (файлов + баз данных MySQL);
— Авторизация на Яндекс.Диске в качестве приложения (по токену, более безопасный способ, чем использование логина и пароля);
— Отправка бекапов с сервера на Яндекс.Диск;
— Удаление старых бекапов с Яндекс.Диска для экономии места (настраивается максимальное количество хранимых бекапов);
— Запись и отправка лога на e-mail (настраивается).

Для того, чтобы воспользоваться скриптом, необходимо сначала получить токен от Яндекс.Диска. Приступим.

1. Логинимся на Яндексе под аккаунтом, на диск которого будем делать бекап, заходим на oauth.yandex.ru и нажимаем «Зарегистрировать новое приложение».

Яндекс.Диск - регистрация нового приложения

2. Заполняем название приложения (например, «backup») и выдаём нужные права в разделе «Яндекс.Диск REST API», а именно: «Доступ к информации о Диске» и «Доступ к папке приложения на Диске».

Яндекс.Диск - предоставление прав приложению

Ниже на той же странице под полем «Callback URL» нажимаем «подставить URL для разработки» и нажимаем «Сохранить»:

Яндекс.Диск - Callback URL

3. После сохранения параметров приложения нас перенаправят на страницу с данными о приложении:

Яндекс.Диск - данные приложения

4. Теперь получим сам токен (если хотите, можете почитать подробнее об этом в мануале Яндекса), для этого копируем ID, подставляем в конец URL https://oauth.yandex.ru/authorize?response_type=token&client_id=, переходим по получившемуся адресу и подтверждаем выдачу разрешений приложению:

Яндекс.Диск - разрешения приложения

В итоге на странице будет отображён токен, который выдается не менее, чем на 1 год, поэтому если скрипт бекапа вдруг перестанет работать, мы сможем получить новый токет и подставить его в скрипт. Протестировать возможности работы с Яндекс.Диском, используя полученный токен, можно на специальном полигоне.

А теперь сам bash-скрипт для бекапа на Яндекс.Диск:

#!/bin/bash
#
# Yandex.Disk backup script v1.0 by Sergey Lukonin (neblog.info)
#
# # # # # # # # # # НАСТРОЙКИ БЕКАПА MYSQL # # # # # # # # # #

# Сервер БД
MYSQL_SERVER=mysql.some-server.ru

# Юзер, под которым будем делать бекап доступных баз, руту mysql обычно доступны все БД, отдельному пользователю обычно доступна БД конкретного проекта
MYSQL_USER=some-user

# Пароль пользователя базы данных (Пароль от рута сервера и от рута mysql разные не путайте)
MYSQL_PASSWORD=some-password

# # # # # # # # # # ОБЩИЕ НАСТРОЙКИ # # # # # # # # # #

# Директория для временного хранения бекапов, которые удаляются после отправки на Яндекс.Диск
BACKUP_DIR='/home/www/backup'

# Название проекта, используется в логах и именах архивов
PROJECT='neblog.info'

# Максимальное количество хранимых на Яндекс.Диске бекапов (0 - хранить все бекапы):
MAX_BACKUPS='14'

# Дата, используется в именах архивов
DATE=`date '+%Y-%m-%d'`

# Директории для архивации (указываются через пробел), которые будут помещены в единый архив и отправлены на Яндекс.Диск
DIRS='/home/www/projects/neblog'

# Yandex.Disk токен (как получить - см. на neblog.info)
TOKEN=''

# Имя лог-файла, хранится в директории, указанной в $BACKUP_DIR
LOGFILE='backup.log'

# E-mail для отправки результата выполнения скрипта. Оставьте пустым, если отправлять результаты не требуется.
sendLog='your-mail@yandex.ru'

# Отправлять только ошибки (true). Укажите false, если нужно отправлять логи при любом результате выполнения скрипта.
sendLogErrorsOnly='false'

# # # # # # # # # # КОНЕЦ НАСТРОЕК # # # # # # # # # # # # # 
# # # # # # # # ДАЛЬШЕ НИЧЕГО НЕ МЕНЯЕМ! # # # # # # # # # #

function mailing()
{
    if [ ! $sendLog = '' ];then
        if [ "$sendLogErrorsOnly" == true ];
        then
            if echo "$1" | grep -q 'error'
            then   
                echo "$2" | mail -s "$1" $sendLog > /dev/null
            fi
        else
            echo "$2" | mail -s "$1" $sendLog > /dev/null
        fi
    fi
}

function logger()
{
    echo "["`date "+%Y-%m-%d %H:%M:%S"`"] File $BACKUP_DIR: $1" >> $BACKUP_DIR/$LOGFILE
}

function parseJson()
{
    local output
    regex="(\"$1\":[\"]?)([^\",\}]+)([\"]?)"
    [[ $2 =~ $regex ]] && output=${BASH_REMATCH[2]}
    echo $output
}

function checkError()
{
    echo $(parseJson 'error' "$1")
}

function getUploadUrl()
{
    json_out=`curl -s -H "Authorization: OAuth $TOKEN" https://cloud-api.yandex.net:443/v1/disk/resources/upload/?path=app:/$backupName&overwrite=true`
    json_error=$(checkError "$json_out")
    if [[ $json_error != '' ]];
    then
        logger "$PROJECT - Yandex.Disk error: $json_error"
        mailing "$PROJECT - Yandex.Disk backup error" "ERROR copy file $FILENAME. Yandex.Disk error: $json_error"
    echo ''
    else
        output=$(parseJson 'href' $json_out)
        echo $output
    fi
}

function uploadFile
{
    local json_out
    local uploadUrl
    local json_error
    uploadUrl=$(getUploadUrl)
    if [[ $uploadUrl != '' ]];
    then
    echo $UploadUrl
        json_out=`curl -s -T $1 -H "Authorization: OAuth $TOKEN" $uploadUrl`
        json_error=$(checkError "$json_out")
    if [[ $json_error != '' ]];
    then
        logger "$PROJECT - Yandex.Disk error: $json_error"
        mailing "$PROJECT - Yandex.Disk backup error" "ERROR copy file $FILENAME. Yandex.Disk error: $json_error"

    else
        logger "$PROJECT - Copying file to Yandex.Disk success"
        mailing "$PROJECT - Yandex.Disk backup success" "SUCCESS copy file $FILENAME"

    fi
    else
    	echo 'Some errors occured. Check log file for detail'
    fi
}

function backups_list() {
    # Ищем в директории приложения все файлы бекапов и выводим их названия:
    curl -s -H "Authorization: OAuth $TOKEN" "https://cloud-api.yandex.net:443/v1/disk/resources?path=app:/&sort=created&limit=100" | tr "{},[]" "\n" | grep "name[[:graph:]]*.tar.gz" | cut -d: -f 2 | tr -d '"'
}

function backups_count() {
    local bkps=$(backups_list | wc -l)
    # Если мы бекапим и файлы, и БД, то на 1 бекап у нас приходится 2 файла. Поэтому количество бекапов = количество файлов / 2:
    expr $bkps / 2
}

function remove_old_backups() {
    bkps=$(backups_count)
    old_bkps=$((bkps - MAX_BACKUPS))
    if [ "$old_bkps" -gt "0" ];then
        logger "Удаляем старые бекапы с Яндекс.Диска"
        # Цикл удаления старых бекапов:
        # Выполняем удаление первого в списке файла 2*old_bkps раз
        for i in `eval echo {1..$((old_bkps * 2))}`; do
            curl -X DELETE -s -H "Authorization: OAuth $TOKEN" "https://cloud-api.yandex.net:443/v1/disk/resources?path=app:/$(backups_list | awk '(NR == 1)')&permanently=true"
        done
    fi
}

logger "--- $PROJECT START BACKUP $DATE ---"
logger "Выгружаем дампы баз"
mkdir $BACKUP_DIR/$DATE
for i in `mysql -h $MYSQL_SERVER -u $MYSQL_USER -p$MYSQL_PASSWORD -e'show databases;' | grep -v information_schema | grep -v Database`;
    do mysqldump -h $MYSQL_SERVER -u $MYSQL_USER -p$MYSQL_PASSWORD $i > $BACKUP_DIR/$DATE/$i.sql;
done

logger "Создаем архив mysql $BACKUP_DIR/$DATE-mysql-$PROJECT.tar.gz"
tar -czf $BACKUP_DIR/$DATE-mysql-$PROJECT.tar.gz $BACKUP_DIR/$DATE
rm -rf $BACKUP_DIR/$DATE

logger "Создаем архив каталогов $BACKUP_DIR/$DATE-files-$PROJECT.tar.gz"
tar -czf $BACKUP_DIR/$DATE-files-$PROJECT.tar.gz $DIRS

FILENAME=$DATE-mysql-$PROJECT.tar.gz
logger "Выгружаем на Яндекс.Диск архив mysql $BACKUP_DIR/$DATE-mysql-$PROJECT.tar.gz"
backupName=$DATE-mysql-$PROJECT.tar.gz
uploadFile $BACKUP_DIR/$DATE-mysql-$PROJECT.tar.gz

FILENAME=$DATE-files-$PROJECT.tar.gz
logger "Выгружаем на Яндекс.Диск архив с файлами $BACKUP_DIR/$DATE-files-$PROJECT.tar.gz"
backupName=$DATE-files-$PROJECT.tar.gz
uploadFile $BACKUP_DIR/$DATE-files-$PROJECT.tar.gz

logger "Удаляем архивы с диска"
find $BACKUP_DIR -type f -name "*.gz" -exec rm '{}' \;

# Удаляем старые бекапы с Яндекс.Диска (если MAX_BACKUPS > 0)
if [ $MAX_BACKUPS -gt 0 ];then remove_old_backups; fi

logger "Завершение скрипта бекапа"

Также вы можете скачать готовый файл скрипта. Скрипт следует расположить на сервере, заменить в нём параметры на свои, дать права на запуск (chmod +x) и поставить на ежедневное выполнение в cron. Если вы планируете выполнять несколько таких заданий, задайте время между их запуском (5-10 минут).


Источник

Заказать услугу
Оформите заявку на сайте, мы свяжемся с вами в ближайшее время и ответим на все интересующие вопросы.