import os
import shutil
import tarfile
from datetime import datetime, timedelta
from pathlib import Path
import logging
class BackupManager:
def __init__(self, source_dir, backup_dir, max_backups=5, compression=True):
self.source_dir = Path(source_dir)
self.backup_dir = Path(backup_dir)
self.max_backups = max_backups
self.compression = compression
# Create backup directory if it doesn't exist
self.backup_dir.mkdir(parents=True, exist_ok=True)
# Setup logging
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
self.logger = logging.getLogger(__name__)
def create_backup(self):
"""Create a new backup of the source directory"""
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
backup_name = f"backup_{timestamp}"
if self.compression:
backup_path = self.backup_dir / f"{backup_name}.tar.gz"
self._create_compressed_backup(backup_path)
else:
backup_path = self.backup_dir / backup_name
self._create_uncompressed_backup(backup_path)
self.logger.info(f"Backup created: {backup_path}")
self._cleanup_old_backups()
def _create_compressed_backup(self, backup_path):
"""Create a compressed backup using tar.gz format"""
try:
with tarfile.open(backup_path, "w:gz") as tar:
tar.add(self.source_dir, arcname=self.source_dir.name)
except Exception as e:
self.logger.error(f"Failed to create compressed backup: {e}")
raise
def _create_uncompressed_backup(self, backup_path):
"""Create an uncompressed backup by copying directory"""
try:
if backup_path.exists():
shutil.rmtree(backup_path)
shutil.copytree(self.source_dir, backup_path)
except Exception as e:
self.logger.error(f"Failed to create uncompressed backup: {e}")
raise
def _cleanup_old_backups(self):
"""Remove old backups exceeding max_backups limit"""
backups = []
for file in self.backup_dir.iterdir():
if file.is_file() and (file.suffix == '.gz' or 'backup_' in file.name):
backups.append((file.stat().st_mtime, file))
# Sort by modification time (newest first)
backups.sort(reverse=True)
# Remove excess backups
for mtime, backup in backups[self.max_backups:]:
try:
if backup.is_file():
backup.unlink()
else:
shutil.rmtree(backup)
self.logger.info(f"Removed old backup: {backup}")
except Exception as e:
self.logger.error(f"Failed to remove old backup {backup}: {e}")
# Usage example
if __name__ == "__main__":
# Initialize backup manager
# Replace paths with your actual directories
backup_manager = BackupManager(
source_dir="./important_files", # Directory to backup
backup_dir="./backups", # Where to store backups
max_backups=3, # Keep only 3 most recent backups
compression=True # Compress backups
)
# Create a backup
backup_manager.create_backup()
This is a complete backup management system that automatically creates timestamped backups of important directories with the following features:
.tar.gz backups to save disk spaceManaging backups manually is time-consuming and error-prone. This script automates the entire process, ensuring you always have recent backups while preventing your storage from filling up with old copies. It’s especially useful for:
source_dir and backup_dir with your actual pathsmax_backups and compression options as neededBackupManager classYou can easily integrate this into automated workflows by:
0 2 * * * /usr/bin/python3 /path/to/backup_script.py
from backup_manager import BackupManager
backup_manager = BackupManager("./data", "./backups")
backup_manager.create_backup()
The script will automatically handle compression, timestamping, and cleanup of old backups while providing detailed logging of all operations.