ZergRushA

pg_backup_script

Aug 3rd, 2025 (edited)
85
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Bash 5.81 KB | None | 0 0
  1. #!/bin/env bash
  2.  
  3. #Коды выхода:
  4. #0 - OK
  5. #1 - Ошибка выполнения (pg_dump, удаление бекапа и тд)
  6. #2 - Ошибка конфигурации (файла конфига нет или нет какого-то параметра)
  7. #11 - Недостаточно памяти для бекапа
  8. #12 - Ошибка подключения к серверу PostgreSQL
  9.  
  10. #--------------------
  11. #Дополнительно:
  12. #строка для для crontab
  13. #5  1   *   *   /путь/до/этого/скрипта
  14. #--------------------
  15.  
  16. if [[ -z $1 ]]; then
  17.   echo "Путь к файлу конфигурации не указан"
  18.   exit 2
  19. fi
  20.  
  21. CONFIG_PATH=$1
  22.  
  23. echo $CONFIG_PATH
  24.  
  25. # Проверяем, существует ли конфиг файл
  26. if [[ ! -f "$CONFIG_PATH" ]]; then
  27.   echo "[$(date +"%Y.%m.%d_%H:%M:%S")] [ERROR] Файл конфигурации не существует: $CONFIG_PATH"
  28.   exit 2
  29. fi
  30.  
  31. #Альтернативно можно подгрузить конфиг при помощи:
  32. #source "$CONFIG_PATH"
  33. DB_HOST=$(awk -F "=" '/DB_HOST/ {print $2}' $CONFIG_PATH)
  34. DB_USER=$(awk -F "=" '/DB_USER/ {print $2}' $CONFIG_PATH)
  35. DB_PASS=$(awk -F "=" '/DB_PASS/ {print $2}' $CONFIG_PATH)
  36. DB_BASE=$(awk -F "=" '/DB_BASE/ {print $2}' $CONFIG_PATH)
  37. BACKUP_PATH=$(awk -F "=" '/BACKUP_PATH/ {print $2}' $CONFIG_PATH)
  38. BACKUP_PREFIX=$(awk -F "=" '/BACKUP_PREFIX/ {print $2}' $CONFIG_PATH)
  39. BACKUP_COUNT=$(awk -F "=" '/BACKUP_COUNT/ {print $2}' $CONFIG_PATH)
  40.  
  41. REQUIRED_VARS=(
  42.   DB_HOST
  43.   DB_USER
  44.   DB_PASS
  45.   DB_BASE
  46.   BACKUP_PATH
  47.   BACKUP_PREFIX
  48.   BACKUP_COUNT
  49. )
  50.  
  51. for var in "${REQUIRED_VARS[@]}"; do
  52.   if [[ -z "${!var}" ]]; then
  53.     echo "[$(date +"%Y.%m.%d_%H:%M:%S")] [ERROR] Переменная $var не задана в файле конфигурации"
  54.     exit 2
  55.   fi
  56. done
  57.  
  58.  
  59. # Проверяем, что директория бекапов существует
  60. if [[ ! -d "$BACKUP_PATH" ]]; then
  61.   echo "[$(date +"%Y.%m.%d_%H:%M:%S")] [ERROR] Директория для резервных копий $BACKUP_PATH не существует"
  62.   exit 2
  63. fi
  64.  
  65. LOG_TIMESTAMP=$(date +"%Y.%m.%d_%H%M%S")
  66. LOG_FILE="$BACKUP_PATH/${BACKUP_PREFIX}.${LOG_TIMESTAMP}.log"
  67.  
  68. BACKUP_FILE="$BACKUP_PATH/${BACKUP_PREFIX}.${LOG_TIMESTAMP}.tar"
  69.  
  70. function log(){
  71.   CURR_TIMESTAMP=$(date +"%Y.%m.%d_%H:%M:%S")
  72.   echo "[$CURR_TIMESTAMP] $1" | tee -a "$LOG_FILE"
  73. }
  74.  
  75. log "[INFO] Начало резервного копирования..."
  76. log "[INFO] Пробую подключиться к серверу..."
  77.  
  78. #тестируем подключение к серверу PostgreSQL
  79. if ! pg_isready -h $DB_HOST -p 5432 -U $DB_USER; then
  80.   log "[ERROR] Не удалось подключиться к серверу PostgreSQL"
  81.   exit 12
  82. fi
  83.  
  84. log "[INFO] Успешное подключение к серверу PostgreSQL"
  85.  
  86. log "[INFO] Проверяю наличие места на диске для бекапа..."
  87.  
  88.  
  89. function convert_to_bytes(){
  90.     local num=$1
  91.     local measure_unit=$2
  92.  
  93.     case "$measure_unit" in
  94.         B) echo $((num)) ;;
  95.         kB|K) echo $((num*1024)) ;;
  96.         MB|M) echo $((num*1024*1024)) ;;
  97.         GB|G) echo $((num*1024*1024*1024)) ;;
  98.         TB|T) echo $((num*1024*1024*1024*1024)) ;;
  99.         *) echo "0" ;;
  100.     esac
  101. }
  102.  
  103.  
  104. export PGPASSWORD=$DB_PASS
  105.  
  106. #Парсим вывод размера БД и конвертируем в байты
  107. #Поскольку посчитать потенциальный бекап при помощи pg_dump
  108. #сложно, я сделал допущение (грубоватое), что размер БД приблизительно равен размеру бекапа
  109.  
  110. DB_SIZE_RAW=$(psql -h "$DB_HOST" -p 5432 -U "$DB_USER" -d "postgres" -c "SELECT pg_size_pretty(pg_database_size('$DB_BASE'));")
  111. DB_SIZE_NUM=$(echo $DB_SIZE_RAW | grep -oE '[0-9]+' | head -1)
  112. DB_SIZE_MEASURE_UNIT=$(echo $DB_SIZE_RAW | grep -oE '[kmKMGT]?B|[GKTM]')
  113. DB_SIZE_BYTES=$(convert_to_bytes $DB_SIZE_NUM $DB_SIZE_MEASURE_UNIT)
  114.  
  115. #Аналогично делаем с дисковым пространством
  116.  
  117. AVAILABLE_DISK_SPACE_RAW=$(df -h --total | awk 'END{print $4}')
  118. AVAILABLE_DISK_NUM=$(echo $AVAILABLE_DISK_SPACE_RAW | grep -oE '[0-9]+')
  119. AVAILABLE_DISK_MEASURE_UNIT=$(echo $AVAILABLE_DISK_SPACE_RAW | grep -oE '[kmKMGT]?B|[GKTM]')
  120. AVAILABLE_DISK_BYTES=$(convert_to_bytes $AVAILABLE_DISK_NUM $AVAILABLE_DISK_MEASURE_UNIT)
  121.  
  122. if [[ $DB_SIZE_BYTES -gt $AVAILABLE_DISK_BYTES ]]; then
  123.     log "[ERROR] Недостаточно места на диске"
  124.     exit 11
  125. fi
  126.  
  127. #добавляем +1, так как скрипт запустился и будет потенциальный бекап
  128. TOTAL_NUM_OF_BACKUPS=$(($(find "$BACKUP_PATH" -type f -name "*tar.gz" | wc -l)+1))
  129.  
  130. #Если число бекапов больше заданного, удаляем самый старый бекап
  131. if [[ $TOTAL_NUM_OF_BACKUPS -gt $BACKUP_COUNT ]]; then
  132.     log "[INFO] Удаляю самую старую резервную копию..."
  133.     OLDEST_BACKUP=$(find "$BACKUP_PATH" -maxdepth 1 -type f -name "*tar.gz" -printf "%T %p\n" | sort -n | head -1 | cut -d' ' -f2-)
  134.     rm "$OLDEST_BACKUP"
  135.     if [[ ! $? -eq 0 ]]; then
  136.       log "[ERROR] Не удалось удалить резервную копию"
  137.       exit 1
  138.     fi
  139. fi
  140.  
  141. log "[INFO] Создаю резервную копию..."
  142.  
  143. pg_dump -h "$DB_HOST" -U "$DB_USER" -d "$DB_BASE" -F t -v -f "$BACKUP_FILE" >> "$LOG_FILE" 2>&1
  144.  
  145. if [[ $? -ne 0 ]]; then
  146.   log "[ERROR] Возникла ошибка при создании резервной копии"
  147.   exit 1
  148. fi
  149.  
  150. gzip -9 $BACKUP_FILE
  151.  
  152. log "[INFO] Резервная копия успешно создана"
  153. log "[INFO] Завершение резервного копирования..."
Advertisement
Add Comment
Please, Sign In to add comment