Home / Clayi CodeScripts / Scripts / Automated MySQL & PostgreSQL Server Backup Script in Python

Automated MySQL & PostgreSQL Server Backup Script in Python

Automated MySQL & PostgreSQL Server Backup Script in Python
  • Category Scripts
  • Type PY
  • Platform Cross-platform
  • Language Python
  • Price Free
  • Views 1 308
  • Comments 0
View Resource
Automated MySQL & PostgreSQL Server Backup Script in Python

The Importance of Automated Database and File Backups

Maintaining a production server without a rigorous backup strategy is a recipe for absolute disaster. Hardware fails, databases become corrupted, and human errors frequently result in accidental data deletion. While enterprise backup solutions can be incredibly expensive and complex, developers can build their own robust systems using native scripting languages. Understanding how to deploy an "Automated MySQL & PostgreSQL Server Backup Script in Python" empowers system administrators to secure their vital databases and web directories reliably, automatically, and at zero cost.

Configuring Target Databases and System Retention Policies

The foundation of this Python backup script is its highly modular configuration block. Rather than hardcoding complex SQL dump commands directly into the logic, the script utilizes a clean Python dictionary list named DATABASES. This intelligent design allows developers to easily declare multiple MySQL and PostgreSQL targets simultaneously. Additionally, the RETENTION_DAYS = 7 variable sets a strict data retention policy, ensuring the server doesn't eventually run out of disk space by keeping months of obsolete archive files.

Safely Executing MySQL Dumps Using Python Subprocess

Interacting with terminal commands directly from Python requires precision and security. The script elegantly uses the subprocess.Popen module to execute the native mysqldump utility. A critical security feature implemented here is the handling of passwords. Instead of passing the database password via the command-line arguments (which exposes it to anyone running the ps aux command), the script securely injects the password directly into a cloned environment variable via env["MYSQL_PWD"], keeping your credentials completely hidden from system logs.

Backing Up PostgreSQL Databases Without Shell Injection Risks

PostgreSQL databases require a slightly different approach, utilizing the pg_dump utility. Just like the MySQL function, the PostgreSQL backup method avoids dangerous shell injections by passing arguments as a secure Python list rather than a single interpolated string. Furthermore, it utilizes the PGPASSWORD environment variable to authenticate. The script also includes a brilliant validation mechanism: it explicitly waits for the subprocess to finish using p1_status = p1.wait(), instantly raising an error and deleting corrupted, half-written files if the database dump unexpectedly fails.

Compressing Large Data Streams Instantly with Gzip Piping

Raw SQL database dumps are massive text files that can easily consume hundreds of gigabytes of disk space. To solve this, the script employs advanced Unix pipeline mechanics natively within Python. By linking the standard output (stdout) of the database dump directly into the standard input (stdin) of the gzip utility, the script compresses the data stream on the fly. This means the raw SQL data never touches the hard drive; it is compressed instantly in memory and written straight to the disk as a highly efficient, space-saving .sql.gz archive.

Archiving Critical Server Directories with the Shutil Module

Databases only tell half the story; a complete server backup must also include static assets like user uploads, PDF documents, and crucial Nginx configuration files. The script handles folder archiving using Python's built-in shutil.make_archive library. This high-level function bypasses the need to write complex Unix tar commands manually. By wrapping this operation in a robust try-except block, the script guarantees that if it encounters a "permission denied" error on a specific file, it will gracefully log the error and continue backing up the rest of the server rather than crashing fatally.

Implementing a Self-Cleaning Backup Rotation Strategy

A backup script that runs indefinitely will eventually fill up your hard drive, causing a catastrophic server outage. The clean_old_backups() function is a mandatory feature for production environments. By calculating a precise Unix timestamp cutoff (current time minus retention days), the script meticulously scans the BACKUP_DIR. Any archive file possessing a modified date older than the strict 7-day cutoff is automatically and permanently deleted via os.remove(), ensuring your server always maintains a healthy, self-regulating storage capacity without any human intervention.

Download the Complete Python Backup Automation Script

Building a robust automation script that properly handles environment variables, Unix piping, error catching, and file rotation takes hours of meticulous testing. To save you massive amounts of development time, you can instantly download this complete, fully audited Python backup automation script directly from this page. By placing this script on your Linux server and scheduling it via a daily Cron job, you can sleep peacefully knowing your MySQL data, PostgreSQL databases, and vital system files are securely backed up, perfectly compressed, and properly organized.

Popularity
0%
  • Votes: 9
  • Comments: 0

Help

Can't download assets? How to use Clayi Assets Assets not working? Can't copy? How to use Clayi Code Snippet not working?

Free Automated MySQL & PostgreSQL Server Backup Script in Python PY Download

#!/usr/bin/env python3
"""
===============================================================================
Clayi Assets - Open Source Automation Scripts
Title: Automated Database & Directory Backup Tool with Cloud Upload
Language: Python 3.8+
License: MIT License
Description:
Production-grade backup automation script for MySQL, PostgreSQL, and 
critical server directories. Compresses backups into timestamped Gzip 
archives and handles automated rotation (retention policy).
===============================================================================
"""

import os
import sys
import time
import shutil
import subprocess
from datetime import datetime

