Автоматизировать бэкапы сервера

Примеры инструментов для работы с Объектным хранилищем:

В инструкции приведен пример создания скрипта, который будет регулярно запускать консольный клиент, архивировать и переносить важные данные в Объектное хранилище.

Требования для выполнения примера

В качестве консольного клиента используем S3cmd с инструментом для автоматизации crontab.

Для начала работы потребуется:

  1. Облачный или выделенный сервер с установленной Ubuntu версии не ниже 18.04.
  2. Новый пользователь Объектного хранилища.
  3. Настроенный S3cmd.

Создать скрипт для резервного копирования

Скрипт создаст резервную копию файла или каталога с помощью tar и загрузит резервную копию в Объектное хранилище с помощью s3cmd.

  1. Откройте на своем сервере домашнюю директорию:

    cd ~
  2. С помощью редактора nano создайте пустой файл, например, с именем bkupscript:

    nano bkupscript.sh
  3. Начните писать скрипт резервного копирования в текстовом редакторе с шебанга. Шебанг — это директива интерпретатора, которая позволяет запускать скрипты или файлы данных как команды и выглядит как последовательность из двух символов: решетки и восклицательного знака. Включая шебанг в начало скрипта, мы говорим оболочке запускать команды файла в bash.

    #!/bin/bash

    Назначить переменные

    Добавьте в скрипт переменные прямо под шебангом в верхней части текстового файла:

    #!/bin/bash
    
    DATETIME=`date +%y%m%d-%H_%M_%S`
    SRC=$1
    DST=$2
    GIVENNAME=$3

Где:

  • DATETIME содержит метку времени, которую нужно прикрепить к имени полученного файла, чтобы каждый файл, резервная копия которого хранится в пространстве, имел уникальное имя. Эта временная метка создается путем вызова команды date и форматирования вывода для отображения двух последних цифр года (% y), двух цифр месяца (% m), двух цифр дня (% d), час (% H), минуты (% M) и секунды (% S);
  • SRC — это исходный путь для файла или папки, в которую мы делаем резервную копию. $1 указывает, что мы берем это значение из первого параметра, переданного скрипту;
  • DST — место назначения файла. В нашем случае это имя пространства, в которое мы загружаем резервную копию. Это имя будет получено из второго параметра, переданного в скрипт, как указано в $2;
  • GIVENNAME — выбранное пользователем имя для файла назначения. Результирующее имя файла будет начинаться с GIVENNAME, и к нему будет добавлено DATETIME. Это имя происходит от третьего параметра, переданного скрипту $3.

Вывести сообщения

Добавьте функцию showhelp в скрипт резервного копирования для вывода сообщений в случае сбоя работы скрипта:

#!/bin/bash

DATETIME=`date +%y%m%d-%H_%M_%S`
SRC=$1
DST=$2
GIVENNAME=$3

showhelp(
        echo "\n This script will backup files/folders into a single compressed file and will store it in the current folder."
}

Собрать файлы

Прежде чем скрипт сможет передавать что-либо в выбранное пространство, ему сначала необходимо собрать нужные файлы и объединить их в единый пакет, который мы можем загрузить. Это выполняется с помощью утилиты tar, условных операторов и функции tarandzip:

#!/bin/bash

DATETIME=`date +%y%m%d-%H_%M_%S`
SRC=$1
DST=$2
GIVENNAME=$3

showhelp(
        echo "\n This script will backup files/folders into a single compressed file and will store it in the current folder."
){

}

tarandzip(){
    echo "\n##### Gathering files #####\n"
    tar -czvf $GIVENNAME-$DATETIME.tar.gz $SRC
}

Когда вызывается инструкция if, скрипт выполняет команду tar и ожидает результата. Если команда выполнена успешно, будут выполнены строки после оператора then:

  • вывод сообщения о том, что процесс tar успешно завершился;
  • возвращение кода ошибки 0, чтобы часть кода, вызывающая эту функцию, знала, что все работает нормально.

Часть else этого скрипта будет выполняться только в том случае, если команда tar обнаружит ошибку при выполнении:

  • вывод сообщения о том, что команда tar не выполнена;
  • возвращение кода ошибки 1, что указывает на то, что что-то пошло не так.

