---
title: 'Пример настройки резервного копирования по расписанию'
sidebar_label: 'Пример настройки резервного копирования по расписанию'
sidebar_position: 14
description: 'Как автоматизировать резервное копирование данных в S3 при помощи скрипта, Crontab и Cyberduck'
---

import Formbricks from '@theme/MDXComponents/Formbricks'
import Tabs from '@theme/Tabs'
import TabItem from '@theme/TabItem'
import {TabItemLabel} from '@selectel/docux/components'

# Пример настройки резервного копирования по расписанию

## Цель настройки \{#purpose}

Создать скрипт, который будет регулярно запускать консольный клиент, архивировать и переносить важные данные в S3.

## Что нужно для настройки \{#what-is-required}

* консольный клиент (в примере [S3cmd](/s3/tools/s3cmd.mdx) с инструментом для автоматизации crontab);
* облачный или выделенный сервер с установленной Ubuntu версии не ниже 18.04;
* [пользователь с доступом в S3](/s3/manage/manage-access.mdx#access-within-roles).

## Результат настройки \{#result}

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

## Шаги настройки \{#customization-steps}

1. [Создайте скрипт](#create-script).
2. [Перенесите файлы в S3](#transfer-files-to-storage).
3. [Настроить управление потоком](#configure-flow-control).
4. [Проверьте скрипт](#check-script).
5. Опционально: [автоматизируйте резервное копирование через crontab или Cyberduck](#automate-backups).

### 1. Создать скрипт \{#create-script}

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

   ```shell
   cd ~
   ```

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

   ```shell
   nano bkupscript.sh
   ```

3. Начните писать скрипт резервного копирования в текстовом редакторе с шебанга:

   ```shell
   #!/bin/bash
   ```

   Шебанг — это директива интерпретатора, которая позволяет запускать скрипты или файлы данных как команды и выглядит как последовательность из двух символов: `#` и `!`. Благодаря шебангу в начале скрипта оболочка запускает команды файла в bash.

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

   ```shell
   #!/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`.

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

   ```shell
   #!/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."
   }
   ```

6. Соберите нужные файлы и объедините их в единый пакет, который можно будет загрузить:

   ```shell
   #!/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, что указывает на то, что что-то пошло не так.

7. Закончите скрипт `if/then/else` фразой `fi`. Вид завершенной функции `tarandzip`:

   ```bash
   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
   }
   ```

### 2. Перенести файлы в S3 \{#transfer-files-to-storage}

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

   ```bash
   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;` — это третья переменная, которую объявили ранее.

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

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

3. Настройте вывод сообщения о результате выполнении команды:

   ```bash
   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
   ```

### 3. Настроить управление потоком \{#configure-flow-control}

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

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

В конец файла добавьте условную инструкцию `if / then / else`:

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

### 4. Проверить скрипт \{#check-script}

1. Проверьте скрипт:

   ```shell
   #!/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
   ```

2. Перед выходом из nano закройте файл (**Ctrl+Х**) и сохраните внесенные изменения (**Y+Enter**).

### 5. Опционально: автоматизировать резервное копирование \{#automate-backups}

<Tabs queryString="tool">
  <TabItem value="crontab" default>
    <TabItemLabel>
      Crontab
    </TabItemLabel>

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

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

       ```bash
       chmod +x bkupscript.sh
       ```

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

       ```bash
       crontab -e
       ```

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

       ```bash
       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]:
       ```

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

    6. В crontab добавьте строку в конце скрипта:

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

    7. Закройте файл (**Ctrl+Х**) и сохраните внесенные изменения (**Y+Enter**).

    8. Если оставить задание cron запущенным без изменений, новый файл будет копироваться в выбранное пространство каждую минуту. Если cron работает успешно, перенастройте crontab для резервного копирования файлов с нужным интервалом.
  </TabItem>

  <TabItem value="cyberduck">
    <TabItemLabel>
      Cyberduck
    </TabItemLabel>

    На локальной машине есть директория, содержимое которой нужно периодически копировать в S3.
    Это можно делать с помощью скрипта и задания Cron, которое отправляет резервную копию в хранилище каждый день в указанное время.

    Пример задания (дополнительно можно использовать другие [опции Cyberduck](#cyberduck-options)):

    ```shell
    #!/bin/bash
    SELECTEL_ID=<selectel_account>
    USERNAME=<username>
    PASSWORD=<password>
    BACKUP_PATH=<bucket_name>/<prefix>
    LOCAL_PATH=<path>

    duck --upload selectel:/<bucket_name>/<prefix> <path> --existing rename --username <selectel_account>:<username> --password <password> -q -y
    ```

    Укажите:

    * `<selectel_account>` — номер учетной записи панели управления Selectel;
    * `<username>` — имя сервисного пользователя;
    * `<password>` — пароль сервисного пользователя. Если вы забыли пароль, [измените его](/access-control/manage/edit-user-data-or-role.mdx#change-service-user-password);
    * `<bucket_name>` — имя бакета;
    * `<prefix>` — префик объектов;
    * `<path>` — путь к локальной директории.

    Здесь:

    * ключ `--existing` команды `duck` указывает, что делать с уже имеющимися в хранилище файлами;
    * опция `rename` переименовывает уже имеющуюся резервную копию, добавляя к имени время и дату.
  </TabItem>
</Tabs>

#### Опции Cyberduck \{#cyberduck-options}

При [автоматизации резервного копирования через Cyberduck](#automate-backups) вы можете использовать дополнительные опции:

* `compare` — осуществлять дифференциальное резервное копирование:

  ```shell
  duck --upload  selectel:/<bucket_name>/<prefix> <path> --existing compare --username <selectel_account>:<username> --password <password>
  ```

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

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

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

<Formbricks />
