Handling File Corruption After System Crashes
System crashes can lead to catastrophic data loss when working files become corrupted. This Python script implements an automated backup system that maintains botth temporary and permanent copies of working directories at configurable intervals.
Implementation Overview
The backup system operates through Backup.py, which uses several core modules:
import click
import os
import time
import datetime
from shutil import copy, copyfile
LOG = print
Directory Copy Functionality
The recursive folder copy function handles nested directory structures:
def copy_folder(src, dest):
"""
Recursively copies contents from src to dest
"""
items = os.listdir(src)
if not os.path.exists(dest):
os.mkdir(dest)
for item in items:
src_path = os.path.join(src, item)
dest_path = os.path.join(dest, item)
if os.path.isdir(src_path):
if not os.path.exists(dest_path):
os.mkdir(dest_path)
copy_folder(src_path, dest_path)
else:
copyfile(src_path, dest_path)
Storage Space Calculation
The script includes safeguards against excessive disk usage:
def calculate_folder_size(path, max_depth=None):
"""
Calculates total size of directory contents
"""
total = 0.0
depth = -1 if max_depth is None else max_depth
if depth >= 0:
if os.path.isfile(path):
total += os.path.getsize(path)
else:
with os.scandir(path) as entries:
for entry in entries:
if entry.is_file():
total += entry.stat().st_size
else:
total += calculate_folder_size(entry.path, depth - 1)
return total
Backup Scheduling Logic
The main backup function uses Click for command-line configuration:
@click.command()
@click.option("--source", default="./", help="Working directory path")
@click.option("--destination", default="E://Backup", help="Backup location")
@click.option("--interval", default=5, help="Temporary backup interval in minutes")
@click.option("--queue_size", default=10, help="Number of temporary backups to maintain")
@click.option("--permanent_interval", default=6.0, help="Permanent backup interval in hours")
def backup(source, destination, interval, queue_size, permanent_interval):
"""
Manages the backup process with configurable intervals
"""
if not os.path.exists(source):
LOG("Error: Source directory not found")
exit(1)
size = calculate_folder_size(source, 10)
LOG(f"Source size: {size/1024**2:.2f}MB")
backup_queue = [os.path.join(destination, f"TEMP_{i}") for i in range(1, queue_size + 1)]
current_index = 0
while True:
current_time = time.time()
# Temporary backup logic
if current_time - last_temp_backup >= interval * 60:
backup_path = backup_queue[current_index]
timestamp = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
LOG(f"{timestamp}: Temporary backup to {backup_path}")
copy_folder(source, backup_path)
current_index = (current_index + 1) % queue_size
last_temp_backup = current_time
# Permanent backup logic
if current_time - last_perm_backup >= permanent_interval * 3600:
timestamp = datetime.datetime.now().strftime("%Y-%m-%d_%H%M%S")
perm_path = os.path.join(destination, f"PERM_{timestamp}")
LOG(f"{timestamp}: Permanent backup to {perm_path}")
copy_folder(source, perm_path)
last_perm_backup = current_time
time.sleep(60)
if __name__ == "__main__":
backup()
Usage Example
To run the backup process:
python Backup.py --source "D:/Work" --destination "E:/Backups" --interval 5 --queue_size 10 --permanent_interval 4
The script will maintain:
- 10 rotating temporary backups (every 5 minutes)
- Permanent archives (every 4 hours)
- Output progress information to console
Terminate the process with Ctrl+C when backup protection is no longer needed.