Заканчивайте скрипт if/then/else фразой fi, что на языке bash означает, что предложение if закончилось.

Завершенная функция tarandzip будет выглядеть так:

tarandzip(){
    echo "\n##### Gathering files #####\n"
    if tar -czvf $GIVENNAME-$DATETIME.tar.gz $SRC; then
        echo "\n##### Done gathering files #####\n"
        return 0
    else
        echo "\n##### Failed to gather files #####\n"
        return 1
    fi
}

Перенести файлы в Объектное хранилище

Добавим в скрипт резервного копирования функцию передачи файла movetoSpace в выбранное пространство с помощью команды s3cmd. Используем s3cmd и переменные, которые мы объявили ранее, для создания команды, которая будет помещать файлы резервных копий в выбранное пространство:

movetoSpace(){
    /bin/s3cmd put $GIVENNAME-$DATETIME.tar.gz s3://$DST
}

Где:

  • /bin/s3cmd вызывает s3cmd — инструмент командной строки, используемый для управления сегментами хранилища объектов;
  • put используется s3cmd для загрузки данных в бакет;
  • $ GIVENNAME- $ DATETIME.tar.gz — это имя резервной копии, которая будет загружена в пространство. Он состоит из четвертой и первой объявленных нами переменных, за которыми следует .tar.gz, и создается функцией tarandzip;
  • s3: // $ DST ; — место, куда мы загружаем файл;
  • s3: // — это схема типа URI, используемая для описания мест хранения объектов в сети, а $DST; — это третья переменная, которую мы объявили ранее.

Добавьте уведомления о том, что процесс переноса файлов начался:

movetoSpace(){
     echo “\n##### MOVING TO SPACE #####\n”
    /bin/s3cmd put $GIVENNAME-$DATETIME.tar.gz s3://$DST
}

Поскольку команда будет либо успешной, либо неудачной (это означает, что она либо загрузит файлы в выбранное пространство, либо нет), можно сообщить пользователям, сработала ли она, повторив одну из двух строк, содержащихся в if/then/else, например:

if /bin/s3cmd put $GIVENNAME-$DATETIME.tar.gz s3://$DST; then
    echo "\n##### Done moving files to s3://"$DST" #####\n"
    return 0
else
    echo "\n##### Failed to move files to the Space #####\n"
    return 1
fi

В целом функция movetoSpace должна выглядеть так:

