Простое резервное копирование VPS сервера на Linux с помощью bash-скрипта

Бэкап (backup — «резервная копия»), — это создание копии данных, хранящихся на устройстве, с целью возможности их восстановления в случае потери или повреждения оригиналов. Бэкапы делаются для файлов, папок, приложений, систем и других данных. Обычно провайдеры предоставляют возможность снятие полного снапшота (snapshot) VPS сервера. Такой вариант бэкапа хорош, но не позволяет полученные данные загрузить себе локально на ПК или один-в-один перенести на другой сервер. Можно установить специализированное ПО, но оно занимает место на диске и потребляет дополнительный объем памяти. И обычно, хорошие системы резервного копирования стоят немалых денег, а бесплатные, не обладают нужной гибкостью и функциональностью. Поэтому предлагается простой bash-скрипт без overhead, позволяющий создавать резервные копии: файлов, папок, volumes Docker контейнеров, баз данных и т.д.

Bash-скрипт рассчитан на запуск в ОС Ubuntu, позволяет создавать резервные копии следующих типов данных:

  • Файлов;
  • Папок;
  • Отдельных volume (том) Docker контейнеров на горячую (без остановки работы самих контейнеров);
  • Отдельных volume (том) Docker контейнеров с остановкой самих контейнеров (когда может быть нарушена целостность данных, например базы данных);
  • Базы данных MariaDB и PostgreSQL;
  • Список cron-задач;
  • Настройки UFW;
  • Настройки Fail2ban.

Bash-скрипт обладает следующими достоинствами:

  • Не требует установки;
  • Нет overhead, только базовые операции копирования и сжатия данных;
  • Легко модифицируется;
  • Легко добавить как cron-задачу;
  • Не требует обновлений;
  • Работает молча, не просит ни пить, ни кушать.

Все данные упаковываются с помощью утилиты RAR (бесплатная) для максимального сжатия данных. Вначале, данные с сохранение файловой структуры архивируются в формат .tar, затем по возможности, без локального сохранения через pipe механизм, передаются в утилиту  rar  для получения конечного архива. Если pipe механизм не используется, то создается .tar архив на диске, затем он упаковывается в формат .rar. Для минимизации простоя Docker контейнеров, для которых требуется остановка, после остановки формируются только .tar архивы, затем запускаются контейнеры. А после запуска всех контейнеров, выполняется сжатие volumes в формат .rar.

Система резервного копирования состоит из трех файлов:

Скрипт с настройками объектов резервного копирования — b1_backup_server2_vars.sh

Для настройки объектов резервного копирования требуется править только скрипт — b1_backup_server2_vars.sh. Скрипт содержит переменные, декларируемые как массив.

Переменные:

Файлы и папки

  • listfilestobackup — список файлов для архивирования, перечисляются построчно, каждый файл на отдельной строке.
declare listfilestobackup="
/etc/hostname
/etc/hosts
/etc/environment
/etc/docker/daemon.json"

В подобном стиле задаются и другие переменные.

  • listfolderstobackup — список папок для архивирования.

Volumes (тома) Docker контейнеров

Без остановки контейнеров (на горячую).

  • listvolumestobackup — названия Docker volumes (тома, название папок) для архивирования на горячую.

Например, volumes контейнеров хранятся по пути  /var/lib/docker/volumes/ , и располагаются по путям:

  •  /var/lib/docker/volumes/gotify-data 
  •  /var/lib/docker/volumes/pihole-config 
  •  /var/lib/docker/volumes/pihole-dnsmasq-config 

Соответственно, переменная listvolumestobackup должна содержать следующие данные:

declare listvolumestobackup="
gotify-data
pihole-config
pihole-dnsmasq-config"

С остановкой контейнеров.

Некоторые данные, могут быть повреждены, если копирование выполняется на горячую, например, это относится к таким СУБД как MariaDB и PostgreSQL. Вначале необходимо остановить контейнеры, использующие базы данных (например, Matomo), затем останавливаются контейнеры с СУБД (MariaDB и PostgreSQL), выполняется резервное копирование volumes в формат .tar, и в завершение запускаются контейнеры, которые были остановлены. После запуска контейнеров, выполняется сжатие .tar архивов в формат .rar.

  • listdbcontainersforstopping — содержит список контейнеров, которые необходимо остановить до резервного копирования volumes, остановка выполняется в порядке очереди от первого до последнего. Контейнер matomo_local подключается к СУБД MariaDB (контейнер some-mariadb), контейнер wallabag_local подключается к СУБД PostgreSQL (контейнер some-postgres). Выполняется остановка контейнеров в следующем порядке: matomo_local > wallabag_local > some-mariadb > some-postgres.
declare listdbcontainersforstopping="
matomo_local
wallabag_local
some-mariadb
some-postgres"

