commit 703b7ff2651810bcb58f474288f8264d633a780e Author: leo <426742@gmail.com> Date: Thu Jul 11 16:18:02 2024 +0000 create diff --git a/README.md b/README.md new file mode 100644 index 0000000..c4e20e5 --- /dev/null +++ b/README.md @@ -0,0 +1,14 @@ + +### Backup all databases & files + +**Based on the:** https://lohvynenko.com/ru/blog/a-way-to-get-daily-postgresql-backups-from-docker-swarm.html + +* В файле `backups.list` указываются папки, для которых нужно сделать резервные копии. +* Скрипт автоматически находит все базы данных в postgres db и для каждой делает резервную копию в `.sql` формате. +* Через заданный в файле `cleaner.sh` в переменной `$EXPIRE_DAYS` срок, устаревшие резервные копии будут удаляться. +* Для запуска полного процесса нужно запустить скрипт `all.sh` с `root` правами. +* Это тестовая версия скрипта, здесь могут быть недоработки. +* Кроме того, необходимо проверить переменные, пути к директориям, которые указаны непосредственно в скриптах. + +* В скрипте `remote-backup.sh` приведен пример для удаленной синхронизации папки `backups` с другим сервером. +* Скрипт должен быть запущен на другом сервере, нужно правильно указать настройки адреса сервера, пути, и кроме того, на сервере должен быть установлен ключ SSH для доступа. \ No newline at end of file diff --git a/all.sh b/all.sh new file mode 100644 index 0000000..5f9369f --- /dev/null +++ b/all.sh @@ -0,0 +1,23 @@ +#!/bin/bash + +if [ "$(id -u)" != "0" ]; then + echo -e "\033[31mThis script requires superuser rights.\033[0m" + exit 0 +fi + +trap 'echo -e "\033[31mSomething went wrong\033[0m"; exit 1' EXIT +set -e + +export DEBIAN_FRONTEND=noninteractive + +docker exec postgres psql -U admin -d postgres -t -A -F',' -c "SELECT d.datname, a.rolname FROM pg_database d JOIN pg_roles a ON d.datdba = a.oid WHERE d.datistemplate = false;" | while IFS=, read -r dbname owner; do + bash postgres.sh "$dbname" "$owner" +done + +bash files.sh +bash cleaner.sh + +echo 'Done.' + +trap - EXIT +echo "All backups were made successfully. Outdated backups have been deleted." \ No newline at end of file diff --git a/backups.list b/backups.list new file mode 100644 index 0000000..a719d60 --- /dev/null +++ b/backups.list @@ -0,0 +1,3 @@ +# /sample/folder/ +/data/appdata/gitea/ +/data/projects/ diff --git a/cleaner.sh b/cleaner.sh new file mode 100644 index 0000000..834df73 --- /dev/null +++ b/cleaner.sh @@ -0,0 +1,38 @@ +#!/bin/bash + +EXPIRE_DAYS=14 +SCAN_DIR=/backups + +if [ "$(id -u)" != "0" ]; then + echo -e "\033[31mThis script requires superuser rights.\033[0m" + exit 0 +fi + +trap 'echo -e "\033[31mSomething went wrong\033[0m"; exit 1' EXIT +set -e + +export DEBIAN_FRONTEND=noninteractive + +FILES=$(find $SCAN_DIR -type f) +for file in $FILES; + do + timestamp=$(date -r $file +%Y%m%d); + echo "Processing $file file.."; + date1yrs=$(date -d "$timestamp" +%Y); + date1days=$(date -d "$timestamp" +%j); + date2yrs=$(date +%Y); + date2days=$(date +%j); + diffYear=$(expr "$date2yrs" - "$date1yrs"); + diffYear2days=$(expr "$diffYear" \* 365); + diffDays=$(expr "$date2days" - "$date1days"); + DAYS=$(expr "$diffYear2days" + "$diffDays"); + + if [ "$DAYS" -ge $EXPIRE_DAYS ] + then + echo "Deleting $file file..."; + rm "$file"; + fi + done + +trap - EXIT +echo "All backups older than $EXPIRE_DAYS days are deleted." \ No newline at end of file diff --git a/files.sh b/files.sh new file mode 100644 index 0000000..b2c1f83 --- /dev/null +++ b/files.sh @@ -0,0 +1,62 @@ +#!/bin/bash + +if [ "$(id -u)" != "0" ]; then + echo -e "\033[31mThis script requires superuser rights.\033[0m" + exit 0 +fi + +trap 'echo -e "\033[31mSomething went wrong\033[0m"; exit 1' EXIT +set -e + +export DEBIAN_FRONTEND=noninteractive + +BACKUP_LIST="./backups.list" +BACKUP_DIR="/backups/files" + +# Checking the presence of a backups.list +if [ ! -f "$BACKUP_LIST" ]; then + echo "List file not found: $BACKUP_LIST" + exit 1 +fi + +# Creating main directories (if not created) +mkdir -p "$BACKUP_DIR" + +# Reading a list of directories for backup +while IFS= read -r DIR; do + # Ignore lines starting with # + if [[ "$DIR" =~ ^#.* ]]; then + continue + fi + + # Let's make sure the line is not empty + if [ -n "$DIR" ]; then + # Let's make sure the directory exists + if [ ! -d "$DIR" ]; then + echo "Directory not found: $DIR" + continue + fi + + # Formation of the archive name + BASENAME=$(basename "$DIR") + TIMESTAMP=$(date +%Y%m%d%H%M%S) + ARCHIVE_NAME="${BASENAME}_${TIMESTAMP}.tar.gz" + + # Creating a directory to store backups of this folder + BACKUP_FOLDER="${BACKUP_DIR}/${BASENAME}" + mkdir -p "$BACKUP_FOLDER" + + # Creating an archive + tar -czf "${BACKUP_FOLDER}/${ARCHIVE_NAME}" -C "$(dirname "$DIR")" "$BASENAME" + + # Checking the success of the backup + if [ $? -eq 0 ]; then + echo "Backup successfully created: ${BACKUP_FOLDER}/${ARCHIVE_NAME}" + else + echo "Error when creating a backup: ${BACKUP_FOLDER}/${ARCHIVE_NAME}" + fi + fi +done < "$BACKUP_LIST" + +trap - EXIT +echo "The backup of all specified directories has been completed successfully." \ No newline at end of file diff --git a/postgres.sh b/postgres.sh new file mode 100644 index 0000000..3a21d5f --- /dev/null +++ b/postgres.sh @@ -0,0 +1,50 @@ +#!/bin/bash + +if [ "$(id -u)" != "0" ]; then + echo -e "\033[31mThis script requires superuser rights.\033[0m" + exit 0 +fi + +if [ -z "$1" ] || [ -z "$2" ]; then + echo "Please provide both the POSTGRES_DB and POSTGRES_USER as arguments." + exit 1 +fi + +trap 'echo -e "\033[31mSomething went wrong\033[0m"; exit 1' EXIT +set -e + +export DEBIAN_FRONTEND=noninteractive + +# configuration settings +POSTGRES_DB="$1" +POSTGRES_USER="$2" + +CURRENT_MONTH=$(date +%Y-%m) +CURRENT_DATE=$(date +%Y-%m-%d) +CURRENT_DATETIME=$(date +%d-%b-%Y_%H_%M_%Z) +BACKUPS_PATH=/data/backups/postgres +DOCKER_SERVICE_NAME=postgres + +# backup PostgreSQL database +BACKUP_FOLDER=$BACKUPS_PATH/$POSTGRES_DB +if [ ! -d "$BACKUP_FOLDER" ]; then + mkdir -p "$BACKUP_FOLDER" +fi + +echo 'Creating PostgreSQL backups...' +cd "$BACKUP_FOLDER" +if [ -f 'dump_'"$POSTGRES_DB"'.sql' ]; then + rm 'dump_'"$POSTGRES_DB"'.sql' +fi +db_backup_filename=$POSTGRES_DB'_'$CURRENT_DATETIME'.tar.gz' + +docker exec -t postgres pg_dump -U $POSTGRES_USER $POSTGRES_DB > 'dump_'"$POSTGRES_DB"'.sql' + +tar -cf - 'dump_'"$POSTGRES_DB"'.sql' | gzip -9 > "$db_backup_filename" +rm 'dump_'"$POSTGRES_DB"'.sql' + +cd "$BACKUP_FOLDER" +md5sum * > MD5SUMS + +trap - EXIT +echo 'The backup of the '"$POSTGRES_DB"' database was completed successfully.' \ No newline at end of file diff --git a/service/remote-backup.sh b/service/remote-backup.sh new file mode 100644 index 0000000..0b0c372 --- /dev/null +++ b/service/remote-backup.sh @@ -0,0 +1,8 @@ +# SAMPLE + +#!/bin/bash + +REMOTE_DIR="usradmin@dev.dd:/backups/" +LOCAL_DIR="/mnt/d/backups/" + +rsync -avz --delete $REMOTE_DIR $LOCAL_DIR \ No newline at end of file