movetoSpace(){
echo “\n##### MOVING TO SPACE #####\n”

if /bin/s3cmd put $GIVENNAME-$DATETIME.tar.gz s3://$DST; then
    echo "\n##### Done moving files to s3://"$DST" #####\n"
    return 0
else
    echo "\n##### Failed to move files to the Space #####\n"
    return 1
fi

Настроить управление потоком

Предполагая, что скрипт настроен правильно, он при запуске должен прочитать команду ввода, присвоить значения из нее каждой переменной, выполнить функцию tarandzip, а затем выполнить функцию movetoSpace.

Если сценарий завершится неудачно между любой из этих точек, он должен напечатать вывод нашей функции showhelp, чтобы помочь пользователям в устранении неполадок.

Мы можем упорядочить отлов ошибки, добавив в конец файла условную инструкцию if / then / else:

if [ ! -z "$GIVENNAME" ]; then
    if tarandzip; then
        movetoSpace
    else
        showhelp
    fi
else
    showhelp
fi

Первый оператор if в приведенном выше разделе проверяет, что третья переданная переменная не пуста. Это происходит следующим образом:

  • [] — квадратные скобки означают, что то, что находится между ними, является тестом. В этом случае проверка заключается в том, чтобы конкретная переменная не была пустой;
  • ! — в данном случае этот символ означает «нет»;
  • -z — эта опция указывает на пустую строку и в сочетании с ! мы запрашиваем не пустую строку;
  • $ GIVENNAME указывает, что строка, которая не должна быть пустой, является значением, присвоенным переменной $GIVENNAME. Этой переменной присваивается значение, переданное третьим параметром, при вызове скрипта из командной строки. Если мы передадим сценарию менее 3 параметров, в коде не будет третьего параметра для присвоения значения $GIVENNAME, он назначит пустую строку и этот запуск завершится ошибкой.

Пример скрипта

Завершенный скрипт выглядит следующим образом:

#!/bin/bash

DATETIME=`date +%y%m%d-%H_%M_%S`
SRC=$1
DST=$2
GIVENNAME=$3

showhelp(){
        echo "\n This script will backup files/folders into a single compressed file and will store it in the current folder."
     }

tarandzip(){
    echo "\n##### Gathering files #####\n"
    if tar -czvf $GIVENNAME-$DATETIME.tar.gz $SRC; then
        echo "\n##### Done gathering files #####\n"
        return 0
    else
        echo "\n##### Failed to gather files #####\n"
        return 1
    fi
}
movetoSpace(){
    echo "\n##### MOVING TO SPACE #####\n"
    if /bin/s3cmd put $GIVENNAME-$DATETIME.tar.gz s3://$DST; then
        echo "\n##### Done moving files to s3://"$DST" #####\n"
        return 0
    else
        echo "\n##### Failed to move files to the Spac #####\n"
        return 1
    fi
}

if [ ! -z "$GIVENNAME" ]; then
    if tarandzip; then
        movetoSpace
    else
        showhelp
    fi
else
    showhelp
fi

После проверки скрипта закройте файл сочетанием клавиш CTRL+Х и сохраните внесенные изменения клавишей Y+ENTER перед выходом из nano.

Автоматизировать резервное копирование с помощью Crontab

Настройте задание cron, которое будет использовать скрипт для регулярного резервного копирования в выбранное пространство. В рамках этого примера резервное копирование будет выполняться каждую минуту.

Сделайте скрипт исполняемым:

chmod +x bkupscript.sh

Отредактируйте файл crontab, чтобы скрипт запускался каждую минуту:

crontab -e

При первом запуске команды crontab -e будет предложено выбрать редактор из списка:

no crontab for root - using an empty one
Select an editor.  To change later, run 'select-editor'.
  1. /bin/ed
  2. /bin/nano        <---- easiest
  3. /usr/bin/vim.basic
  4. /usr/bin/vim.tiny
Choose 1-4 [2]:

Можно выбрать nano по умолчанию или любой другой текстовый редактор.

Перейдя в crontab, добавьте следующую строку внизу скрипта:

* * * * * ~/bkupscript.sh ~/backupthis nameofyourspace cronupload

Закройте файл сочетанием клавиш CTRL+Х и сохраните внесенные изменения клавишей Y+ENTER.

Если оставить задание cron запущенным без каких-либо изменений, новый файл будет копироваться в выбранное пространство каждую минуту. Убедившись, что cron работает успешно, перенастройте crontab для резервного копирования файлов с нужным интервалом.

Автоматизировать резервное копирование с помощью Cyberduck

На локальной машине имеется директория, содержимое которой нужно периодически копировать в Объектное хранилище. Для этого написан специальный скрипт и добавлено задание Cron, которое отправляет резервную копию в хранилище каждый день в указанное время.

Скрипт:

#!/bin/bash
SELECTEL_ID=<номер учетной записи панели управления Selectel>
USERNAME=<имя пользователя Облачного хранилища>
PASSWORD=<пароль пользователя Облачного хранилища>
BACKUP_PATH=<имя контейнера>/<путь к директории>
LOCAL_PATH=<путь к локальной директории>

duck --upload selectel:/<BACKUP_PATH> <LOCAL_PATH> --existing rename --username <SELECTEL_ID>:<USERNAME> --password <PASSWORD> -q -y

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

Опция rename переименовывает уже имеющуюся резервную копию, добавляя к её имени время и дату.

С помощью cyberduck можно осуществлять и дифференциальное резервное копирование, используя опцию compare:

duck --upload  selectel:/<container_name>/<path_to_remote_folder> <path_to_folder_on_local_machine> --existing compare --username <selectel_id>:<username> --password <password>

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

При использовании опции skip в хранилище будут загружены только новые файлы (те, которые появились в папке на локальной машине после предыдущей загрузки). Уже имеющиеся файлы не будут загружены, даже если на локальной машине они были изменены.

Опция overwrite удаляет из хранилища имеющуюся резервную копию и загружает новую.