Соответственно, после резервного копирования контейнеры запускаются в обратном порядке. Переменная listdbcontainersforstart (не требуется изменять) содержит обратный список listdbcontainersforstopping. Запуск контейнеров выполняется в следующем порядке: some-postgres > some-mariadb > wallabag_local > matomo_local.

  • listdbvolumestobackup — названия Docker volumes (тома, название папок), которые архивируются с остановкой Docker контейнеров, указанных в listdbcontainersforstopping. В этом списке нет volumes контейнеров matomo_local и wallabag_local, т.к. они не содержат оперативные данные необходимые для сохранения. Однако, их присутствие в списке остановки контейнеров объясняется зависимостью от работы контейнеров some-mariadb и some-postgres, из-за использования баз данных.
declare listdbvolumestobackup="
some-mariadb-data
some-postgres-data"

Базы данных MariaDB и PostgreSQL в формат SQL

Помимо копирования volumes СУБД, так же доступно создание резервных копии баз данных средствами самих СУБД. Выполняется резервное копирование указанных баз данных с ролями (пользователями) СУБД.

Настройки доступа к СУБД MariaDB:

declare mariadb_host="172.15.1.30"
declare mariadb_user="root"
declare mariadb_password="password"
  • listnamesmariadb — названия баз данных MariaDB для резервного копирования.

Настройки доступа к СУБД PostgreSQL:

declare postgres_host="172.15.1.31"
declare postgres_user="postgres"
declare postgres_password="password"
  • listnamespostgres — названия баз данных PostgreSQL для резервного копирования

Скрипт резервного копирования — b1_backup_server2.sh

Основной скрипт запуска выполнения резервного копирования — b1_backup_server2.sh.

Для работы скрипта требуется установить утилиты  tar ,  rar  и клиентов работы с СУБД MariaDB и PostgreSQL.

Установка необходимых утилит:

sudo apt update && sudo apt install tar rar mariadb-client
# PostgreSQL client 17
sudo apt update && sudo sh -c 'echo "deb http://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list'
curl -fsSL https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo gpg --dearmor -o /etc/apt/trusted.gpg.d/postgresql.gpg
sudo apt update && sudo apt install postgresql-client-17

Запуск скрипта:

chmod +x b1_backup_server2.sh
sudo MIN_FREE_SPACE=1500 ./b1_backup_server2.sh --name srv1-dc-spb1-timeweb_ --vars b1_backup_server2_vars.sh --source_volumes /var/lib/docker/volumes/ --destination /var/backup/

Аргументы:

1) MIN_FREE_SPACE — свободное дисковое пространство в MiB, необходимое для размещения резервной копии. Если меньше, то выполнение скрипта приостанавливается;
2) name — название префикса архива;
3) vars — путь к конфигурационному файлу  b1_backup_server2_vars.sh ;
4) source_volumes — путь к папке с volumes для Docker контейнеров;
5) destination — путь сохранения результирующего архива.

По итогу выполнения скрипта, резервная копия будет расположена в папке с названием, например:

 srv1-dc-spb1-timeweb_24_06_2025_14-53 .

Папка с резервной копией данных, содержит следующую структуру:

anton@srv1-dc-spb1-timeweb:/var/backup$ tree
.
└── srv1-dc-spb1-timeweb_24_06_2025_14-53
    ├── crontab.bak
    ├── databases
    │   ├── mariadb-dump_matomo.sql.rar
    │   ├── mariadb-dump_testdb.sql.rar
    │   ├── mysqldump_grants.sql.rar
    │   ├── pg_dump_testdb.sql.rar
    │   ├── pg_dump_wallabag.sql.rar
    │   └── pg_dumpall_roles-only.sql.rar
    ├── fail2ban.tar.rar
    ├── files.tar.rar
    ├── folders.tar.rar
    ├── ufw.tar.rar
    └── volumes
        ├── gotify-data.tar.rar
        ├── pihole-config.tar.rar
        ├── pihole-dnsmasq-config.tar.rar
        ├── some-mariadb-data.tar.rar
        └── some-postgres-data.tar.rar

4 directories, 16 files

Аргументы утилиты RAR

В отличие от zip, алгоритм rar более требователен к вычислительным ресурсам, степень сжатия регулируется переменной RAR_COMMAND, скрипт  b1_backup_server2.sh . Аргументы для утилиты  rar :

# rar
# rr[N] - Add data recovery record
# m<0..5> Set compression level (0-store...3-default...5-maximal)
# v.. volume size
declare RAR_COMMAND="-rr5 -m3 -v307200k"

Аргументы:

1) rr — добавляет данные для восстановления архива на случай повреждения, задается в процентном выражение от всего размера архива;
2) m — степень сжатия от 0 до 5. В случае наличия производительного vCPU на VPS сервере, выставьте значение от 3 до 5;
3) v — размер архива, если размер файла архива превысит 300 MB, то архив поделится на n-ое количество файлов, и станет многотомным.

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

