Мои сайты
Частые вопросы
Полезные ссылки
Операционные системы
Программное обеспечение
Оборудование
СУБД
Кулинария
Предыдущая версия скрипта расположена тут: Скрипт архивирования всех баз postgresql на linux
Исходный скрипт решал задачу, но был уязвим в нескольких местах.
Вот что было улучшено по категориям:
| Было | Стало | Зачем |
| `rm -f $BackupDir/$dbname.sql.gz` перед созданием | Запись в `.tmp` + `mv` | Если бэкап упадёт, старый архив не будет потерян |
| Нет проверки результата `pg_dump` | `if pg_dump …; then … else … fi` | Ошибки фиксируются, битые файлы удаляются |
| Нет ротации | `find … -mtime +7 -delete` | Диск не переполнится старыми архивами Ротация (закомментирована, включается при необходимости) |
| Было | Стало | Зачем |
| `$BackupDir/$dbname.sql.gz` без кавычек | `«$BackupDir/${dbname}.dump»` | Защита от имён с пробелами |
| Парсинг через `tail|head|egrep` | SQL-фильтр `WHERE datistemplate = false` | Не зависит от формата вывода `psql` |
| Было | Стало | Зачем |
| Бэкап всех БД кроме шаблонов | Список из файла `/opt/scripts/pg_backup_list.lst` | Можно бэкапить только нужные БД, игнорировать комментарии |
| Plain SQL + `gzip` | Кастомный формат `-Fc -Z 6` | Быстрее, компактнее, можно восстанавливать отдельные таблицы |
| Нет отчёта | Счётчики `total/success/failed` | Видно результат выполнения |
| Код возврата всегда 0 | `exit 1` при ошибках | Мониторинг (Zabbix, Prometheus) замечает сбои |
| Было | Стало | Зачем |
| `echo «Архив создан»` | `log()` с временными метками в файл и консоль | Есть история в `/var/log/pg_backup.log` |
| Нет обработки peer-ошибок | `-h localhost` в командах | Работает из-под любого пользователя ОС |
| Нет создания директории | `mkdir -p «$BackupDir»` | Скрипт не падает, если папка ещё не создана |
| Нет проверки списка БД | Проверка существования `LIST_FILE` | Ясная ошибка вместо молчаливого провала |
Было: pg_dump | gzip → .sql.gz
Стало: pg_dump -Fc -Z 6 → .dump
Это даёт:
Было: Автоматический, все БД кроме шаблонов
Стало: Управляемый файл /opt/scripts/pg_backup_list.lst с комментариями
Создайте файл со списком баз для бэкапа: /opt/scripts/pg_backup_list.lst
# Список баз для бэкапа my_db1 my_db2 # analytics - временно отключена
#!/bin/bash # === Настройки === PATH=/etc:/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin BackupDir="/mnt/backups/pgsql" LIST_FILE="/opt/scripts/pg_backup_list.lst" LOG_FILE="/var/log/pg_backup.log" # Уровень сжатия кастомного формата (0-9, по умолчанию 6) DUMP_COMPRESSION=6 # === Функции === log() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE" } # === Проверки === mkdir -p "$BackupDir" || { log "ОШИБКА: не удалось создать $BackupDir"; exit 1; } if [ ! -f "$LIST_FILE" ]; then log "ОШИБКА: файл со списком баз $LIST_FILE не найден." exit 1 fi # === Аутентификация === # Рекомендуется использовать ~/.pgpass вместо PGPASSWORD export PGPASSWORD="123456" log "=== Начало процесса бэкапа ===" # === Счётчики для отчёта === total=0 success=0 failed=0 # === Основной цикл === while IFS= read -r dbname || [ -n "$dbname" ]; do # Убираем пробелы по краям dbname="$(echo "$dbname" | xargs)" # Пропускаем пустые строки и комментарии [[ -z "$dbname" || "$dbname" =~ ^[[:space:]]*# ]] && continue total=$((total + 1)) log "[$total] Обработка базы: $dbname" temp_file="$BackupDir/${dbname}.dump.tmp" final_file="$BackupDir/${dbname}.dump" # -Fc — кастомный формат (сжатый, бинарный) # -Z — уровень сжатия (0-9) if pg_dump -h localhost -U postgres -Fc -Z "$DUMP_COMPRESSION" "$dbname" > "$temp_file"; then mv "$temp_file" "$final_file" log "Успешно создан архив: $final_file" success=$((success + 1)) else log "ОШИБКА при создании архива $dbname! Старый бэкап сохранен." rm -f "$temp_file" failed=$((failed + 1)) fi done < "$LIST_FILE" # === Ротация: удаляем бэкапы старше 7 дней === # Закомментирована #find "$BackupDir" -name "*.dump" -type f -mtime +7 -delete #log "Ротация завершена: удалены файлы старше 7 дней." # === Итог === unset PGPASSWORD log "=== Завершение: всего=$total успешно=$success ошибок=$failed ===" if [ "$failed" -gt 0 ]; then exit 1 fi