diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..58322a0 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +*/.env.dist \ No newline at end of file diff --git a/README.md b/README.md index ac502d4..af66fec 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,13 @@ # scripts -Random scripts for different tasks \ No newline at end of file +Random scripts for different tasks + +## Configuration + +If the script provides any configuration, make a copy of `.env.dist` file to `.env` and edit configuration there. + +```shell +cd some_script +cp .env.dist .env +nano .env +``` \ No newline at end of file diff --git a/postgresql_backup/.env.dist b/postgresql_backup/.env.dist new file mode 100644 index 0000000..1d170f8 --- /dev/null +++ b/postgresql_backup/.env.dist @@ -0,0 +1,22 @@ +# Backup path +BACKUP_PATH="/path/to/backup/directory" + +# Compression levels +ZSTD_LEVEL=5 +GZIP_LEVEL=7 + +# Servers configuration +# Add as many as needed + +# Database 1 configuration +DB1_HOST="localhost" +DB1_PORT="5432" +DB1_USER="user1" +# "custom" for .dump or "sql" for SQL compressed with Gzip +DB1_DUMP_FORMAT="custom" + +# Database 2 configuration +#DB2_HOST="remote_host" +#DB2_PORT="5432" +#DB2_USER="user2" +#DB2_DUMP_FORMAT="sql" diff --git a/postgresql_backup/README.md b/postgresql_backup/README.md new file mode 100644 index 0000000..72d4e66 --- /dev/null +++ b/postgresql_backup/README.md @@ -0,0 +1,57 @@ +# Usage + +## Authentication + +Do not forget to create and/or edit `~/.pgpass` file providing all needed passwords for each host: + +The format is the following: +```properties +hostname:port:database:username:password +``` + +Example + +```properties +localhost:5432:*:postgres:pg_password_1 +localhost:5433:*:postgres:pg_password_2 +``` + +## Scheduling + +### Systemd + +#### Service + +`/etc/systemd/system/postgresql_backup.service` + +```ini +[Unit] +Description=PostgreSQL backup Script + +[Service] +Type=oneshot +WorkingDirectory=/root/scripts/postgresql_backup +ExecStart=/root/scripts/postgresql_backup/pg_backup.sh +``` + +#### Timer + +`/etc/systemd/system/postgresql_backup.timer` + +```ini +[Unit] +Description=Run Backup Script Every Night + +[Timer] +OnCalendar=*-*-* 22:00:00 +Unit=postgresql_backup.service + +[Install] +WantedBy=timers.target +``` + +Then: + +```shell +systemctl enable postgresql_backup.timer --now +``` \ No newline at end of file diff --git a/postgresql_backup/pg_backup.sh b/postgresql_backup/pg_backup.sh index e77646c..8c2e6d7 100644 --- a/postgresql_backup/pg_backup.sh +++ b/postgresql_backup/pg_backup.sh @@ -1,38 +1,77 @@ #!/bin/bash -# Configuration -HOST="localhost" -PORT="5432" -USER="your_postgres_user" -BACKUP_PATH="/path/to/backup/directory" -DUMP_FORMAT="custom" # Set to "custom" for .dump or "sql" for plaintext SQL -EXTENSION="dump" # Default extension - -# Adjust file extension based on dump format -if [[ "$DUMP_FORMAT" == "sql" ]]; then - EXTENSION="sql.gz" +# Load environment variables from .env file +if [ -f .env ]; then + export $(grep -v '^#' .env | xargs) +else + echo ".env file not found! Please create it with the necessary configuration." + exit 1 fi -# Create backup directory if it doesn't exist -mkdir -p "$BACKUP_PATH" +# Ensure BACKUP_PATH is set +if [ -z "$BACKUP_PATH" ]; then + echo "BACKUP_PATH not set in .env file!" + exit 1 +fi -# Get a list of all databases, excluding template databases -DATABASES=$(psql -h "$HOST" -p "$PORT" -U "$USER" -d postgres -t -c "SELECT datname FROM pg_database WHERE datistemplate = false;") +# Extract unique database prefixes (DB1, DB2, ...) +DATABASE_PREFIXES=$(env | grep -o 'DB[0-9]*_' | sort -u) -# Loop over each database and create a backup -for DB in $DATABASES; do - BACKUP_FILE="$BACKUP_PATH/$DB.$EXTENSION" - - if [[ "$DUMP_FORMAT" == "custom" ]]; then - # Create a compressed custom-format backup - pg_dump -h "$HOST" -p "$PORT" -U "$USER" -Fc "$DB" -f "$BACKUP_FILE" - elif [[ "$DUMP_FORMAT" == "sql" ]]; then - # Create a plain-text SQL backup and compress it with gzip - pg_dump -h "$HOST" -p "$PORT" -U "$USER" "$DB" | gzip > "$BACKUP_FILE" - else - echo "Invalid DUMP_FORMAT specified: $DUMP_FORMAT" - exit 1 +# Loop through each database configuration prefix +for PREFIX in $DATABASE_PREFIXES; do + HOST_VAR="${PREFIX}HOST" + PORT_VAR="${PREFIX}PORT" + USER_VAR="${PREFIX}USER" + FORMAT_VAR="${PREFIX}DUMP_FORMAT" + + HOST=${!HOST_VAR} + PORT=${!PORT_VAR} + USER=${!USER_VAR} + DUMP_FORMAT=${!FORMAT_VAR:-"custom"} # Default to "custom" if not set + + if [ -z "$HOST" ] || [ -z "$PORT" ] || [ -z "$USER" ]; then + echo "Incomplete configuration for $PREFIX. Skipping..." + continue fi - echo "Backup for database '$DB' created at '$BACKUP_FILE'" -done \ No newline at end of file + # Create a directory for each server using host and port, only if it doesn't exist + SERVER_DIR="$BACKUP_PATH/${HOST}_${PORT}" + if [ ! -d "$SERVER_DIR" ]; then + echo "Creating backup directory: $SERVER_DIR" + mkdir -p "$SERVER_DIR" + else + echo "Backup directory $SERVER_DIR already exists, skipping creation." + fi + + # Get a list of all databases for this server, excluding template databases + echo "Fetching databases for $HOST:$PORT ..." + DATABASES=$(psql -h "$HOST" -p "$PORT" -U "$USER" -d postgres -t -c "SELECT datname FROM pg_database WHERE datistemplate = false;") + + # Loop over each database and create a backup + for DB_NAME in $DATABASES; do + # Set file extension based on DUMP_FORMAT + EXTENSION="dump" + if [[ "$DUMP_FORMAT" == "sql" ]]; then + EXTENSION="sql.gz" + fi + + # Set backup file path within the server-specific directory + BACKUP_FILE="$SERVER_DIR/$DB_NAME.$EXTENSION" + + echo "Dumping '$DB_NAME' on $HOST:$PORT to $BACKUP_FILE" + + # Perform the backup based on the specified format + if [[ "$DUMP_FORMAT" == "custom" ]]; then + pg_dump -h "$HOST" -p "$PORT" -U "$USER" -Fc --compress="zstd:$ZSTD_LEVEL" "$DB_NAME" -f "$BACKUP_FILE" + elif [[ "$DUMP_FORMAT" == "sql" ]]; then + pg_dump -h "$HOST" -p "$PORT" -U "$USER" "$DB_NAME" | gzip -$GZIP_LEVEL > "$BACKUP_FILE" + else + echo "Invalid DUMP_FORMAT for $PREFIX: $DUMP_FORMAT. Skipping..." + continue + fi + + du -sh $BACKUP_FILE + done +done + +echo "Backup process completed."