From 0e4845d956d96761b7b4760381636f3d0e9a9dd3 Mon Sep 17 00:00:00 2001 From: imbeer Date: Wed, 4 Jun 2025 03:02:32 +0300 Subject: [PATCH] #196: add backup service --- .../database_backup_service/install.sh | 135 ++++++++++++++++ .../lib/backup_worker.sh.template | 69 ++++++++ .../database_backup_service/restore.sh | 150 ++++++++++++++++++ .../database_backup_service/uninstall.sh | 97 +++++++++++ 4 files changed, 451 insertions(+) create mode 100755 backend/scripts/database_backup_service/install.sh create mode 100644 backend/scripts/database_backup_service/lib/backup_worker.sh.template create mode 100755 backend/scripts/database_backup_service/restore.sh create mode 100755 backend/scripts/database_backup_service/uninstall.sh diff --git a/backend/scripts/database_backup_service/install.sh b/backend/scripts/database_backup_service/install.sh new file mode 100755 index 00000000..c28befab --- /dev/null +++ b/backend/scripts/database_backup_service/install.sh @@ -0,0 +1,135 @@ +#!/bin/bash + +BASE_DIR=$(dirname "$0") +TEMPLATE_WORKER_SCRIPT="${BASE_DIR}/lib/backup_worker.sh.template" +INSTALLED_WORKER_DIR="${HOME}/.pg_backup_manager/scripts" +CONFIG_FILE="${HOME}/.pg_backup_manager/config" +CRON_JOB_COMMENT_PREFIX="PG_AUTO_BACKUP_JOB_FOR" + +ask_value() { + local prompt="$1" + local default_value="$2" + local var_name="$3" + local input_value + read -r -p "$prompt [$default_value]: " input_value + eval "$var_name=\"${input_value:-$default_value}\"" +} + +ask_password() { + local prompt="$1" + local var_name="$2" + local pass + echo -n "$prompt: " + stty -echo + read -r pass + stty echo + echo + eval "$var_name=\"$pass\"" +} + +echo "--- Установка автоматического бэкапа PostgreSQL ---" + +ask_value "Имя базы данных для бэкапа" "" DB_NAME +while [ -z "$DB_NAME" ]; do echo "Имя БД не может быть пустым."; ask_value "Имя базы данных" "" DB_NAME; done + +ask_value "Пользователь PostgreSQL" "$(whoami)" DB_USER +ask_value "Хост PostgreSQL (оставьте пустым для localhost)" "localhost" DB_HOST +ask_value "Порт PostgreSQL (оставьте пустым для 5432)" "5432" DB_PORT +ask_password "Пароль для пользователя ${DB_USER}" DB_PASSWORD +while [ -z "$DB_PASSWORD" ]; do echo "Пароль не может быть пустым."; ask_password "Пароль для пользователя ${DB_USER}" DB_PASSWORD; done + +DEFAULT_BACKUP_DIR="${HOME}/pg_backups/${DB_NAME}" +ask_value "Директория для хранения бэкапов" "$DEFAULT_BACKUP_DIR" BACKUP_DIR +ask_value "Количество дней хранения бэкапов (целое число)" "7" DAYS_TO_KEEP +while ! [[ "$DAYS_TO_KEEP" =~ ^[0-9]+$ ]] || [ "$DAYS_TO_KEEP" -lt 1 ]; do + echo "Некорректное значение. Введите целое положительное число." + ask_value "Количество дней хранения бэкапов" "7" DAYS_TO_KEEP +done + +ask_value "Минута для запуска cron (0-59)" "30" CRON_MINUTE +while ! [[ "$CRON_MINUTE" =~ ^[0-5]?[0-9]$ ]]; do echo "Неверное значение для минут."; ask_value "Минута (0-59)" "30" CRON_MINUTE; done +ask_value "Час для запуска cron (0-23)" "2" CRON_HOUR +while ! [[ "$CRON_HOUR" =~ ^([0-1]?[0-9]|2[0-3])$ ]]; do echo "Неверное значение для часов."; ask_value "Час (0-23)" "2" CRON_HOUR; done + +mkdir -p "$INSTALLED_WORKER_DIR" +mkdir -p "$BACKUP_DIR" +mkdir -p "$(dirname "$CONFIG_FILE")" + +PGPASS_FILE="${HOME}/.pgpass" +EFFECTIVE_DB_HOST=${DB_HOST:-localhost} +EFFECTIVE_DB_PORT=${DB_PORT:-5432} +PGPASS_ENTRY="${EFFECTIVE_DB_HOST}:${EFFECTIVE_DB_PORT}:${DB_NAME}:${DB_USER}:${DB_PASSWORD}" +PGPASS_ENTRY_CHECK="${EFFECTIVE_DB_HOST}:${EFFECTIVE_DB_PORT}:${DB_NAME}:${DB_USER}:" # Для проверки без пароля + +echo "Настройка $PGPASS_FILE..." +if [ -f "$PGPASS_FILE" ]; then + if grep -qF "$PGPASS_ENTRY_CHECK" "$PGPASS_FILE"; then + echo "Похожая запись уже существует в $PGPASS_FILE." + read -r -p "Хотите обновить её с новым паролем? (y/N): " update_pgpass + if [[ "$update_pgpass" =~ ^[Yy]$ ]]; then + grep -vF "$PGPASS_ENTRY_CHECK" "$PGPASS_FILE" > "${PGPASS_FILE}.tmp" && mv "${PGPASS_FILE}.tmp" "$PGPASS_FILE" + echo "$PGPASS_ENTRY" >> "$PGPASS_FILE" + echo "Запись в $PGPASS_FILE обновлена." + else + echo "Запись в $PGPASS_FILE не изменена. Убедитесь, что существующий пароль корректен." + fi + else + echo "$PGPASS_ENTRY" >> "$PGPASS_FILE" + echo "Запись добавлена в $PGPASS_FILE." + fi +else + echo "$PGPASS_ENTRY" > "$PGPASS_FILE" + echo "$PGPASS_FILE создан с новой записью." +fi +chmod 600 "$PGPASS_FILE" +echo "Установлены права 600 на $PGPASS_FILE." + +SAFE_DB_NAME_FOR_SCRIPT=$(echo "${DB_NAME}" | tr -cd '[:alnum:]_-') +SAFE_HOST_FOR_SCRIPT=$(echo "${EFFECTIVE_DB_HOST}" | tr -cd '[:alnum:]_-') +INSTALLED_WORKER_SCRIPT_NAME="backup_worker_${SAFE_DB_NAME_FOR_SCRIPT}_on_${SAFE_HOST_FOR_SCRIPT}.sh" +INSTALLED_WORKER_SCRIPT_PATH="${INSTALLED_WORKER_DIR}/${INSTALLED_WORKER_SCRIPT_NAME}" + +echo "Генерация скрипта бэкапа: $INSTALLED_WORKER_SCRIPT_PATH" +sed -e "s|__DB_NAME__|${DB_NAME}|g" \ + -e "s|__DB_USER__|${DB_USER}|g" \ + -e "s|__DB_HOST__|${EFFECTIVE_DB_HOST}|g" \ + -e "s|__DB_PORT__|${EFFECTIVE_DB_PORT}|g" \ + -e "s|__BACKUP_DIR__|${BACKUP_DIR}|g" \ + -e "s|__DAYS_TO_KEEP__|${DAYS_TO_KEEP}|g" \ + "$TEMPLATE_WORKER_SCRIPT" > "$INSTALLED_WORKER_SCRIPT_PATH" + +if [ $? -ne 0 ]; then + echo "ОШИБКА: Не удалось создать скрипт $INSTALLED_WORKER_SCRIPT_PATH" + exit 1 +fi +chmod +x "$INSTALLED_WORKER_SCRIPT_PATH" +echo "Скрипт бэкапа создан и сделан исполняемым." + +CRON_JOB_COMMENT="${CRON_JOB_COMMENT_PREFIX}_${SAFE_DB_NAME_FOR_SCRIPT}_ON_${SAFE_HOST_FOR_SCRIPT}" +CRON_JOB_LINE="${CRON_MINUTE} ${CRON_HOUR} * * * /bin/bash ${INSTALLED_WORKER_SCRIPT_PATH} ${CRON_JOB_COMMENT}" + +echo "Добавление задачи в crontab..." +(crontab -l 2>/dev/null | grep -vF "$CRON_JOB_COMMENT" ; echo "$CRON_JOB_LINE") | crontab - +if [ $? -eq 0 ]; then + echo "Задача успешно добавлена/обновлена в crontab." + echo "Бэкап будет выполняться ежедневно в ${CRON_HOUR}:${CRON_MINUTE}." +else + echo "ОШИБКА при добавлении задачи в crontab. Попробуйте добавить вручную:" + echo "$CRON_JOB_LINE" +fi + +CONFIG_KEY_PREFIX="${SAFE_DB_NAME_FOR_SCRIPT}_ON_${SAFE_HOST_FOR_SCRIPT}" +{ + echo "${CONFIG_KEY_PREFIX}_WORKER_SCRIPT_PATH=\"${INSTALLED_WORKER_SCRIPT_PATH}\"" + echo "${CONFIG_KEY_PREFIX}_BACKUP_DIR=\"${BACKUP_DIR}\"" + echo "${CONFIG_KEY_PREFIX}_CRON_COMMENT=\"${CRON_JOB_COMMENT}\"" + echo "${CONFIG_KEY_PREFIX}_DB_NAME=\"${DB_NAME}\"" + echo "${CONFIG_KEY_PREFIX}_DB_USER=\"${DB_USER}\"" + echo "${CONFIG_KEY_PREFIX}_DB_HOST=\"${EFFECTIVE_DB_HOST}\"" + echo "${CONFIG_KEY_PREFIX}_DB_PORT=\"${EFFECTIVE_DB_PORT}\"" +} >> "$CONFIG_FILE" +chmod 600 "$CONFIG_FILE" + +echo "--- Установка завершена! ---" +echo "Проверьте работу, запустив: ${INSTALLED_WORKER_SCRIPT_PATH}" +echo "Логи будут в ${BACKUP_DIR}/_backup.log" \ No newline at end of file diff --git a/backend/scripts/database_backup_service/lib/backup_worker.sh.template b/backend/scripts/database_backup_service/lib/backup_worker.sh.template new file mode 100644 index 00000000..322d06c2 --- /dev/null +++ b/backend/scripts/database_backup_service/lib/backup_worker.sh.template @@ -0,0 +1,69 @@ +#!/bin/bash + +DB_NAME="__DB_NAME__" +DB_USER="__DB_USER__" +DB_HOST="__DB_HOST__" +DB_PORT="__DB_PORT__" + +BACKUP_DIR="__BACKUP_DIR__" +DAYS_TO_KEEP="__DAYS_TO_KEEP__" + +set -e +set -o pipefail + +LOG_FILE="${BACKUP_DIR}/_backup.log" +TIMESTAMP=$(date +%Y%m%d_%H%M%S) +SAFE_DB_NAME=$(echo "${DB_NAME}" | tr -cd '[:alnum:]._-') +FILENAME="${SAFE_DB_NAME}_${TIMESTAMP}.dump" +BACKUP_FILE_FULL_PATH="${BACKUP_DIR}/${FILENAME}" +COMPRESSED_BACKUP_FILE="${BACKUP_FILE_FULL_PATH}.gz" + +PG_DUMP_OPTIONS="-Fc -Z0" + +CONNECT_OPTS="" +if [ -n "$DB_HOST" ] && [ "$DB_HOST" != "localhost" ] && [ "$DB_HOST" != "127.0.0.1" ]; then + CONNECT_OPTS="$CONNECT_OPTS -h $DB_HOST" +fi +if [ -n "$DB_PORT" ] && [ "$DB_PORT" != "5432" ]; then + CONNECT_OPTS="$CONNECT_OPTS -p $DB_PORT" +fi + +log_msg() { + echo "$(date +'%Y-%m-%d %H:%M:%S') - $1" | tee -a "$LOG_FILE" +} + +log_msg "--------------------------------------------" +log_msg "Начало бэкапа для БД: ${DB_NAME}" +log_msg "Пользователь: ${DB_USER}, Хост: ${DB_HOST:-localhost}, Порт: ${DB_PORT:-5432}" +log_msg "Директория бэкапов: ${BACKUP_DIR}, Хранить дней: ${DAYS_TO_KEEP}" + +mkdir -p "$BACKUP_DIR" +if [ ! -d "$BACKUP_DIR" ]; then + log_msg "ОШИБКА: Не удалось создать директорию ${BACKUP_DIR}" + exit 1 +fi + +log_msg "Создание дампа: ${BACKUP_FILE_FULL_PATH}" +pg_dump $PG_DUMP_OPTIONS $CONNECT_OPTS -U "$DB_USER" -d "$DB_NAME" -w -f "$BACKUP_FILE_FULL_PATH" + +if [ $? -ne 0 ]; then + log_msg "ОШИБКА при создании дампа ${DB_NAME}!" + rm -f "$BACKUP_FILE_FULL_PATH" 2>/dev/null + exit 1 +fi +log_msg "Дамп успешно создан." + +log_msg "Сжатие дампа: ${COMPRESSED_BACKUP_FILE}" +gzip "$BACKUP_FILE_FULL_PATH" +if [ $? -ne 0 ]; then + log_msg "ОШИБКА при сжатии файла ${BACKUP_FILE_FULL_PATH}!" + exit 1 +fi +log_msg "Дамп успешно сжат." + +log_msg "Удаление старых бэкапов (старше ${DAYS_TO_KEEP} дней)..." +find "$BACKUP_DIR" -maxdepth 1 -type f -name "${SAFE_DB_NAME}_*.dump.gz" -mtime "+${DAYS_TO_KEEP}" -print -delete | while IFS= read -r line; do log_msg "Удален старый бэкап: $line"; done + +log_msg "Бэкап успешно завершен." +log_msg "--------------------------------------------" +exit 0 \ No newline at end of file diff --git a/backend/scripts/database_backup_service/restore.sh b/backend/scripts/database_backup_service/restore.sh new file mode 100755 index 00000000..db03673c --- /dev/null +++ b/backend/scripts/database_backup_service/restore.sh @@ -0,0 +1,150 @@ +#!/bin/bash + +CONFIG_FILE="${HOME}/.pg_backup_manager/config" + +ask_value() { + local prompt="$1" + local default_value="$2" + local var_name="$3" + local input_value + read -r -p "$prompt [$default_value]: " input_value + eval "$var_name=\"${input_value:-$default_value}\"" +} + +echo "--- Восстановление бэкапа PostgreSQL ---" + +BACKUP_DIR_TO_RESTORE="" +DEFAULT_DB_NAME="" +DEFAULT_DB_USER="" +DEFAULT_DB_HOST="localhost" +DEFAULT_DB_PORT="5432" + +if [ -f "$CONFIG_FILE" ]; then + echo "Найдены следующие настроенные конфигурации бэкапов:" + + declare -A backup_configs + config_idx=1 + while IFS= read -r line; do + if [[ "$line" =~ ^([^_]+_ON_[^_]+)_DB_NAME=\"(.*)\"$ ]]; then + prefix="${BASH_REMATCH[1]}" + db_name_display="${BASH_REMATCH[2]}" + backup_dir_display=$(grep "^${prefix}_BACKUP_DIR=" "$CONFIG_FILE" | cut -d'"' -f2) + if [ -n "$backup_dir_display" ]; then + echo "$config_idx) БД: $db_name_display (Бэкапы в: $backup_dir_display)" + backup_configs[$config_idx]="$backup_dir_display;$db_name_display" + ((config_idx++)) + fi + fi + done < <(grep "_DB_NAME=" "$CONFIG_FILE" | sort -u) + + + echo "$config_idx) Ввести путь к директории бэкапов вручную" + echo "0) Отмена" + + read -r -p "Выберите конфигурацию для восстановления или введите путь вручную (0 для отмены): " choice + if ! [[ "$choice" =~ ^[0-9]+$ ]]; then echo "Неверный ввод."; exit 1; fi + if [ "$choice" -eq 0 ]; then echo "Отмена."; exit 0; fi + + if [ "$choice" -lt "$config_idx" ]; then + selected_config=${backup_configs[$choice]} + BACKUP_DIR_TO_RESTORE=$(echo "$selected_config" | cut -d';' -f1) + DEFAULT_DB_NAME=$(echo "$selected_config" | cut -d';' -f2) + fi +fi + +if [ -z "$BACKUP_DIR_TO_RESTORE" ]; then + ask_value "Введите полный путь к директории с бэкапами" "" BACKUP_DIR_TO_RESTORE +fi + +if [ ! -d "$BACKUP_DIR_TO_RESTORE" ]; then + echo "ОШИБКА: Директория $BACKUP_DIR_TO_RESTORE не найдена." + exit 1 +fi + +echo -e "\nДоступные файлы бэкапов в $BACKUP_DIR_TO_RESTORE (формат .dump.gz):" +mapfile -t backup_files < <(find "$BACKUP_DIR_TO_RESTORE" -maxdepth 1 -type f -name "*.dump.gz" -printf "%T@ %p\n" | sort -nr | cut -d' ' -f2- | xargs -L1 basename) + +if [ ${#backup_files[@]} -eq 0 ]; then + echo "Бэкапы не найдены в $BACKUP_DIR_TO_RESTORE." + exit 1 +fi + +for i in "${!backup_files[@]}"; do + printf "%3d) %s\n" $((i+1)) "${backup_files[$i]}" +done +echo " 0) Отмена" + +read -r -p "Введите номер файла для восстановления: " file_choice +if ! [[ "$file_choice" =~ ^[0-9]+$ ]] || [ "$file_choice" -lt 0 ] || [ "$file_choice" -gt ${#backup_files[@]} ]; then + echo "Неверный выбор." + exit 1 +fi +if [ "$file_choice" -eq 0 ]; then echo "Восстановление отменено."; exit 0; fi + + +SELECTED_BACKUP_GZ_BASENAME="${backup_files[$((file_choice-1))]}" +SELECTED_BACKUP_GZ_FULLPATH="${BACKUP_DIR_TO_RESTORE}/${SELECTED_BACKUP_GZ_BASENAME}" +SELECTED_BACKUP_DUMP_FULLPATH="${SELECTED_BACKUP_GZ_FULLPATH%.gz}" # Убираем .gz + +echo "Выбран файл: $SELECTED_BACKUP_GZ_FULLPATH" + +echo -e "\nВведите данные для подключения к ЦЕЛЕВОЙ базе данных PostgreSQL (КУДА восстанавливать):" +ask_value "Имя целевой базы данных" "$DEFAULT_DB_NAME" RESTORE_DB_NAME +while [ -z "$RESTORE_DB_NAME" ]; do echo "Имя БД не может быть пустым."; ask_value "Имя целевой базы данных" "$DEFAULT_DB_NAME" RESTORE_DB_NAME; done + +ask_value "Пользователь PostgreSQL для восстановления" "$(whoami)" RESTORE_DB_USER +ask_value "Хост PostgreSQL (оставьте пустым для localhost)" "$DEFAULT_DB_HOST" RESTORE_DB_HOST +ask_value "Порт PostgreSQL (оставьте пустым для 5432)" "$DEFAULT_DB_PORT" RESTORE_DB_PORT + +CLEAN_BEFORE_RESTORE="n" +read -r -p "Очистить целевую базу данных перед восстановлением (DROP OBJECTS)? (y/N): " confirm_clean +if [[ "$confirm_clean" =~ ^[Yy]$ ]]; then + CLEAN_BEFORE_RESTORE="y" +fi + +echo -e "\nВНИМАНИЕ: Это действие перезапишет данные в базе '${RESTORE_DB_NAME}' на '${RESTORE_DB_HOST:-localhost}'!" +if [[ "$CLEAN_BEFORE_RESTORE" == "y" ]]; then + echo "Все существующие объекты в базе '${RESTORE_DB_NAME}' будут УДАЛЕНЫ перед восстановлением." +fi +read -r -p "Вы абсолютно уверены, что хотите продолжить? (Введите 'YES_RESTORE' для подтверждения): " confirm_action +if [ "$confirm_action" != "YES_RESTORE" ]; then + echo "Восстановление отменено." + exit 0 +fi + +echo "Распаковка $SELECTED_BACKUP_GZ_FULLPATH..." +gunzip -k -f "$SELECTED_BACKUP_GZ_FULLPATH" # -k оставляет .gz, -f перезаписывает .dump если есть +if [ $? -ne 0 ]; then echo "ОШИБКА: не удалось распаковать $SELECTED_BACKUP_GZ_FULLPATH"; exit 1; fi +echo "Файл распакован: $SELECTED_BACKUP_DUMP_FULLPATH" + +RESTORE_OPTS="-d $RESTORE_DB_NAME -U $RESTORE_DB_USER -v" # -v для подробного вывода +EFFECTIVE_RESTORE_DB_HOST=${RESTORE_DB_HOST:-localhost} +EFFECTIVE_RESTORE_DB_PORT=${RESTORE_DB_PORT:-5432} + +if [ "$EFFECTIVE_RESTORE_DB_HOST" != "localhost" ] && [ "$EFFECTIVE_RESTORE_DB_HOST" != "127.0.0.1" ]; then + RESTORE_OPTS="$RESTORE_OPTS -h $EFFECTIVE_RESTORE_DB_HOST" +fi +if [ "$EFFECTIVE_RESTORE_DB_PORT" != "5432" ]; then + RESTORE_OPTS="$RESTORE_OPTS -p $EFFECTIVE_RESTORE_DB_PORT" +fi + +if [[ "$CLEAN_BEFORE_RESTORE" == "y" ]]; then + RESTORE_OPTS="$RESTORE_OPTS --clean" +fi + +echo "Запуск pg_restore..." +pg_restore $RESTORE_OPTS "$SELECTED_BACKUP_DUMP_FULLPATH" + +if [ $? -eq 0 ]; then + echo "Восстановление успешно завершено." +else + echo "ОШИБКА во время восстановления. Проверьте вывод выше." +fi + +read -r -p "Удалить распакованный файл ${SELECTED_BACKUP_DUMP_FULLPATH}? (y/N): " delete_dump +if [[ "$delete_dump" =~ ^[Yy]$ ]]; then + rm -f "$SELECTED_BACKUP_DUMP_FULLPATH" + echo "Файл $SELECTED_BACKUP_DUMP_FULLPATH удален." +fi + +echo "--- Процесс восстановления завершен ---" \ No newline at end of file diff --git a/backend/scripts/database_backup_service/uninstall.sh b/backend/scripts/database_backup_service/uninstall.sh new file mode 100755 index 00000000..2b8d5551 --- /dev/null +++ b/backend/scripts/database_backup_service/uninstall.sh @@ -0,0 +1,97 @@ +#!/bin/bash + +CONFIG_FILE="${HOME}/.pg_backup_manager/config" + +echo "--- Удаление автоматического бэкапа PostgreSQL ---" + +if [ ! -f "$CONFIG_FILE" ]; then + echo "Файл конфигурации $CONFIG_FILE не найден. Удаление невозможно." + exit 1 +fi + +echo "Найдены следующие настроенные бэкапы:" +grep -oP '^[^_]+_ON_[^_]+' "$CONFIG_FILE" | sort -u | nl +echo "0) Отмена" + +read -r -p "Введите номер бэкапа для удаления (или 0 для отмены): " choice +if ! [[ "$choice" =~ ^[0-9]+$ ]]; then + echo "Неверный ввод." + exit 1 +fi +if [ "$choice" -eq 0 ]; then + echo "Удаление отменено." + exit 0 +fi + +SELECTED_PREFIX=$(grep -oP '^[^_]+_ON_[^_]+' "$CONFIG_FILE" | sort -u | sed -n "${choice}p") + +if [ -z "$SELECTED_PREFIX" ]; then + echo "Неверный выбор." + exit 1 +fi + +echo "Выбран для удаления бэкап с идентификатором: $SELECTED_PREFIX" + +WORKER_SCRIPT_PATH=$(grep "^${SELECTED_PREFIX}_WORKER_SCRIPT_PATH=" "$CONFIG_FILE" | cut -d'"' -f2) +BACKUP_DIR=$(grep "^${SELECTED_PREFIX}_BACKUP_DIR=" "$CONFIG_FILE" | cut -d'"' -f2) +CRON_COMMENT=$(grep "^${SELECTED_PREFIX}_CRON_COMMENT=" "$CONFIG_FILE" | cut -d'"' -f2) +DB_NAME_FOR_PGPASS=$(grep "^${SELECTED_PREFIX}_DB_NAME=" "$CONFIG_FILE" | cut -d'"' -f2) +DB_USER_FOR_PGPASS=$(grep "^${SELECTED_PREFIX}_DB_USER=" "$CONFIG_FILE" | cut -d'"' -f2) +DB_HOST_FOR_PGPASS=$(grep "^${SELECTED_PREFIX}_DB_HOST=" "$CONFIG_FILE" | cut -d'"' -f2) +DB_PORT_FOR_PGPASS=$(grep "^${SELECTED_PREFIX}_DB_PORT=" "$CONFIG_FILE" | cut -d'"' -f2) + + +read -r -p "Вы уверены, что хотите удалить конфигурацию бэкапа для '${DB_NAME_FOR_PGPASS}' на '${DB_HOST_FOR_PGPASS}'? (y/N): " confirm_delete +if [[ ! "$confirm_delete" =~ ^[Yy]$ ]]; then + echo "Удаление отменено." + exit 0 +fi + +if [ -n "$CRON_COMMENT" ]; then + echo "Удаление задачи из crontab с комментарием: $CRON_COMMENT" + (crontab -l 2>/dev/null | grep -vF "$CRON_COMMENT") | crontab - + if [ $? -eq 0 ]; then echo "Задача из crontab удалена (если существовала)."; else echo "Ошибка при удалении из crontab."; fi +else + echo "Комментарий для cron не найден в конфигурации." +fi + +if [ -f "$WORKER_SCRIPT_PATH" ]; then + read -r -p "Удалить скрипт бэкапа ${WORKER_SCRIPT_PATH}? (y/N): " delete_script + if [[ "$delete_script" =~ ^[Yy]$ ]]; then + rm -f "$WORKER_SCRIPT_PATH" + echo "Скрипт $WORKER_SCRIPT_PATH удален." + fi +else + echo "Скрипт воркера $WORKER_SCRIPT_PATH не найден." +fi + +if [ -d "$BACKUP_DIR" ]; then + read -r -p "УДАЛИТЬ ВСЕ БЭКАПЫ в директории ${BACKUP_DIR}? (ОЧЕНЬ ОПАСНО!) Введите 'YES_DELETE_BACKUPS' для подтверждения: " confirm_del_backups + if [ "$confirm_del_backups" == "YES_DELETE_BACKUPS" ]; then + rm -rf "$BACKUP_DIR" + echo "Директория $BACKUP_DIR со всеми бэкапами удалена." + else + echo "Директория бэкапов $BACKUP_DIR НЕ удалена." + fi +fi + +echo "Удаление записей из $CONFIG_FILE..." +grep -v "^${SELECTED_PREFIX}_" "$CONFIG_FILE" > "${CONFIG_FILE}.tmp" && mv "${CONFIG_FILE}.tmp" "$CONFIG_FILE" +echo "Записи для $SELECTED_PREFIX удалены из файла конфигурации." +if [ ! -s "$CONFIG_FILE" ]; then + rm -f "$CONFIG_FILE" + echo "Файл конфигурации $CONFIG_FILE был пуст и удален." + if [ -d "$(dirname "$WORKER_SCRIPT_PATH")" ] && [ -z "$(ls -A "$(dirname "$WORKER_SCRIPT_PATH")")" ]; then + rmdir "$(dirname "$WORKER_SCRIPT_PATH")" + echo "Директория $(dirname "$WORKER_SCRIPT_PATH") удалена, так как пуста." + fi + if [ -d "$(dirname "$CONFIG_FILE")" ] && [ -z "$(ls -A "$(dirname "$CONFIG_FILE")")" ]; then + rmdir "$(dirname "$CONFIG_FILE")" + echo "Директория $(dirname "$CONFIG_FILE") удалена, так как пуста." + fi +fi + +echo -e "\nНАПОМИНАНИЕ: Если вы хотите удалить соответствующую запись из ~/.pgpass, сделайте это вручную." +echo "Запись для удаления могла выглядеть так: ${DB_HOST_FOR_PGPASS}:${DB_PORT_FOR_PGPASS}:${DB_NAME_FOR_PGPASS}:${DB_USER_FOR_PGPASS}:ВАШ_ПАРОЛЬ" + +echo "--- Удаление завершено ---" \ No newline at end of file