Add postgres-backup.sh
This commit is contained in:
parent
f747843f5b
commit
e9d36aa261
348
postgres-backup.sh
Normal file
348
postgres-backup.sh
Normal file
@ -0,0 +1,348 @@
|
||||
#!/bin/bash
|
||||
# Script per il backup di database PostgreSQL
|
||||
# Autore: Mattia Tadini
|
||||
# Nome File: postgres-backup.sh
|
||||
# Revisione: 1.0
|
||||
|
||||
|
||||
# Prerequisiti
|
||||
|
||||
apt install ftp msmtp -y
|
||||
mkdir -p /$BACKUPDIR
|
||||
cat > /etc/msmtprc <<'EOF'
|
||||
# Configurazione msmtp - account predefinito
|
||||
defaults
|
||||
auth on
|
||||
tls on
|
||||
tls_trust_file /etc/ssl/certs/ca-certificates.crt
|
||||
host relay.poloinformatico.it
|
||||
port 587
|
||||
user brass@relay.poloinformatico.it
|
||||
from brass@relay.poloinformatico.it
|
||||
password DMKqP9vUYn8s
|
||||
logfile ~/.msmtp.log
|
||||
|
||||
# Impostiamo l'account predefinito
|
||||
account default
|
||||
|
||||
EOF
|
||||
|
||||
# Load configuration from external file
|
||||
CONFIG_FILE="/zucchetti/backupdb/psqlconfig.env"
|
||||
if [ -f "$CONFIG_FILE" ]; then
|
||||
source "$CONFIG_FILE"
|
||||
else
|
||||
echo "Configuration file not found: $CONFIG_FILE"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Default values for configuration (will be overridden by config.env if present)
|
||||
: ${BACKUP_DIR:="/zucchetti/backupdb/bkfiles"}
|
||||
: ${PGDUMP:="pg_dump"}
|
||||
: ${PSQL:="psql"}
|
||||
: ${HOST:="localhost"}
|
||||
: ${PORT:="5432"}
|
||||
: ${RETENTION:=1} # Retention per i backup locali
|
||||
: ${REMOTE_RETENTION:=2} # Retention per i backup remoti
|
||||
: ${SERVER_NAME:="PGDB01"} # Identificativo del server fisico
|
||||
: ${LOG_FILE:="/zucchetti/backupdb/backup_log.txt"}
|
||||
: ${ERROR_LOG_FILE:="/zucchetti/backupdb/backup_err.txt"}
|
||||
: ${REMOTE_DIR:="/BackupDB"}
|
||||
: ${DO_LOCAL_BACKUP:=1} # 1 per eseguire il backup locale, 0 per disabilitarlo
|
||||
: ${DO_FTP_BACKUP:=1} # 1 per eseguire il backup FTP, 0 per disabilitarlo
|
||||
: ${COMPRESSION_LEVEL:="9"} # Livello di compressione (1-9)
|
||||
|
||||
# Required variables check
|
||||
required_vars=(
|
||||
"USER" "PASSWORD" "FTP_SERVER" "FTP_USER" "FTP_PASSWORD"
|
||||
"SMTP_SERVER" "SMTP_USER" "SMTP_PASS" "DO_LOCAL_BACKUP" "DO_FTP_BACKUP"
|
||||
)
|
||||
|
||||
for var in "${required_vars[@]}"; do
|
||||
if [ -z "${!var}" ]; then
|
||||
echo "Error: Required variable $var is not set in config file"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
# Set date format
|
||||
DATE=$(LC_TIME=C date +%Y%m%d%H%M%S)
|
||||
|
||||
# Export PostgreSQL password
|
||||
export PGPASSWORD="$PASSWORD"
|
||||
|
||||
# Function to get all user databases
|
||||
get_all_databases() {
|
||||
$PSQL -h "$HOST" -p "$PORT" -U "$USER" -t -c "SELECT datname FROM pg_database WHERE datistemplate = false AND datname != 'postgres'" | grep -v "^$" | tr -d ' '
|
||||
}
|
||||
|
||||
# Function to check FTP connection
|
||||
check_ftp_connection() {
|
||||
# Skip if FTP backup is disabled
|
||||
if [ "$DO_FTP_BACKUP" -eq 0 ]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
local temp_file=$(mktemp)
|
||||
ftp -inv $FTP_SERVER > $temp_file 2>&1 <<EOF
|
||||
user $FTP_USER $FTP_PASSWORD
|
||||
quit
|
||||
EOF
|
||||
local connection_status=$?
|
||||
if grep -q "Connection refused\|Can't connect" $temp_file; then
|
||||
connection_status=1
|
||||
fi
|
||||
rm -f $temp_file
|
||||
return $connection_status
|
||||
}
|
||||
|
||||
# Function to perform FTP upload with retry mechanism
|
||||
perform_ftp_upload() {
|
||||
# Skip if FTP backup is disabled
|
||||
if [ "$DO_FTP_BACKUP" -eq 0 ]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
local source_file="$1"
|
||||
local dest_file="$2"
|
||||
local max_retries=3
|
||||
local retry_count=0
|
||||
local temp_file=$(mktemp)
|
||||
|
||||
while [ $retry_count -lt $max_retries ]; do
|
||||
ftp -inv $FTP_SERVER > $temp_file 2>&1 <<EOF
|
||||
user $FTP_USER $FTP_PASSWORD
|
||||
cd $REMOTE_DB_DIR
|
||||
put "$source_file" "$dest_file"
|
||||
bye
|
||||
EOF
|
||||
local upload_status=$?
|
||||
|
||||
if [ $upload_status -eq 0 ] && ! grep -q "Connection refused\|Can't connect\|failed\|error" $temp_file; then
|
||||
break
|
||||
fi
|
||||
|
||||
retry_count=$((retry_count + 1))
|
||||
echo "Upload attempt $retry_count failed, retrying in 5 seconds..." >> $LOG_FILE
|
||||
sleep 5
|
||||
done
|
||||
|
||||
cat $temp_file >> $LOG_FILE 2>> $ERROR_LOG_FILE
|
||||
rm -f $temp_file
|
||||
return $upload_status
|
||||
}
|
||||
|
||||
# Function to send email with msmtp
|
||||
send_email() {
|
||||
local db_name="$1"
|
||||
local status_message=""
|
||||
|
||||
# Costruisci il messaggio di stato dettagliato
|
||||
if [ "$DO_LOCAL_BACKUP" -eq 1 ]; then
|
||||
if [ $LOCAL_STATUS -eq 0 ]; then
|
||||
status_message="Local backup: SUCCESS\n"
|
||||
else
|
||||
status_message="Local backup: FAILED\n"
|
||||
fi
|
||||
else
|
||||
status_message="Local backup: DISABLED\n"
|
||||
fi
|
||||
|
||||
if [ "$DO_FTP_BACKUP" -eq 1 ]; then
|
||||
if [ $FTP_STATUS -eq 0 ]; then
|
||||
status_message+="FTP upload: SUCCESS\n"
|
||||
else
|
||||
status_message+="FTP upload: FAILED\n"
|
||||
fi
|
||||
else
|
||||
status_message+="FTP upload: DISABLED\n"
|
||||
fi
|
||||
|
||||
SUBJECT="Backup [${EMAIL_STATUS}] for $db_name on $SERVER_NAME - $(LC_TIME=C date)"
|
||||
MESSAGE="Backup process completed with following status:\n\n${status_message}\nDetailed log:\n\n$(cat $LOG_FILE)"
|
||||
|
||||
if [ -f "$ERROR_LOG_FILE" ] && [ -s "$ERROR_LOG_FILE" ]; then
|
||||
MESSAGE+="\n\nErrors encountered:\n\n$(cat $ERROR_LOG_FILE)"
|
||||
fi
|
||||
|
||||
echo -e "Subject: $SUBJECT\nFrom: $SMTP_USER\nTo: $SMTP_USER\n\n$MESSAGE" | \
|
||||
msmtp --debug --from="$SMTP_USER" -t
|
||||
}
|
||||
|
||||
# Function to perform backup for a single database
|
||||
perform_backup() {
|
||||
local db_name="$1"
|
||||
local LOCAL_STATUS=1
|
||||
local FTP_STATUS=1
|
||||
local EMAIL_STATUS=""
|
||||
|
||||
echo "Starting backup process for database: $db_name"
|
||||
|
||||
LOCAL_DB_DIR="$BACKUP_DIR/$db_name"
|
||||
REMOTE_DB_DIR="$REMOTE_DIR/$db_name"
|
||||
BACKUP_FILE="$LOCAL_DB_DIR/${db_name}_backup_$DATE.sql.gz"
|
||||
REMOTE_BACKUP_FILE="${db_name}_backup_$DATE.sql.gz"
|
||||
|
||||
# Create local backup directory if local backup is enabled
|
||||
if [ "$DO_LOCAL_BACKUP" -eq 1 ]; then
|
||||
mkdir -p "$LOCAL_DB_DIR"
|
||||
fi
|
||||
|
||||
# Create remote directory on FTP server if FTP backup is enabled
|
||||
if [ "$DO_FTP_BACKUP" -eq 1 ] && check_ftp_connection; then
|
||||
ftp -inv $FTP_SERVER <<EOF >> $LOG_FILE 2>> $ERROR_LOG_FILE
|
||||
user $FTP_USER $FTP_PASSWORD
|
||||
mkdir "$REMOTE_DB_DIR"
|
||||
bye
|
||||
EOF
|
||||
fi
|
||||
|
||||
# Start time for the backup
|
||||
START_TIME=$(date +%s)
|
||||
echo "$(LC_TIME=C date): Starting backup for database: $db_name on server $SERVER_NAME" > $LOG_FILE
|
||||
|
||||
# Perform local backup if enabled
|
||||
if [ "$DO_LOCAL_BACKUP" -eq 1 ]; then
|
||||
# Esegui il backup con pg_dump e comprimi direttamente
|
||||
$PGDUMP -h "$HOST" -p "$PORT" -U "$USER" -F c -Z $COMPRESSION_LEVEL "$db_name" > "$BACKUP_FILE" 2>> $ERROR_LOG_FILE
|
||||
|
||||
# Check if the local backup was successful
|
||||
if [ $? -eq 0 ] && [ -f "$BACKUP_FILE" ]; then
|
||||
LOCAL_STATUS=0
|
||||
echo "$(LC_TIME=C date): Local backup completed successfully for $db_name." >> $LOG_FILE
|
||||
else
|
||||
LOCAL_STATUS=1
|
||||
echo "$(LC_TIME=C date): Error during local backup of $db_name. Check error log." >> $LOG_FILE
|
||||
fi
|
||||
else
|
||||
LOCAL_STATUS=0
|
||||
echo "$(LC_TIME=C date): Local backup disabled for $db_name." >> $LOG_FILE
|
||||
fi
|
||||
|
||||
# End time and duration
|
||||
END_TIME=$(date +%s)
|
||||
DURATION=$((END_TIME - START_TIME))
|
||||
echo "$(LC_TIME=C date): Backup ended for $db_name." >> $LOG_FILE
|
||||
echo "Start time: $(LC_TIME=C date -d @$START_TIME)" >> $LOG_FILE
|
||||
echo "End time: $(LC_TIME=C date -d @$END_TIME)" >> $LOG_FILE
|
||||
echo "Duration: $((DURATION / 60)) minutes and $((DURATION % 60)) seconds" >> $LOG_FILE
|
||||
|
||||
# Upload backup to remote FTP server if enabled and local backup was successful
|
||||
if [ "$DO_FTP_BACKUP" -eq 1 ]; then
|
||||
if [ "$DO_LOCAL_BACKUP" -eq 0 ] || [ $LOCAL_STATUS -eq 0 ]; then
|
||||
echo "$(LC_TIME=C date): Starting FTP upload for $db_name." >> $LOG_FILE
|
||||
|
||||
if ! check_ftp_connection; then
|
||||
FTP_STATUS=1
|
||||
echo "$(LC_TIME=C date): Cannot establish FTP connection. Upload failed." >> $LOG_FILE
|
||||
echo "FTP connection failed - Cannot connect to server" >> $ERROR_LOG_FILE
|
||||
else
|
||||
if perform_ftp_upload "$BACKUP_FILE" "$REMOTE_BACKUP_FILE"; then
|
||||
FTP_STATUS=0
|
||||
echo "$(LC_TIME=C date): FTP upload completed successfully for $db_name." >> $LOG_FILE
|
||||
else
|
||||
FTP_STATUS=1
|
||||
echo "$(LC_TIME=C date): Error during FTP upload for $db_name. Check error log." >> $LOG_FILE
|
||||
fi
|
||||
fi
|
||||
else
|
||||
echo "$(LC_TIME=C date): Skipping FTP upload due to local backup failure." >> $LOG_FILE
|
||||
FTP_STATUS=1
|
||||
fi
|
||||
else
|
||||
FTP_STATUS=0
|
||||
echo "$(LC_TIME=C date): FTP upload disabled for $db_name." >> $LOG_FILE
|
||||
fi
|
||||
|
||||
# Local retention policy if local backup is enabled
|
||||
if [ "$DO_LOCAL_BACKUP" -eq 1 ] && [ $LOCAL_STATUS -eq 0 ]; then
|
||||
find "$LOCAL_DB_DIR" -name "${db_name}_backup_*.sql.gz" -type f -mtime +$RETENTION -delete >> $LOG_FILE 2>> $ERROR_LOG_FILE
|
||||
fi
|
||||
|
||||
# Remote retention policy if FTP backup is enabled
|
||||
if [ "$DO_FTP_BACKUP" -eq 1 ] && [ $FTP_STATUS -eq 0 ]; then
|
||||
echo "$(LC_TIME=C date): Performing remote retention check." >> $LOG_FILE
|
||||
|
||||
temp_list_file=$(mktemp)
|
||||
ftp -inv $FTP_SERVER > $temp_list_file 2>> $ERROR_LOG_FILE <<EOF
|
||||
user $FTP_USER $FTP_PASSWORD
|
||||
cd $REMOTE_DB_DIR
|
||||
ls
|
||||
bye
|
||||
EOF
|
||||
|
||||
grep -E -o '\S+_backup_[0-9]{14}\.sql\.gz' $temp_list_file | while read -r file; do
|
||||
if [[ "$file" =~ ^$db_name ]]; then
|
||||
file_date=$(echo "$file" | sed -n 's/.*_backup_\([0-9]\{14\}\)\.sql\.gz/\1/p')
|
||||
|
||||
if [ -n "$file_date" ]; then
|
||||
echo "$(LC_TIME=C date): Data estratta dal file remoto $file: $file_date" >> $LOG_FILE
|
||||
retention_date=$(LC_TIME=C date -d "-$REMOTE_RETENTION days" +%Y%m%d%H%M%S)
|
||||
|
||||
if [ "$file_date" -lt "$retention_date" ]; then
|
||||
ftp -inv $FTP_SERVER <<EOF >> $LOG_FILE 2>> $ERROR_LOG_FILE
|
||||
user $FTP_USER $FTP_PASSWORD
|
||||
cd $REMOTE_DB_DIR
|
||||
delete "$file"
|
||||
bye
|
||||
EOF
|
||||
echo "$(LC_TIME=C date): File remoto $file eliminato perché più vecchio di $REMOTE_RETENTION giorni." >> $LOG_FILE
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
done
|
||||
rm -f $temp_list_file
|
||||
fi
|
||||
|
||||
# Determine email status based on enabled backups
|
||||
if [ "$DO_LOCAL_BACKUP" -eq 1 ] && [ "$DO_FTP_BACKUP" -eq 1 ]; then
|
||||
if [ $LOCAL_STATUS -eq 0 ] && [ $FTP_STATUS -eq 0 ]; then
|
||||
EMAIL_STATUS="SUCCESS"
|
||||
elif [ $LOCAL_STATUS -eq 1 ] && [ $FTP_STATUS -eq 1 ]; then
|
||||
EMAIL_STATUS="FAILED"
|
||||
else
|
||||
EMAIL_STATUS="WARNING"
|
||||
fi
|
||||
elif [ "$DO_LOCAL_BACKUP" -eq 1 ]; then
|
||||
if [ $LOCAL_STATUS -eq 0 ]; then
|
||||
EMAIL_STATUS="SUCCESS"
|
||||
else
|
||||
EMAIL_STATUS="FAILED"
|
||||
fi
|
||||
elif [ "$DO_FTP_BACKUP" -eq 1 ]; then
|
||||
if [ $FTP_STATUS -eq 0 ]; then
|
||||
EMAIL_STATUS="SUCCESS"
|
||||
else
|
||||
EMAIL_STATUS="FAILED"
|
||||
fi
|
||||
else
|
||||
EMAIL_STATUS="DISABLED"
|
||||
fi
|
||||
|
||||
# Send email with log
|
||||
send_email "$db_name"
|
||||
|
||||
# Cleanup
|
||||
rm -f $LOG_FILE
|
||||
[ -f "$ERROR_LOG_FILE" ] && [ ! -s "$ERROR_LOG_FILE" ] && rm -f "$ERROR_LOG_FILE"
|
||||
|
||||
echo "Backup process complete for $db_name with status: $EMAIL_STATUS (Local: $LOCAL_STATUS, FTP: $FTP_STATUS)"
|
||||
return $(( LOCAL_STATUS | FTP_STATUS ))
|
||||
}
|
||||
|
||||
# Main script logic
|
||||
if [ -z "$1" ]; then
|
||||
echo "No database specified, backing up all databases..."
|
||||
OVERALL_STATUS=0
|
||||
|
||||
for db in $(get_all_databases); do
|
||||
perform_backup "$db"
|
||||
BACKUP_STATUS=$?
|
||||
[ $BACKUP_STATUS -ne 0 ] && OVERALL_STATUS=1
|
||||
done
|
||||
|
||||
exit $OVERALL_STATUS
|
||||
else
|
||||
perform_backup "$1"
|
||||
exit $?
|
||||
fi
|
||||
Loading…
Reference in New Issue
Block a user