Скрипт загрузки данных в MEGA.NZ — b2_backup_upload_mega.nz.sh

Используется для загрузки данных в хранилище MEGA.NZ — b2_backup_upload_mega.nz.sh.

Для работы требуется предварительно установить утилиту MEGA CMD. Для установки MEGA CMD выполните следующий скрипт:

sudo apt update && sudo apt install wget
wget https://mega.nz/linux/repo/xUbuntu_24.04/amd64/megacmd-xUbuntu_24.04_amd64.deb
sudo apt install "$PWD/megacmd-xUbuntu_24.04_amd64.deb" && rm "$PWD/megacmd-xUbuntu_24.04_amd64.deb"

Запуск скрипта:

chmod +x b2_backup_upload_mega.nz.sh
./b2_backup_upload_mega.nz.sh --login user@server.com --password PASSWORD --source /var/backup/ --destination /folder_on_mega/

Аргументы:

1) login — логин авторизации.
2) password — пароль учетной записи.
3) source — путь к папке, которую необходимо загрузить в хранилище MEGA.NZ.
4) destination — путь в самом хранилище MEGA.NZ, по которому будет расположен архив.

Так же, вы можете воспользоваться другим инструментами для загрузки архива в другие хранилища.

Структура скрипта — b1_backup_server2.sh

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

Основное тело выполнения скрипта:

echo "================= Start backup ================="
# script execution start time
START_TIME=$(date +%s)
echo "Start is: $(date)"
echo "Folder: ${FULL_PATH_BACKUP_DESTINATION}"
echo "----------------------------------------------"
echo ""

funcBackupFiles

funcBackupFolders

funcBackupVolumes

funcBackupDatabasesMariaDB

funcBackupDatabasesPostgreSQL

funcBackupDatabaseCompression

funcBackupDatabasesWithContainerStop

funcBackupCrontab

funcBackupUfw

funcBackupFail2ban

echo "================= End backup ================="

В фрагменте перечислены названия вызываемых функций. Например, если нет необходимости выполнять резервное копирования баз данных MariaDB, то достаточно удалить строку с вызываемой функцией funcBackupDatabasesMariaDB.

Если у вас несколько экземпляров СУБД MariaDB, то вам следует создать отдельные файлы  b1_backup_server2_vars.sh , в которые необходимо прописать разные реквизиты доступа к экземплярам СУБД MariaDB.

Создания сron задачи для регулярного выполнения скрипта резервного копирования

Создадим cron задачу для ежедневного создания резервной копии данных, во время наименьшей нагрузки на VPS сервер, в 02:05. Разместим bash-скрипты в каталоге  /var/scripts/ . Допустим, в системе создана учетная запись с именем user_backup, от имени которой, необходимо выполнить скрипт резервного копирования.

Выставим необходимые права:

sudo chown -R user_backup:user_backup /var/scripts/{b1_backup_server2.sh,b1_backup_server2_vars.sh,b2_backup_upload_mega.nz.sh}
sudo find /var/scripts/ -type f -exec sudo chmod 644 {} +
sudo chmod 755 /var/scripts/*.sh /var/scripts/*.csx

Откроем список cron задач:

sudo crontab -e

Если cron не установлен в системе, то необходимо выполнить команду для установки:

sudo apt update && sudo apt install cron && sudo systemctl enable cron && sudo systemctl status cron

Добавим строку в самый конец:

# At 02:05
5 02 * * * sudo -u user_backup MIN_FREE_SPACE=1500 /var/scripts/b1_backup_server2.sh --name srv1-dc-spb1-timeweb_ --vars /var/scripts/b1_backup_server2_vars.sh --source_volumes /var/lib/docker/volumes/ --destination /var/backup/ && sleep 10 && /var/scripts/b2_backup_upload_mega.nz.sh --login user@server.com --password PASSWORD --source /var/backup/ --destination /folder_on_mega/

Для выставления другого расписания выполнения задачи, воспользуйтесь сайтом Crontab.guru — The cron schedule expression generator.

Сохраним изменения и перезапустим службу:

sudo systemctl restart cron
sudo systemctl status cron

Если необходимо сохранить вывод исполнения скрипта очистки, то необходимо указать следующий формат исполнения cron задачи:

# At 02:05
5 02 * * * sudo ... >> /var/log/backup.log 2>&1

Где  >> /var/log/backup.log  — вывод будет записан в лог-файл доступный для просмотра.

Для просмотра журнала исполнения скрипта выполнить команду:

cat /var/log/backup.log

Ресурсы

Скрипты резервного копирования — GitHub devdotnetorg/Linux.

 

* — титульная иллюстрация к посту сгенерирована системой ChatGPT.

Вам также может понравиться

About the Author: Anton

Programistik