Various improvements

This commit is contained in:
ge 2022-10-08 19:37:22 +03:00
parent 67c8d4715a
commit 9276d0f738
10 changed files with 855 additions and 634 deletions

4
.gitignore vendored
View File

@ -1,6 +1,6 @@
*.txt
build/
dist/
tests/helpers/*
src/backups/
src/clean
plan.sh
NOTE.todo

8
CHANGELOG Normal file
View File

@ -0,0 +1,8 @@
CHANGELOG
All notable changes to this project will be documented in this file.
Version numbering uses Semantic Versioning 2.0.0 <https://semver.org/>
0.1.0
Initial release.

View File

@ -1,9 +0,0 @@
# Changelog
All notable changes to this project will be documented in this file.
Version numbering uses [Semantic Versioning 2.0.0](https://semver.org/).
# 0.1.0
Initial release.

View File

@ -1,24 +1,28 @@
SRC_DIR := ./src
DOCS_DIR := ./docs
TESTS_DIR := ./tests
BUILD_DIR := ./build
DOCS_BUILD_DIR := ./build/docs
BUILD_DIR := ./dist
.PHONY: help tests docs man install uninstall
.PHONY: help tests manpages install uninstall fixpath
all: man
all: manpages
help:
@echo Usage: make TARGET
@echo 'Usage: make TARGET'
@echo ' make prefix=/path install'
@echo ' make prefix=/path uninstall'
@echo
@echo Available targets:
@echo
@echo ' help print this help message'
@echo ' tests run tests from $(TESTS_DIR)'
@echo ' lint run shellcheck'
@echo 'man build manual pages from $(DOCS_DIR)'
@echo ' manpages build manual pages from $(DOCS_DIR)'
@echo ' install install boring-backup with prefix'
@echo ' uninstall uninstall boring-backup with prefix'
@echo
@echo See README.md for more info.
@echo 'prefix examples: $$HOME/.local, /usr/local, /usr/bin'
@echo See README for more info.
tests:
# See bats(1), https://bats-core.readthedocs.io/en/latest/index.html
@ -32,24 +36,63 @@ lint:
shellcheck $(SRC_DIR)/lib/handlers/sources/*.sh
shellcheck $(SRC_DIR)/lib/handlers/targets/*.sh
man: build_dir
# See rst2man(1), rst2html(1),
manpages:
mkdir -pv $(BUILD_DIR)/share/man/ru/man1
# See rst2man(1)
# https://docutils.sourceforge.io/docs/index.html
rst2man $(DOCS_DIR)/boring-backup.ru.1.rst \
> $(DOCS_BUILD_DIR)/boring-backup.ru.1
rst2man -v $(DOCS_DIR)/manpages/boring-backup.ru.1.rst \
> $(BUILD_DIR)/share/man/ru/man1/boring-backup.1
sed -e 's/.SH NAME/.SH ИМЯ/' \
-e 's/.SH AUTHOR/.SH АВТОРЫ/' \
-e 's/.SH COPYRIGHT/.SH АВТОРСКИЕ ПРАВА/' \
-i $(DOCS_BUILD_DIR)/boring-backup.ru.1
gzip -9 $(DOCS_BUILD_DIR)/boring-backup.ru.1
-i $(BUILD_DIR)/share/man/ru/man1/boring-backup.1
gzip -vf9 $(BUILD_DIR)/share/man/ru/man1/boring-backup.1
build_dir:
mkdir -p $(BUILD_DIR)
mkdir -p $(DOCS_BUILD_DIR)
html: manpages
mkdir -p $(BUILD_DIR)/share/doc/boring-backup
zcat $(BUILD_DIR)/share/man/ru/man1/boring-backup.1.gz | \
groff -man -Kutf8 -Thtml \
> $(BUILD_DIR)/share/doc/boring-backup/boring-backup.1.html 2>/dev/null
rm -v grohtml-*.png
install:
# install
install: manpages
@echo prefix: $$prefix
install -Dm755 $(SRC_DIR)/boring-backup $$prefix/bin/boring-backup
install -Dm644 $(SRC_DIR)/lib/lib.sh $$prefix/share/boring-backup/lib.sh
install -Dm644 $(SRC_DIR)/lib/backup.sh $$prefix/share/boring-backup/backup.sh
install -Dm644 $(SRC_DIR)/lib/common.sh $$prefix/share/boring-backup/common.sh
install -Dm644 $(SRC_DIR)/lib/source.sh $$prefix/share/boring-backup/source.sh
install -Dm644 $(SRC_DIR)/lib/uri.sh $$prefix/share/boring-backup/uri.sh
install -Dm644 $(SRC_DIR)/lib/handlers/sources/tar.sh $$prefix/share/boring-backup/handlers/sources/tar.sh
install -Dm644 $(SRC_DIR)/lib/handlers/sources/mysqldump.sh $$prefix/share/boring-backup/handlers/sources/mysqldump.sh
install -Dm644 $(SRC_DIR)/lib/handlers/sources/pg_dump.sh $$prefix/share/boring-backup/handlers/sources/pg_dump.sh
install -Dm644 $(SRC_DIR)/lib/handlers/targets/cp.sh $$prefix/share/boring-backup/handlers/targets/cp.sh
install -Dm644 $(SRC_DIR)/lib/handlers/targets/s3cmd.sh $$prefix/share/boring-backup/handlers/targets/s3cmd.sh
sed -e "s%LIBRARY=\"\$${LIBRARY:-.\/lib}\"%LIBRARY=\"\$${LIBRARY:-$$prefix\/share\/boring-backup}\"%" \
-i $$prefix/share/boring-backup/lib.sh \
-i $$prefix/bin/boring-backup
install -Dm664 $(BUILD_DIR)/share/man/ru/man1/boring-backup.1.gz $$prefix/share/man/ru/man1/boring-backup.1.gz
uninstall:
# uninstall
@echo prefix: $$prefix
rm $$prefix/bin/boring-backup
rm $$prefix/share/boring-backup/lib.sh
rm $$prefix/share/boring-backup/backup.sh
rm $$prefix/share/boring-backup/common.sh
rm $$prefix/share/boring-backup/source.sh
rm $$prefix/share/boring-backup/uri.sh
rm $$prefix/share/boring-backup/handlers/sources/tar.sh
rm $$prefix/share/boring-backup/handlers/sources/mysqldump.sh
rm $$prefix/share/boring-backup/handlers/sources/pg_dump.sh
rm $$prefix/share/boring-backup/handlers/targets/cp.sh
rm $$prefix/share/boring-backup/handlers/targets/s3cmd.sh
rm -rv $$prefix/share/boring-backup
rm $$prefix/share/man/ru/man1/boring-backup.1.gz
fixpath:
# Set boring-backup library path
@echo prefix: $$prefix
@echo path: $$path
sed -e "s%LIBRARY=\"\$${LIBRARY:-.\/lib}\"%LIBRARY=\"\$${LIBRARY:-$$path}\"%" \
-i $$prefix/share/boring-backup/lib.sh \
-i $$prefix/bin/boring-backup

28
README Normal file
View File

@ -0,0 +1,28 @@
BORING BACKUP
Bash powered backuping tool.
INSTALLATION
Install for user locally:
make prefix=$HOME/.local install
Uninstall:
make prefix=$HOME/.local uninstall
DEVELOPMENT
TESTING
BB uses amazing test suite: https://bats-core.readthedocs.io/
Install Bats:
git clone https://github.com/bats-core/bats-core.git
bash bats-core/install.sh ~/.local
Add some Bats extensions:
git clone https://github.com/bats-core/bats-assert.git tests/helpers/bats-assert
git clone https://github.com/bats-core/bats-support.git tests/helpers/bats-support
Run tests:
make test

View File

@ -1,33 +0,0 @@
# Boring Backup
Bash powered backup tool.
# Testing
BB uses amazing test suite: https://bats-core.readthedocs.io/
Install Bats:
git clone https://github.com/bats-core/bats-core.git
bash bats-core/install.sh ~/.local
Add some Bats extensions:
git clone https://github.com/bats-core/bats-assert.git tests/helpers/bats-assert
git clone https://github.com/bats-core/bats-support.git tests/helpers/bats-support
Run tests:
make test
# Linting
Run shellcheck:
make lint
# Building
Build manpages:
make man

View File

@ -1,509 +0,0 @@
:Title: boring-backup
:Title upper: BORING-BACKUP
:Subtitle: backup files and databases
:Author: ge
:Copyright: \(C) 2022, ge <https://nixhacks.net/>, GPLv3+
:Date: 2022 May 15
:Manual section: 1
:Version: boring-backup 0.1.0
Синопсис
--------
``boring-backup`` [-cvlphV] FILES..
Описание
--------
boring-backup - это расширяемая утилита для резервного копирования на основе
сценариев Bash.
Опции
-----
-c, --config config file.
-v, --verbose verbose output.
-l, --log-file log file.
-p, --pid-file PID file.
-h, --help print this help messagea and exit.
-V, --version print version and exit.
Быстрый старт
-------------
boring-backup можно рассматривать как фреймворк или библиотеку для создания
сценариев резервного копирования. Сценарии должны содержать валидный код на
Bash. Сценарий импортируется в основной скрипт с помощью команды ``source``
(см. ``bash``\(1) п. SHELL BUILTIN COMMANDS).
Простейший сценарий резервного копирования выглядит следующим образом::
sources=(file:/home/user)
targets=(file:/var/backup)
Здесь массивы `sources` и `targets` определяют точки, они же поинты (`points`)
резервного копирования: источники (`sources`) и назначения (`targets`). Это
основные сущности, с которыми работает boring-backup. Вот некоторые особенности
поинтов:
- Все поинты указываются в формате URI.
- Поинты могут указывать как на локальные (размещённые на текущей машине), так
и на удалённые (размещённые на удалённой машине) ресурсы.
- Можно указать как несколько источников, так и несколько назначений.
Для выполнения бэкапа директорий или отдельных файлов применяется схема URI
`file`. В схеме `file` нельзя указать директорию, размещённую на удалённом
хранилище (за исключением случая, когда удалённое хранилище примонтировано как
файловая система), для этого используйте другие схемы. В примере выше будет
выполнена резервная копия локальной директории /home/user в другую локальную
директорию /var/backup. Поскольку в сценарии из примера нет ничего, кроме
указания точек `sources` и `targets`, бэкап будет выполнен с параметрами по
умолчанию: директория /home/user будет заархивирована с помощью утилиты
``tar``\(1) и помещён в директорию /var/backup. Имя архива будет сложено по
шаблону::
${name_prefix}${name}${name_date_fmt}${name_suffix}${name_ext}
Описание переменных см. в разделе ПЕРЕМЕННЫЕ. Пример имени файла::
example.sh_example_2022.05.15-0953.tar
Обзор URI
---------
Источники (`sources`) и назначения (`targets`) должны быть указаны в виде
URI. Это позовляет наглядно в одной сроке видеть весь набор данных. Парсер
реализует поддержку следующего синтаксиса URI::
scheme:[//[username[:password]@]hostname[:port]]/[path]?[query]#[fragment]
Парсер URI соответствует RFC 3986 не полностью - разбиение на составные части
URI происходит верно, но интерпретация в отдельных ситуациях может отличаться.
См. примеры URI и реузультаты их интерпретации парсером в файле
`tests/parse_uri.bats`. На практике рекомендую придерживаться примеров, которые
приведены ниже и в файле `tests/parse_uri.bats`. В случае, если изменение
логики парсера необходимо, вы можете прислать правки в pull-реквесте или
завести feature-реквест в репозитории проекта. На текущий момент компоненты
`query` и `fragment` не используются.
Примеры URI для массива `sources`::
mysql://wordpress:1jobrRRjtLYs@localhost/wordpress
postgres://django:9%3F2%3D%40gHW@localhost:5432:/django
sqlite:///var/www/app/data/database.db
file:///var/www/html/
Примеры URI для `targets`::
file:/var/backup
ftp://jhon:%24t%D0%AFo%7C%5C%7C6@[fe80::5054:ff:fe24:382]:2021/backups/
rsync://backup_user@192.168.3.12:2022/backups
s3://my_bucket
Пароли содержащие специальные символы недопустимые в URI (включая пробелы)
необходимо закодировать в percent code. См. примеры кодирования строки на
разных языках программирования ниже.
Python 2::
python2 -c "import urllib, sys; \
print urllib.quote(sys.argv[1], safe='')" 'p@$$w0rd'
Python 3::
python3 -c "import urllib.parse, sys; \
print(urllib.parse.quote(sys.argv[1], safe=''))" 'p@$$w0rd'
Perl 5::
echo 'p@$$w0rd' | perl -MURI::Escape -wlne 'print uri_escape $_'
Поддерживаемые протоколы и схемы URI
------------------------------------
Схемы, которые могут быть использованы как sources
``````````````````````````````````````````````````
file
Может содержать путь к локальному файлу или директории. Файлы
архивируются при помощи ``tar`` и по умолчанию не сжимаются. Cжатие
архива может быть включено через переменную `compression`. Примеры::
/var/www/www-root/data
file:/var/www/html
file:///home/jhon/cool_stuff.txt
Не используйте двойной слэш для этой схемы, используйте один или три
слэша. Двойной слэш означает наличие компонента Authority, это приводит
к неверной интерпретации адреса.
См. также ``handler::tar``
mysql
URI содержит реквизиты для подключения к БД MySQL/MariaDB. Формат::
mysql://[username[:password]@]hostname[:port]/database
С помощью утилиты ``mysqldump``\(1) формируется дамп в формате SQL. Файл
по умолчанию не сжимается, но сжатие может быть включено через переменную
`compression`.
См. также ``handler::mysqldump``
postgres
Аналогично `mysql`, но для PostgreSQL. Для создания дампа используется
``pg_dump``\(1) с расширением .psql. Файл по умолчанию не сжимается, но
сжатие может быть включено через переменную `compression`.
См. также ``handler::pg_dump``
sqlite
Схема для баз данных SQLite. Мало отличается от `file`, добавлена для
наглядного обозначения, что источником является БД SQLite, а не иной файл.
См. также ``handler::sqlite``
Схемы, которые могут быть использованы как targets
``````````````````````````````````````````````````
file
В контексте `targets` указывает директорию для сохранения бэкапов. В
массиве `targets` обязательно должен быть хотя бы один поинт со схемой
`file`. Этот поинт будет использован как основной и сохранён в переменные
``__main_target`` (содержит URI) и ``__main_target_path`` (содержит
компонент URI path). Если в массиве присутствует несколько поинтов со
схемой `file`, то в качестве основного будет выбран первый по порядку
поинт. Все бэкапы первоначально будут сохраняться в директорию
``__main_target_path`` и затем копироваться в другой таргет с помощью
соответствующего обработчика. В случае копировани из одной директории в
другую используется утилита ``cp``\(1).
Избегайте указания в одном сценарии таргетов, которые ведут одновременно на
примонтированный к локальной машине сетевой диск и другое удалённое
хранилище. В таком случае архивы будут создаваться на сетевом диске и далее
снова копироваться по сети, что будет очень медленно.
См. также ``handler::cp``
ftp
Не реализовано.
sftp
Не реализовано.
rsync
Не реализовано.
s3
Не реализовано.
swift
Не реализовано.
sj
Не реализовано.
dav, davs
Не реализовано.
Создание резервных копий
------------------------
boring-backup предполагает, что для всех резервных копий необходимо создавать
архивы. Поэтому вам нужно следить за тем, чтобы в локальном хранилище всегда
хватало дискового пространства для создания новых архивов. boring-backup также
не удаляет старые архивы и вам также надо позаботиться об удалении устаревших
резервных копий. Изменить это поведение можно с помощью пользовательских
функций в сценариях. В этом разделе речь пойдёт о поведении, которое
установлено по умолчанию. См. функции ``builtin_backup``, ``process_sources``,
``process_targets``.
Базовая концепция строится на том, что существует несколько источников и
несколько точек назначения. Создаётся резервная копия источника и копируется в
точку назначения.
Для всех источников в сценарии выполняется локальная резервная копия. После
этого локальная копия переносится в удалённые точки назначения, если они
заданы. Копирование локального бэкапа будет осуществлёно столько раз, сколько
точек назначения задано. В каждом сценарии обязательно должен быть задан хотя
бы один источник и одна точка назначения. При этом в списке точек назначения
обязательно должна присутствовать точка со схемой `file`. Именно в неё будут
сохранены архивы.
Например, имеется следующий сценарий::
sources=(
mysql://wordpress:1jobrRRjtLYs@localhost/wordpress
file:///var/www/wordpress
)
targets=(
file:///var/backup
ftp://jhon:%24t%D0%AFo%7C%5C%7C6@[fe80::5054:ff:fe24:382]:2021/backups/
)
Здесь будут созданы архивы файлов и базы данных и сохранены в локальную
директорию /var/backup. Затем эти файлы будут переданы по протоколу FTP на
сервер fe80::5054:ff:fe24:382 в директорию /backups. Файлы из директории
/var/backup не будут удалены или перемещены. Если добавить дополнительную точку
назначения, то файлы из /var/backup будут скопированы и туда. Обратите
внимание, что boring-backup не выполняет повторного создания архивов для каждой
точки назначения — архивы создаются один раз и далее распространяются по всем
указанным назначениям. Если в массиве `targets` имеется несколько точек
назначения со схемой `file`, то архивы будут сохранены в первую по порядку
точку, а затем скопированы оттуда в остальные.
Резервное копирование на удалённое хранилище
--------------------------------------------
FTP
```
SFTP
````
Rsync over SSH
``````````````
Rsync with rsyncd
`````````````````
Amazon S3
`````````
S3 compatible storage
`````````````````````
OpenStack Swift
```````````````
Storj DCS
`````````
WebDAV
``````
Переменные
----------
``boring-backup`` условно разделяет переменные на "внутренние" ("защищённые") и
"обычные". К "защищённым" переменным относятся все перемеменные, имена которых
начинаются с двух знаков подчёркивания, например: ``__main_target``. Все
остальные переменные считаются "обычными".
Обычные переменные могут быть перезаписаны в пользовательском скрипте.
Защищённые переменные технически ничем от них не отличаются, однако не нужно
переопределять такие переменные в пользовательском скрипте, так как это может
привести к неожиданным ошибкам во время выполнения скрипта. Точно также очень
внимательно нужно относится к перезаписи обычных переменных — в обоих случаях
есть риск что-то поломать.
``backups``
Массив со списком созданных бэкапов. Содержит абсолютные пути к файлам.
Заполняется функциями-обработчиками `sources`.
| Тип: массив
| Умолчание: ()
``errors``
Массив с текстами ошибок. Заполняется функцией ``err`` с опцией ``-a``.
| Тип: массив
| Умолчание: ()
``log_date_fmt``
Формат даты в логе. См. ``date``\(1).
| Тип: строка
| Умолчание: %d/%b/%Y:%H:%M:%S %z
``name_prefix``
Префикс имени файла. Может быть задан в скрипте.
| Тип: строка
| Умолчание: имя_скрипта\_
``name``
Соответствует имени архивируемой директории/файла полученного из `path` с
помощью утилиты ``basename``\(1).
| Тип: строка
| Умолчание: нет
``name_date_fmt``
Дата, интерпретируемая утилитой ``date``\(1).
| Тип: строка
| Умолчание: _%Y%m%d
``name_suffix``
Суффикс, добавляемый к имени файла перед расширением. Строка
интерпретируется утилитой ``date``.
| Тип: строка
| Умолчание: -%H%M
``name_ext``
Расширение имени файла, соответствующее формату архива.
| Тип: строка
| Умолчание: .tar.gz
``tar_options``
Опции ``tar``. См. ``tar``\(1).
| Тип: строка
| Умолчание: -acf
``tar_exclude``
Список имён для опции ``tar`` ``--exclude``.
| Тип: массив
| Умолчание: нет
``compression``
В контексте ``tar`` работа этой фичи базируется на опции ``tar``
``--auto-compress``. Переменная может принимать значения, в соответствии с
табилцей ниже. Если переменная имеет значение, отличное от перечисленныых,
то будет использован ``gzip``. Если переменная пуста или не задана, то
сжатие будет отключено.
| Тип: строка
| Умолчание: нет
==================== ================ ========
Значение compression Расширение файла Утилита
==================== ================ ========
gzip, gz .tar.gz gzip
tgz .tgz gzip
taz .taz gzip
compress, Z .tar.Z compress
taZ .taZ compress
bzip2, bz2 .tar.bz2 bzip2
tz2 .tz2 bzip2
tbz2 .tbz2 bzip2
tbz .tbz bzip2
lzip, lz .tar.lz lzip
lzma .tar.lzma lzma
tlz .tlz lzma
lzop, lzo .tar.lzo lzop
xz .tar.xz xz
zstd, zst .tar.zst zstd
tzst .tzst zstd
==================== ================ ========
Функции
-------
``backup``
Пользовательская функция резервного копирования. Если она задана в скрипте,
то вызывается вместо ``builtin_backup``.
``builtin_backup``
Встроенная функция, запускает резервное копирвоание. Вызывает функции
``process_source`` и ``process_target``.
``err [-eao] MESSAGE``
Печатает сообщение об ошибке MESSAGE на экран и в лог и выполняет обработку
ошибок.
-e Выйти из скрипта с кодом выхода 1.
-a Добавить сообщение MESSAGE в массив ``errors``.
-o Вызвать функцию ``on_error``.
``finalise``
Пользовательская функция. Если задана, то запускается после функции
``backup`` или ``builtin_backup()``.
``gen_backup_name FILE_EXT``
Печатает полученное имя файла в STDOUT. Имя является выводом команды
``date`` и строки ``${prefix}${name}${date_fmt}${name_ext}``.
См. переменные ``name_prefix``, ``name``, ``name_date_fmt``, ``name_ext``.
``try COMMAND``
Функция выполняет команду COMMAND и в случае ненулевого кода выхода
вызывает ``err()`` с ключами ``-eao``. Ошибка при выполнении COMMAND
приведёт к вызову функции ``on_error``. Рекомендуется для использования в
качестве обёртки для команд правильное выполнение которых критично.
``handler::tar URI``
Архивация файлов с помощью ``tar``.
``handler::mysqldump URI``
Не реализовано.
``handler::pg_dump URI``
Не реализовано.
``handler::sqlite URI``
Не реализовано.
``handler::cp URI``
Копирует файлы в новое назначение с помощью ``cp``.
``handler::ftp URI``
Не реализовано.
``handler::sftp URI``
Не реализовано.
``handler::rsync URI``
Не реализовано.
``handler::s3 URI``
Не реализовано.
``handler::sj URI``
Не реализовано.
``handler::swift URI``
Не реализовано.
``handler::dav URI``
Не реализовано.
``handler::davs URI``
Не реализовано.
``is_installed COMMAND``
Проверяет установлена ли программа COMMAND.
``is_function_set FUNCTION``
Проверяет задана ли функция FUNCTION.
``log [-p] MESSAGE``
Печатает лог в файл ``__log_file`` (лог задаётся опцией --log-file) и на
экран, если указана опция ``-p``. Формат даты в логе можно изменить с
помощью переменной ``log_date_fmt``.
``on_error``
Пользовательская функция для обработки ошибок. Если задана, то запускается
при обработке ошибки в функции ``err`` с опцией ``-o``.
``parse_uri URI``
Парсер URI. Задаёт переменные ``scheme``, ``username``, ``password``,
``hostname``, ``port``, ``path``, ``query``, ``fragment`` и выполняет
декодинг пароля, если он закодирован в percent code.
``prepare``
Пользовательская функция. Если задана, то запускается до функции ``backup``
или ``builtin_backup``.
``process_source URI``
На основе схемы запускает соответсвующую функцию-обработчик.
``process_target URI``
На основе схемы запускает соответсвующую функцию-обработчик.
``source_script FILE``
Выполняет ``source`` пользовательского скрипта и проверяет его
корректность. Проверяется синтаксис Bash, наличие непустых массивов
`sources` и `targets`, наличие поинта `file` в `targets`. Во
вспомогательной функции ``validate_targets`` задаются значения переменных
``__main_target`` и ``__main_target_path``.
Использование функций в сценариях
---------------------------------
Переменные окружения
--------------------
``LIBRARY``
Путь до библиотеки функций boring-backup.
Примеры
-------
См. также
---------
``bash``\(1), ``tar``\(1), ``cp``\(1), ``date``\(1), ``mysqldump``\(1),
``pg_dump``\(1)
RFC 3986 https://datatracker.ietf.org/doc/html/rfc3986

View File

@ -0,0 +1,640 @@
:Title: boring_backup
:Title upper: BORING_BACKUP
:Subtitle: бэкап файлов и баз данных
:Author: ge
:Copyright: \(C) 2022, ge <https://nixhacks.net/>, GPLv3+
:Date: 2022 May 15
:Manual section: 1
:Version: boring_backup 0.1.0
СИНТАКСИС
---------
**boring_backup** [-hVvs] [-c `файл`] [-l `файл`] [-p `файл`] файл ...
ОПИСАНИЕ
--------
boring_backup - это расширяемая утилита для резервного копирования на основе
сценариев Bash.
ОПЦИИ
-----
-h, --help
Показать справку и выйти.
-V, --version
Показать информацию о версии и выйти.
-v, --verbose
Печатать подробный вывод.
-c, --config=\ `файл`
Путь до файла конфигурации. См. **КОНФИГУРИРОВАНИЕ**.
-l, --log-file=\ `файл`
Путь до файла лога.
-s, --use-syslog
Записывать лог в syslog вместо файла. Эта опция несовместима с опцией
--log-file и переменной log_date_format.
-p, --pid-file=\ `файл`
Путь до PID-файла.
ОБЗОР
-----
**boring_backup** можно рассматривать как фреймворк или библиотеку для создания
сценариев резервного копирования. Сценарии (скрипты) должны содержать валидный
код на Bash.
Скрипты передаются в качестве аргументов **boring_backup** и исполняются в
цикле. Скрипты загружается с помощью команды ``source`` (см. ``bash``\(1)
п. SHELL BUILTIN COMMANDS).
Простейший сценарий резервного копирования выглядит следующим образом::
sources=(file:/home/john)
targets=(file:/var/backups)
Массивы `sources` и `targets` определяют источники и назначения соответственно.
Ресурсы из `sources` нужно сохранить в точку(и) назначения — `targets`. См.
больше примеров в разделе **ПРИМЕРЫ**.
Все ресурсы записываются в формате URI. См. подробности в разделе
**СХЕМЫ URI** и в описании функции ``parse_uri`` ниже.
Каждой схеме URI соответствует функция-обработчик, которая выполняет действие
с ресурсом. Например, URI со схемой `mysql` будет обработан функцией
``src_mysqldump``.
Обработчики ресурсов для массива `sources` имеют в имени префикс ``src_``, а
обработчики для массива `targets` префикс ``tgt_``. См. описания обработчиков в
разделе **ВСТРОЕННЫЕ ФУНКЦИИ**.
Поскольку скрипты резервного копирования это обычные скрипты Bash, то здесь
применимы все те же приёмы. В **boring_backup** предусмотрено несколько
специальных пользовательских функций и ряд специальных переменных. См. разделы
**ПЕРЕМЕННЫЕ** и **ПОЛЬЗОВАТЕЛЬСКИЕ ФУНКЦИИ**.
СХЕМЫ URI
---------
file
Схема для указания ресурсов в файловой системе. Примеры записи::
/var/www/www-root/data
file:/var/www/html
file:///home/jhon/cool_stuff.txt
Не используйте двойной слэш для этой схемы, используйте один или три
слэша. Двойной слэш означает наличие компонента Authority, который здесь
не обрабатывается, что приводит к неверной интерпретации адреса.
Схема `file` может быть указана как в массиве `sources`, так и `targets`.
В массиве `sources` схема обрабатывается функцией ``src_tar``. Файлы
архивируются и сжимаются согласно значению переменной $compression.
В контексте `targets` `file` указывает директорию для сохранения бэкапов.
В `targets` обязательно должен быть хотя бы один URI со схемой `file`.
Этот URI будет использован как основной и сохранён в переменные
$__main_target (содержит URI целиком) и $__main_target_path (содержит
компонент URI path).
Если в массиве `targets` присутствует несколько URI со схемой `file`, то в
качестве основного будет выбран первый по порядку URI. Все бэкапы
первоначально будут сохраняться туда и затем копироваться в другой таргет с
помощью соответствующего обработчика. В случае копирования бэкапов между
директориями будет использован обработчик ``tgt_cp``.
Избегайте указания в одном сценарии таргетов, которые ведут одновременно на
примонтированный к локальной машине сетевой диск и на другое удалённое
хранилище. В таком случае архивы будут создаваться на сетевом диске и далее
снова копироваться по сети. Это может быть очень медленно.
См. также ``src_tar``, ``tgt_cp``.
mysql, mariadb
URI содержит реквизиты для подключения к БД MySQL/MariaDB. Иногда такой
формат ещё называют DSN (data source name)::
mysql://[username[:password]@]hostname[:port]/database
См. также ``src_mysqldump``.
postgres
Аналогично `mysql`, но для PostgreSQL. Для создания дампа используется
``pg_dump``. Расширение несжатых файлов — .psql.
См. также ``src_pg_dump``
sqlite [НЕ РЕАЛИЗОВАН]
Схема для баз данных SQLite. Мало отличается от `file`, добавлена для
наглядного обозначения, что ресурсом является БД SQLite, а не иной файл.
См. также ``src_sqlite``
s3
Схема Simple Storage Service (S3). Пример использования::
s3://bucket
URI содержит только схему и путь. Все остальные реквизиты для подключения к
хранилищу задаются через конфигурационный файл или отдельные переменные.
См. ``tgt_s3cmd`` ниже.
В S3 важно наличие слэшей в конце URI. Пример::
s3://bucket/backups (1)
s3://bucket/backups/ (2)
В случае (1) при загрузке файла с именем dump.sql.gz файл будет сохранён
как, s3://bucket/backups, а не s3://bucket/backups/dump.sql.gz. Чтобы
такого не происходило следует добавлять слэш в конце (2), чтобы обозначить,
что backups в данном случае является директорией. Обработчик ``tgt_s3cmd``
сам добавляет слэш в конец URI, если его нет.
Ещё одной особенностью является то, что в URI можно записывать
несуществующие в хранилище директории. Они будут созданы при загрузке
файла. Таким образом можно делать следующее::
today="$(date +%d_%b_%Y)"
targets=(
file:///var/backups
s3://bucket/backups/$today
)
Бэкап будет сохранён как::
s3://bucket/backups/22_Aug_2022/dump.sql.gz
ПЕРЕМЕННЫЕ
----------
``sources``
| Тип: массив
| Умолчание: нет
Массив из строк с URI ресурсов, резервную копию которых нужно выполнить.
Массив обязатально должен быть непустой. Пример::
sources=(
file:///home/john
mysql://user:password@localhost:3306/database
)
См. **СХЕМЫ URI**.
``targets``
| Тип: массив
| Умолчание: нет
Массив из строк URI хранилищ, куда необходимо доставить резервные копии.
Обязательно должен содержать хотя бы один URI со схемой `file`. Пример::
targets=(
file:///var/backups
s3://bucket/backups/$today
)
См. **СХЕМЫ URI**.
``backups``
| Тип: массив
| Умолчание: нет
Массив со списком созданных бэкапов. Содержит абсолютные пути к файлам.
Заполняется функциями-обработчиками `sources` при успешном создании бэкапа.
При использовании пользовательской функции ``backup`` массив следует
заполнять вручную для корректного вызова функций-обработчиков для
`targets`. См. пример в разделе **ПРИМЕРЫ**.
``compression``
| Тип: строка
| Умолчание: нет
Тип компрессии для сжатия файлов.
В контексте ``tar`` работа этой фичи базируется на опции ``tar``
``--auto-compress``. Переменная может принимать значения, в соответствии с
табилцей ниже. Если переменная не задана, имеет пустое или отличное от
перечисленныых в таблице значение, то сжатие будет отключено.
Для файлов, которые не являются архивами tar (не созданы функцией
``src_tar``) расширение из таблицы будет добавлено к оригинальному
рассширению файла.
==================== ========== =================== =====================
Значение compression Утилита Расширение файла Расширение архива tar
==================== ========== =================== =====================
gzip, gz gzip .gz .tar.gz
tgz gzip .gz .tgz
taz gzip .gz .taz
bzip2, bz2 bzip2 .bz2 .tar.bz2
tz2 bzip2 .bz2 .tz2
tbz2 bzip2 .bz2 .tbz2
tbz bzip2 .bz2 .tbz
lzip, lz lzip .lz .tar.lz
lzma lzma .lzma .tar.lzma
tlz lzma .lzma .tlz
lzop, lzo lzop .lzo .tar.lzo
xz xz .xz .tar.xz
zstd, zst zstd .zst .tar.zst
tzst zstd .zst .tzst
==================== ========== =================== =====================
``log_date_format``
| Тип: строка
| Умолчание: %d/%b/%Y:%H:%M:%S %z
Формат даты в логе. См. ``date``. См. **КОНФИГУРИРОВАНИЕ**.
``name``
| Тип: строка
| Умолчание: нет
Соответствует имени архивируемой директории/файла полученного из `path` с
помощью утилиты ``basename``. Вычисляется автоматически, не может быть
задан в скрипте.
``name_date_format``
| Тип: строка
| Умолчание: _%Y%m%d
Дата, интерпретируемая утилитой ``date``. Полученная строка используется в
имени файла бэкапа.
``name_prefix``
| Тип: строка
| Умолчание: имя_скрипта\_
Префикс имени файла. Может быть задан в скрипте. Значение по-умолчанию
состоит из имени скрипта резервного копирования и знака "_".
``name_suffix``
| Тип: строка
| Умолчание: -%H%M
Суффикс, добавляемый к имени файла перед расширением. Строка
интерпретируется утилитой ``date``.
``name_ext``
| Тип: строка
| Умолчание: нет
Расширение имени файла соответствующее формату архива. Вычисляется
автоматически и не может быть задано в скрипте резервного копирования.
``mysqldump_options``
| Тип: строка
| Умолчание: нет
Опции для утилиты ``mysqldump``.
``pg_dump_options``
| Тип: строка
| Умолчание: нет
Опции для утилиты ``pg_dump``.
``s3cmd_config``
| Тип: строка
| Умолчание: нет
Путь к файлу конфигурации утилиты ``s3cmd``. См. соответствующую страницу
страницу справки ``s3cmd``\(1).
``s3cmd_options``
| Тип: строка
| Умолчание: --preserve --quiet --no-progress
Опции для утилиты ``s3cmd``.
``s3_access_key``
| Тип: строка
| Умолчание: нет
Значение для опции ``s3cmd`` ``--access_key``.
``s3_secret_key``
| Тип: строка
| Умолчание: нет
Значение для опции ``s3cmd`` ``--secret_key``.
``s3_host``
| Тип: строка
| Умолчание: нет
Значение для опции ``s3cmd`` ``--host``. Должен содержать адрес эндпоинта
для доступа к объектному хранилищу без схемы (только домен).
``s3_host_bucket``
| Тип: строка
| Умолчание: нет
Значение для опции ``s3cmd`` ``--host-bucket``. Шаблон для `virtual-hosted
style` адреса бакета. Для `path style` это значение должно совпадать с
`s3_host`.
``s3_region``
| Тип: строка
| Умолчание: na
Значение для опции ``s3cmd`` ``--region`` или ``--bucket_location``.
Переменная необязательна к заполнению, так как некоторые S3-совместимые
хранилища не используют регионы. В таком случае будет использован фиктивный
регион `na` (not available).
``tar_options``
| Тип: строка
| Умолчание: -acf
Опции ``tar``. См. ``tar``\(1).
``tar_exclude``
| Тип: массив
| Умолчание: нет
Список имён для опции ``tar`` ``--exclude``. Пример::
tar_exclude=( foo bar )
Массив разворачивается в строку вида '--exclude=foo --exclude=bar' и
подставляется в строку опций ``tar``.
ВСТРОЕННЫЕ ФУНКЦИИ
------------------
``set_compression``
Определить утилиту и расширение файла на основе строки.
При вызове этой функции в качестве аргумента ей передаётся значение
переменной $compression. На её основе функция задаёт переменные $cmpr_ext,
$tar_ext и $cmpr_cmd. $tar_ext используется только в функции ``src_tar``,
другие две в функции ``compress_file``.
См. таблицу в описании переменной $compression.
``compress_file``
Выполнить сжатие файла и напечатать имя сжатого файла. Удалить несжатый
файл.
Внутри себя вызывает функцию ``set_compression`` для определния утилиты и
расширения файла. Если переменная $compression не задана, то сжатие не
производится.
``gen_backup_name``
Функция печатает строку, содержащую имя файла. Имя генерируется с помощью
команды::
date +"${name_prefix}${name}${name_date_format}${name_suffix}${name_ext}"
$name_ext принимает значение, переданное в качестве аргумента. См. описания
переменных выше и также в исходном коде функции.
``handle_error``
Обработать ошибку. Делает проверку и вызывает пользовательскую функцию
``on_error``.
``is_function_set``
Проверить задана ли функция и вернуть код выхода. Применима в конструкции
**if**.
``is_installed``
Проверить установлена ли утилита и выйти из скрипта при неудаче.
``log``
Записать сообщение в лог.
Синтаксис: **log** [-pV] сообщение
| Опции:
| -p напечатать сообщение также на экран (STDOUT)
| -V игнорировать опцию **--verbose**
Функция записывает сообщения в лог-файл. Лог-файл может быть задан через
опцию **--log-file**, имя этого файла будет сохранено в переменную
$__log_file. **log** перед записью в файл удаляет из текста
escape-последовательности ANSI.
Формат лога '[%s] %s\\n', где первое вхождение %s заменяется на дату, а
второе на текст сообщения. Формат даты задаётся через переменную
$log_date_format (см. описание выше).
Все сообщения, отправляемые в **log** печатаются в терминал, если
**boring_backup** запущен с опцией **--verbose**. Избежать этого можно
вызвав логгер с опцией **-V**.
``parse_uri``
Разобрать строку URI на компоненты. Парсер соответствует RFC 3986.
Функция задаёт переменные: $scheme, $username, $password, $hostname,
$port, $path, $query, $fragment
Поддерживается работа с IPv6 адресами, если они заключены в квадратные
скобки.
Поддерживается работа с паролями, содержащими зарезервированные символы.
Такие пароли необходимо закодировать в так называемый percent code.
**parse_uri** возвращает в переменной $password уже раскодированный пароль.
Ниже представлены примеры кодирования паролей в командной строке.
Python 2::
python2 -c "import urllib, sys; \
print urllib.quote(sys.argv[1], safe='')" 'p@$$w0rd'
Python 3::
python3 -c "import urllib.parse, sys; \
print(urllib.parse.quote(sys.argv[1], safe=''))" 'p@$$w0rd'
Perl 5::
echo 'p@$$w0rd' | perl -MURI::Escape -wlne 'print uri_escape $_'
``remove_if_empty``
Удалить файл, если он пустой.
``src_mysqldump``
Получить SQL дамп базы данных MariaDB или MySQL.
Дамп выполняется с помощью утилиты ``mysqldump``. Ей можно передать
дополнительные опции через переменную $mysqldump_options (см. описание
выше).
``src_pg_dump``
Получить SQL дамп базы данных PostgreSQL.
Дамп выполняется с помощью утилиты ``pg_dump``. Ей можно передать
дополнительные опции через переменную $pg_dump_options (см. описание выше).
``src_tar``
Создать архив tar. Используемые переменные: $tar_options, $tar_exclude.
``tgt_cp``
Скопировать файлы в новое назначение.
Эта функция вызывается при каждом запуске резервного копирования и
обрабатывает схему `file` в массиве `targets`. Если в массиве есть
несколько URI со схемой `file`, то ``tgt_cp`` скопирует файлы из первой
директории во все остальные.
``tgt_s3cmd``
Загрузить файлы в S3-совместимое объектное хранилище с помощью ``s3cmd``.
Реквизиты для подключения к хранилищу можно передать в конфигурационном
файл ``s3cmd`` указав путь до него в переменной $s3cmd_config.
Помимо этого реквизиты можно записать прямо в скрипт резервного копирования
в переменные: $s3_access_key, $s3_secret_key, $s3_host, $s3_host_bucket,
$s3_region. Дополнительные опции для ``s3cmd`` можно задать через
$s3cmd_options. См. описание всех переменных в разделе **ПЕРЕМЕННЫЕ**.
``builtin_backup``
Запустить функции ``process_source`` и ``process_target`` для каждого URI
из соответствующих массивов.
``process_source``
Запустить соответствующую функцию-обработчик для массива `sources`.
``process_target``
Запустить соответствующую функцию-обработчик для массива `targets`.
``source_script``
Выполнить проверки и загрузить (``source``) пользовательский скрипт
резервного копирования.
``validate_sources``
Проверить массив `sources`. Выполняются проверки на пустой массив и на
использование правильного набора схем URI.
``validate_targets``
Проверить массив `targets`. Выполняются проверки на пустой массив и на
использование правильного набора схем URI. Для успешной проверки массив
должен содержать хотя бы одну строку URI со схемой `file`.
ПОЛЬЗОВАТЕЛЬСКИЕ ФУНКЦИИ
------------------------
``prepare``
В этой функции можно запрограммировать действия, необходимые перед
выполнением бэкапа.
``backup``
Эта функция позволяет переопределить логику резервной копии.
Если функция **backup** объявлена, то она будет вызвана вместо встроенной
функции **builtin_backup**.
Используйте **backup**, когда вам необходимо использовать собственную
логику вместо заложенной разработчиком **boring_backup**.
``finalise``
В этой функции можно запрограммировать действия, выполнение которых
необходимо после выполнения бэкапа.
Пример использования: удаление локальных резервных копий после их загрузки
на удалённое хранилище.
``on_error``
В этой функции можно запрограммировать действия при возникновении ошибки.
В качестве аргумента для неё передаётся строка с текстом произошедшей
ошибки.
Пример использования: отправка отчёта об ошибке на имейл.
КОНФИГУРИРОВАНИЕ
----------------
По умолчанию **boring_backup** пытается прочитать файл по пути
~/.config/boring_backup. Также путь до конфигурационного файла можно
передать через опцию **--config**.
Конфиг имеет те же свойства, что и скрипт резервного копированиия, но
загружается всякий раз после загрузки скрипта резевного копирования. Таким
образом он может переопределять заданные в скриптах функции и переменные.
Параметры, которые нежелательно определять в скриптах резервного копирования:
* log_date_format
* name_date_format
Переопределять их следует через конфигурационный файл.
ПРИМЕРЫ
-------
Скрипт для бэкапа сайта со сжатием файлов с помощью ``xz``, загрузкой в S3 и
удалением локальных бэкапов после загрузки::
compression=xz
s3cmd_config=~/.s3cfg
sources=(
/var/www/www-data/example.com
mysql://example_user:Smk3mVH2@localhost/example_db
)
targets=(
/var/backups/example.com/
s3://mybucket/backups/example-com
)
finalise() {
log -p "\tClean up local backups"
log -p "\tFiles to delete: ${backups[@]}"
rm -- "${backups[@]}"
log -p "\tLocal backups deleted"
}
Бэкап домашней папки на примонтированный в /mnt/backups сетевой диск::
compression=xz
tar_exclude=(.cache)
sources=(/home/john)
targets=(/mnt/backups)
Бэкап приложения Gitea::
sources=(.) # just pass validation
targets=(.)
today="$(date +%d_%b_%Y)"
s3cmd_config=~/.s3cfg
prepare() {
systemctl stop gitea.service
sleep 5
}
backup() {
log -p "Dumping Gitea"
su -c "/usr/local/bin/gitea dump -c /etc/gitea/app.ini \
-f /home/git/.cache/gitea_dump.zip" - git 2>> "$__log_file"
backups+=(/home/git/.cache/gitea_dump.zip)
tgt_s3cmd s3://mybucket/backups/gitea-$today
}
finalise() {
systemctl start gitea.service
rm "${backups[@]}"
}
ОКРУЖЕНИЕ
---------
LIBRARY
Если задана переменная окружения $LIBRARY, то её значение будет
использовано в качестве пути для поиска библиотеки **boring_backup**.
СМ. ТАКЖЕ
---------
``bash``\(1), ``date``\(1), ``cp``\(1), ``tar``\(1), ``mysqldump``\(1),
``pg_dump``\(1), ``s3cmd``\(1)
RFC 3986 https://datatracker.ietf.org/doc/html/rfc3986
ОШИБКИ
------
https://git.nxhs.cloud/ge/boring_backup/issues

View File

@ -1,6 +1,6 @@
#!/usr/bin/env bash
# boring-backup -- backup files and databases.
# boring_backup -- backup files and databases.
# Copyright (c) 2022 ge <https://nixhacks.net/>
#
# This program is free software: you can redistribute it and/or modify
@ -16,12 +16,7 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
__version='0.1.0'
__config=
__verbose=
__log_file='./log.txt'
__pid_file='/tmp/boring-backup.pid'
VERSION='0.1.0'
LIBRARY="${LIBRARY:-./lib}"
# Source library
@ -30,24 +25,47 @@ if [ -f "$LIBRARY/lib.sh" ]; then
. "$LIBRARY/lib.sh"
else
echo "Error: Cannot source library $LIBRARY/lib.sh: No such file" >&2
__exit=1
fi
print_help() {
cat <<- EOF
Backup files and databases.
printf << EOF \
"USAGE:
Usage: $0 [-cvlphV] FILES..
$0 [-hVvs] [-c \033[4mfile\033[0m] [-l \033[4mfile\033[0m] \
[-p \033[4mfile\033[0m] file ...
Options:
-c, --config config file.
-v, --verbose verbose output.
-l, --log-file log file [default: $__log_file]
-p, --pid-file PID file [default: $__pid_file]
-h, --help print this help messagea and exit.
-V, --version print version and exit.
OPTIONS:
Environment:
LIBRARY path to bb library [current: $LIBRARY]
-h, --help
Print this help message and exit.
-V, --version
Print version and exit.
-v, --verbose
Enable verbose output.
-c, --config=\033[4mfile\033[0m
Path to configuration file. Default: ~/.config/boring_backup
Configuration file actually is Bash-script similar to backup
script. See boring_backup(1) CONFIGURATION.
-l, --log-file=\033[4mfile\033[0m
Log file.
-s, --use-syslog
Write log into syslog via logger instead of log file. This option
is incompatible with --log-file option and log_date_format variable.
-p, --pid-file=\033[4mfile\033[0m
PID file. Default: /tmp/boring_backup.pid
ENVIRONMENT:
LIBRARY Path to boring_backup library. Current path is
$LIBRARY
"
EOF
}
@ -88,33 +106,70 @@ for args in "$@"; do
shift
case "$args" in
--*)
set -- "$@" "$args";; # save long options
set -- "$@" "$args" # save long options
;;
-*)
args="$(echo "${args:1}" | grep -o . | xargs -I {} echo -n '-{} ')"
args="$(echo "${args:1}" |
grep -o . | xargs -I {} echo -n '-{} ')"
# shellcheck disable=SC2086
set -- "$@" $args;; # 'args' must be unquoted!
set -- "$@" $args # 'args' must be unquoted!
;;
*)
set -- "$@" "$args";; # save positional arguments
set -- "$@" "$args" # save positional arguments
;;
esac
done
# Final arguments parser
while (( "$#" )); do
case "$1" in
-h|--help)
print_help
exit 0
;;
-V|--version)
echo "$VERSION"
exit 0
;;
-v|--verbose)
verbose_output=1
shift
;;
-c|--config|--config=*)
optval "$1" "$2"; __config="$val"; shift "$sft";;
-v|--verbose) __verbose=1; shift;;
optval "$1" "$2"
bb_config="$val"
shift "$sft"
;;
-l|--log-file|--log-file=*)
optval "$1" "$2"; __log_file="$val"; shift "$sft";;
optval "$1" "$2"
log_file="$val"
shift "$sft"
;;
-s|--use-syslog)
use_syslog=1
shift
;;
-p|--pid-file|--pid-file=*)
optval "$1" "$2"; __pid_file="$val"; shift "$sft";;
-h|--help) print_help; exit 0;;
-V|--version) echo "$__version"; exit 0;;
-*) echo "Error: Unknown option: $1" >&2; exit 1;;
*) __args+=("$1"); shift;; # Save positional args
optval "$1" "$2"
pid_file="$val"
shift "$sft"
;;
-*)
echo "Error: Unknown option: $1" >&2
exit 1
;;
*)
__args+=("$1") # Save positional args
shift
;;
esac
done
# -- Set defaults -- #
log_file="${log_file:-./log.txt}"
bb_config="${bb_config:-$HOME/.config/boring_backup}"
pid_file="${pid_file:-/tmp/boring_backup.pid}"
# Exit if library is not loaded
if ! declare -F -- log > /dev/null 2>&1; then
exit 1
@ -127,20 +182,20 @@ fi
log -V "Backup STARTED"
# Check PID file
if [ -e "$__pid_file" ]; then
if [ -e "$pid_file" ]; then
# shellcheck disable=SC2009
# shellcheck disable=SC2143
if [ -z "$(ps ax -o pid | grep "$(cat "$__pid_file")")" ]; then
log -p "Process $(cat "$__pid_file") died." >&2
rm "$__pid_file"
if [ -z "$(ps ax -o pid | grep "$(cat "$pid_file")")" ]; then
log -p "Process $(cat "$pid_file") died." >&2
rm "$pid_file"
else
echo "Process $(cat "$__pid_file") still running." >&2
echo "Process $(cat "$pid_file") still running." >&2
exit 1
fi
fi
# Touch PID file
echo "$$" > "$__pid_file"
echo "$$" > "$pid_file"
# Scripts counter.
__count="${#__args[@]}" # count
@ -149,9 +204,12 @@ __i=1 # iterator
# Startup log.
date +'Start: %d %b %Y %T %z'
log -p "Library path: $LIBRARY"
log -p "Log file: $__log_file"
log -p "Configuration file:" \
"$([ "$__config" ] || echo not specified && echo "$__config")"
log -p "Log file: $log_file"
log -p "Configuration file:" "$(\
if [ -f "$bb_config" ];
then echo "$bb_config";
else echo not specified;
fi)"
log -p "Total scripts: $__count"
log "Scripts to process (${__count}): ${__args[*]}"
@ -171,7 +229,7 @@ for script in "${__args[@]}"; do
# Config can ovewrite script functions and variables
# shellcheck source=/dev/null
[ -n "$__config" ] && . "$__config"
[ -f "$bb_config" ] && . "$bb_config"
# --- Run user script -- #
@ -208,17 +266,10 @@ for script in "${__args[@]}"; do
# Unset user defined variables
unset compression
unset name_prefix
unset name_date_format
unset s3cmd_options
unset s3cmd_config
unset s3_access_key
unset s3_secret_key
unset s3_region
unset s3_host
unset s3_host_bucket
unset tar_options
unset tar_exclude
unset name_prefix name_date_format name_prefix name_suffix
unset s3cmd_config s3cmd_options
unset s3_access_key s3_secret_key s3_region s3_host s3_host_bucket
unset tar_options tar_exclude
unset mysqldump_options
unset pg_dump_options
done
@ -227,4 +278,6 @@ echo -e "\nBackup [Done]"
log -V "Backup FINISHED"
# Remove PID file
rm "$__pid_file"
rm "$pid_file"
exit "${__exit:-0}"

View File

@ -25,7 +25,6 @@ tgt_s3cmd() {
log "Run handler ${FUNCNAME[0]}()"
local uri
local src_path
uri="$1"
@ -44,7 +43,7 @@ tgt_s3cmd() {
# Set s3cmd comand. See s3cmd(1)
if [ -n "$s3cmd_config" ]; then
# Use configuration file
# shellcheck disable=SC2154
# shellcheck disable=SC2154,SC2086
set -- s3cmd $s3cmd_options --config "$s3cmd_config" \
put "${backups[@]}" "$uri"
elif [ -n "$s3_access_key" ] && \
@ -54,7 +53,7 @@ tgt_s3cmd() {
then
s3_region="${s3_region:-na}" # fallback to 'no available' region
# Use parameters provided from backup script
# shellcheck disable=SC2154
# shellcheck disable=SC2154,SC2086
set -- s3cmd $s3cmd_options \
--access_key="$s3_access_key" \
--secret_key="$s3_secret_key" \
@ -74,6 +73,7 @@ tgt_s3cmd() {
# ^^^ hide secret_key from output ^^^
# Upload backups
# shellcheck disable=SC2154
if "$@" 2>> "$__log_file"; then
: # Success
else