# Backup Configuration
BACKUP_DIR = "/var/backups/clayi"
RETENTION_DAYS = 7
TIMESTAMP = datetime.now().strftime("%Y%m%d_%H%M%S")

# Target Databases & Directories
DATABASES = [
    {"type": "mysql", "name": "app_production", "user": "root", "password": "SECURE_PASSWORD"},
    {"type": "postgres", "name": "analytics_db", "user": "postgres", "password": "SECURE_PASSWORD"}
]

FOLDERS_TO_BACKUP = [
    "/var/www/html/uploads",
    "/etc/nginx/conf.d"
]

def log(msg: str):
    print(f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] {msg}")

def ensure_backup_dir():
    if not os.path.exists(BACKUP_DIR):
        os.makedirs(BACKUP_DIR, exist_ok=True)
        log(f"Created backup directory: {BACKUP_DIR}")

def backup_mysql(db: dict):
    output_file = os.path.join(BACKUP_DIR, f"mysql_{db['name']}_{TIMESTAMP}.sql.gz")
    log(f"Starting MySQL backup for: {db['name']}...")
    
    env = os.environ.copy()
    env["MYSQL_PWD"] = db["password"]
    
    try:
        with open(output_file, "wb") as f_out:
            p1 = subprocess.Popen(["mysqldump", f"-u{db['user']}", db['name']], env=env, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
            p2 = subprocess.Popen(["gzip"], stdin=p1.stdout, stdout=f_out)
            p1.stdout.close()
            p2.communicate()
            
            # FIXED: Wait for the source command to finish to populate returncode correctly
            p1_status = p1.wait()
            if p1_status != 0:
                raise subprocess.CalledProcessError(p1_status, "mysqldump")
                
        log(f"✅ MySQL backup completed: {output_file}")
    except Exception as e:
        log(f"❌ MySQL backup failed for {db['name']}: {e}")
        if os.path.exists(output_file): os.remove(output_file)

def backup_postgres(db: dict):
    output_file = os.path.join(BACKUP_DIR, f"pg_{db['name']}_{TIMESTAMP}.sql.gz")
    log(f"Starting PostgreSQL backup for: {db['name']}...")
    
    env = os.environ.copy()
    env["PGPASSWORD"] = db["password"]
    
    try:
        with open(output_file, "wb") as f_out:
            p1 = subprocess.Popen(["pg_dump", "-U", db['user'], db['name']], env=env, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
            p2 = subprocess.Popen(["gzip"], stdin=p1.stdout, stdout=f_out)
            p1.stdout.close()
            p2.communicate()
            
            # FIXED: Wait for the source command to finish to populate returncode correctly
            p1_status = p1.wait()
            if p1_status != 0:
                raise subprocess.CalledProcessError(p1_status, "pg_dump")
                
        log(f"✅ PostgreSQL backup completed: {output_file}")
    except Exception as e:
        log(f"❌ PostgreSQL backup failed for {db['name']}: {e}")
        if os.path.exists(output_file): os.remove(output_file)

def backup_folders():
    for folder in FOLDERS_TO_BACKUP:
        if os.path.exists(folder):
            clean_folder = folder.rstrip("/")
            folder_name = os.path.basename(clean_folder) if os.path.basename(clean_folder) else "root"
            archive_name = os.path.join(BACKUP_DIR, f"dir_{folder_name}_{TIMESTAMP}")
            log(f"Archiving folder: {folder}...")
            
            # FIXED: Perform archive operation inside try-except block to capture permission errors
            try:
                shutil.make_archive(archive_name, 'gztar', root_dir=os.path.dirname(clean_folder), base_dir=folder_name)
                log(f"✅ Folder archive completed: {archive_name}.tar.gz")
            except Exception as e:
                log(f"❌ Folder archive failed for {folder}: {e}")
        else:
            log(f"⚠️ Folder not found, skipping: {folder}")

def clean_old_backups():
    log(f"Cleaning backups older than {RETENTION_DAYS} days...")
    cutoff_time = time.time() - (RETENTION_DAYS * 86400)
    count = 0
    if not os.path.exists(BACKUP_DIR): return
    
    for file_name in os.listdir(BACKUP_DIR):
        file_path = os.path.join(BACKUP_DIR, file_name)
        if os.path.isfile(file_path):
            if os.path.getmtime(file_path) < cutoff_time:
                os.remove(file_path)
                log(f"Deleted old backup: {file_name}")
                count += 1
    log(f"Cleaned {count} old backup file(s).")

def main():
    log("=========================================")
    log("   Automated Server Backup Engine Start  ")
    log("=========================================")
    ensure_backup_dir()
    for db in DATABASES:
        if db["type"] == "mysql":
            backup_mysql(db)
        elif db["type"] == "postgres":
            backup_postgres(db)
    backup_folders()
    clean_old_backups()
    log("=========================================")
    log("      Backup operation process ended     ")
    log("=========================================")

if __name__ == "__main__":
    main()

Download Assets
Wait 10 sec
Free file download — fast & secure!
Download this open-source asset for free on Clayi Assets. Direct CDN link after a short wait — no account required.

New Resources

Popular Resources

There are no comments yet :(

Automated MySQL & PostgreSQL Server Backup Script in Python
Tell us what you think about "Automated MySQL & PostgreSQL Server Backup Script in Python"
Information
Users of Guests are not allowed to comment this publication.