Last active
April 15, 2025 14:58
-
-
Save phaneesh/703f49b36f721b8da007f123c06c89fa to your computer and use it in GitHub Desktop.
PostgreSql Daily Backup & Restore
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# | |
# PostgreSQL Daily Backup Script | |
# This script creates daily backups of PostgreSQL databases with rotation | |
# | |
# Configuration variables | |
BACKUP_DIR="/var/backups/postgresql" | |
DB_USER="postgres" | |
DB_PASSWORD="" # For security, consider using a .pgpass file instead | |
DB_HOST="localhost" | |
DB_PORT="5432" | |
DAYS_TO_KEEP=7 | |
DATE_FORMAT=$(date +"%Y-%m-%d") | |
LOG_FILE="${BACKUP_DIR}/backup_log_${DATE_FORMAT}.log" | |
# Create backup directory if it doesn't exist | |
mkdir -p "$BACKUP_DIR" | |
# Initialize log file | |
echo "===== PostgreSQL Backup Started at $(date) =====" > "$LOG_FILE" | |
# Function to log messages | |
log_message() { | |
echo "$(date +"%Y-%m-%d %H:%M:%S") - $1" >> "$LOG_FILE" | |
echo "$1" | |
} | |
# Function to handle errors | |
handle_error() { | |
log_message "ERROR: $1" | |
exit 1 | |
} | |
# Check if pg_dump is available | |
if ! command -v pg_dump &> /dev/null; then | |
handle_error "pg_dump command not found. Please install PostgreSQL client tools." | |
fi | |
# Backup all databases | |
backup_all_databases() { | |
log_message "Starting backup of all databases..." | |
# Get list of databases, excluding template databases | |
DB_LIST=$(PGPASSWORD="$DB_PASSWORD" psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -t -c "SELECT datname FROM pg_database WHERE datname NOT IN ('template0', 'template1') AND datname NOT LIKE 'pg_%';" 2>> "$LOG_FILE") | |
if [ $? -ne 0 ]; then | |
handle_error "Failed to get database list" | |
fi | |
# Backup each database | |
for DB_NAME in $DB_LIST; do | |
backup_single_database "$DB_NAME" | |
done | |
log_message "All database backups completed!" | |
} | |
# Backup a single database | |
backup_single_database() { | |
DB_NAME="$1" | |
BACKUP_FILE="${BACKUP_DIR}/${DB_NAME}_${DATE_FORMAT}.sql.gz" | |
log_message "Backing up database: $DB_NAME to $BACKUP_FILE" | |
PGPASSWORD="$DB_PASSWORD" pg_dump -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" \ | |
-F p -b -v -f - "$DB_NAME" 2>> "$LOG_FILE" | gzip > "$BACKUP_FILE" | |
if [ $? -ne 0 ]; then | |
log_message "Warning: There might have been a problem with the backup of $DB_NAME. Check the log for details." | |
else | |
log_message "Successfully backed up database: $DB_NAME" | |
# Set appropriate permissions for backup file | |
chmod 600 "$BACKUP_FILE" | |
fi | |
} | |
# Delete old backups | |
rotate_backups() { | |
log_message "Removing backups older than $DAYS_TO_KEEP days..." | |
find "$BACKUP_DIR" -name "*.sql.gz" -type f -mtime +$DAYS_TO_KEEP -delete | |
find "$BACKUP_DIR" -name "backup_log_*.log" -type f -mtime +$DAYS_TO_KEEP -delete | |
log_message "Old backups removed!" | |
} | |
# Main execution | |
log_message "Starting PostgreSQL backup process..." | |
# Execute backups | |
backup_all_databases | |
# Rotate old backups | |
rotate_backups | |
log_message "Backup process completed successfully!" | |
echo "===== PostgreSQL Backup Completed at $(date) =====" >> "$LOG_FILE" | |
exit 0 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# | |
# PostgreSQL Backup Restore Script | |
# This script restores PostgreSQL databases from backups created by the backup script | |
# | |
# Configuration variables | |
BACKUP_DIR="/var/backups/postgresql" | |
DB_USER="postgres" | |
DB_PASSWORD="" # For security, consider using a .pgpass file instead | |
DB_HOST="localhost" | |
DB_PORT="5432" | |
LOG_FILE="${BACKUP_DIR}/restore_log_$(date +"%Y-%m-%d_%H-%M-%S").log" | |
# Create log directory if it doesn't exist | |
mkdir -p "$BACKUP_DIR" | |
# Initialize log file | |
echo "===== PostgreSQL Restore Started at $(date) =====" > "$LOG_FILE" | |
# Function to log messages | |
log_message() { | |
echo "$(date +"%Y-%m-%d %H:%M:%S") - $1" >> "$LOG_FILE" | |
echo "$1" | |
} | |
# Function to handle errors | |
handle_error() { | |
log_message "ERROR: $1" | |
exit 1 | |
} | |
# Check if psql is available | |
if ! command -v psql &> /dev/null; then | |
handle_error "psql command not found. Please install PostgreSQL client tools." | |
fi | |
# Display available backups | |
list_backups() { | |
echo "Available database backups:" | |
ls -lt "$BACKUP_DIR" | grep ".sql.gz" | awk '{print NR". "$9}' | |
} | |
# Restore a database from backup | |
restore_database() { | |
BACKUP_FILE="$1" | |
DB_NAME="$2" | |
# Check if backup file exists | |
if [ ! -f "$BACKUP_FILE" ]; then | |
handle_error "Backup file does not exist: $BACKUP_FILE" | |
fi | |
# Check if database exists | |
DB_EXISTS=$(PGPASSWORD="$DB_PASSWORD" psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -t -c "SELECT 1 FROM pg_database WHERE datname='$DB_NAME';" 2>> "$LOG_FILE") | |
if [ "$DB_EXISTS" = " 1" ]; then | |
read -p "Database $DB_NAME already exists. Do you want to drop and recreate it? (y/n): " CONFIRM | |
if [[ "$CONFIRM" =~ ^[Yy]$ ]]; then | |
log_message "Dropping existing database: $DB_NAME" | |
PGPASSWORD="$DB_PASSWORD" psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -c "DROP DATABASE \"$DB_NAME\";" 2>> "$LOG_FILE" | |
if [ $? -ne 0 ]; then | |
handle_error "Failed to drop database $DB_NAME" | |
fi | |
else | |
log_message "Restore cancelled by user." | |
exit 0 | |
fi | |
fi | |
# Create database | |
log_message "Creating database: $DB_NAME" | |
PGPASSWORD="$DB_PASSWORD" psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -c "CREATE DATABASE \"$DB_NAME\";" 2>> "$LOG_FILE" | |
if [ $? -ne 0 ]; then | |
handle_error "Failed to create database $DB_NAME" | |
fi | |
# Restore from backup | |
log_message "Restoring $DB_NAME from $BACKUP_FILE..." | |
gunzip -c "$BACKUP_FILE" | PGPASSWORD="$DB_PASSWORD" psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d "$DB_NAME" 2>> "$LOG_FILE" | |
if [ $? -ne 0 ]; then | |
log_message "Warning: There might have been a problem with the restore of $DB_NAME. Check the log for details." | |
else | |
log_message "Successfully restored database: $DB_NAME from $BACKUP_FILE" | |
fi | |
} | |
# Interactive mode - let user choose which backup to restore | |
interactive_restore() { | |
# List available backups | |
list_backups | |
# Ask user to select a backup | |
read -p "Enter the number of the backup to restore: " BACKUP_NUM | |
# Get the selected backup file | |
BACKUP_FILE=$(ls -t "$BACKUP_DIR"/*.sql.gz | sed -n "${BACKUP_NUM}p") | |
if [ -z "$BACKUP_FILE" ]; then | |
handle_error "Invalid backup number" | |
fi | |
# Extract database name from backup file | |
DB_NAME=$(basename "$BACKUP_FILE" | sed 's/\(.*\)_[0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}\.sql\.gz/\1/') | |
echo "Selected backup file: $BACKUP_FILE" | |
echo "Database name: $DB_NAME" | |
# Confirm restoration | |
read -p "Do you want to restore this database? (y/n): " CONFIRM | |
if [[ "$CONFIRM" =~ ^[Yy]$ ]]; then | |
restore_database "$BACKUP_FILE" "$DB_NAME" | |
else | |
log_message "Restore cancelled by user." | |
fi | |
} | |
# Specific restore - restore a specific backup file for a specific database | |
specific_restore() { | |
if [ -z "$1" ] || [ -z "$2" ]; then | |
echo "Usage: $0 -s <backup_file> <database_name>" | |
exit 1 | |
fi | |
BACKUP_FILE="$1" | |
DB_NAME="$2" | |
# Check if backup file exists | |
if [ ! -f "$BACKUP_FILE" ]; then | |
# Try adding the backup directory | |
BACKUP_FILE="$BACKUP_DIR/$BACKUP_FILE" | |
if [ ! -f "$BACKUP_FILE" ]; then | |
handle_error "Backup file does not exist: $1" | |
fi | |
fi | |
restore_database "$BACKUP_FILE" "$DB_NAME" | |
} | |
# Latest restore - restore the latest backup of a database | |
latest_restore() { | |
if [ -z "$1" ]; then | |
echo "Usage: $0 -l <database_name>" | |
exit 1 | |
fi | |
DB_NAME="$1" | |
LATEST_BACKUP=$(ls -t "$BACKUP_DIR"/${DB_NAME}_*.sql.gz 2>/dev/null | head -n1) | |
if [ -z "$LATEST_BACKUP" ]; then | |
handle_error "No backup found for database $DB_NAME" | |
fi | |
echo "Latest backup found: $LATEST_BACKUP" | |
read -p "Do you want to restore this database? (y/n): " CONFIRM | |
if [[ "$CONFIRM" =~ ^[Yy]$ ]]; then | |
restore_database "$LATEST_BACKUP" "$DB_NAME" | |
else | |
log_message "Restore cancelled by user." | |
fi | |
} | |
# Main execution | |
case "$1" in | |
-i|--interactive) | |
interactive_restore | |
;; | |
-s|--specific) | |
specific_restore "$2" "$3" | |
;; | |
-l|--latest) | |
latest_restore "$2" | |
;; | |
*) | |
echo "PostgreSQL Backup Restore Script" | |
echo "Usage:" | |
echo " $0 -i, --interactive : Interactive mode, select backup from a list" | |
echo " $0 -s, --specific <file> <db> : Restore specific backup file to database" | |
echo " $0 -l, --latest <db> : Restore the latest backup of a database" | |
exit 1 | |
;; | |
esac | |
log_message "Restore process completed!" | |
echo "===== PostgreSQL Restore Completed at $(date) =====" >> "$LOG_FILE" | |
exit 0 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment