Last active
November 12, 2024 19:18
-
-
Save cbruegg/70d8d9fcb7ebc7f53b7648084516b48c to your computer and use it in GitHub Desktop.
Script to keep differential backups of your Dropbox with a maximum storage quota using rclone. Uses hardlinks to save space.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# Configuration | |
RCLONE_REMOTE="dropbox:/" # Adjust this if you don't want the full Dropbox | |
BACKUP_DIR="/path/to/backups" # Adjust to your local backup directory | |
SNAPSHOT_LIMIT=500000 # Max usage in MB (500 GB) | |
# Create backup directory if it doesn't exist | |
mkdir -p "$BACKUP_DIR" | |
# Function to calculate disk usage (including 'backup-main') | |
calculate_usage() { | |
du -sm "$BACKUP_DIR" 2>/dev/null | awk '{print $1}' | |
} | |
# Step 1: Sync Dropbox to backup-main | |
echo "Starting rclone sync..." | |
if ! rclone sync "$RCLONE_REMOTE" "$BACKUP_DIR/backup-main"; then | |
echo "Error: rclone sync failed" | |
exit 1 | |
fi | |
echo "rclone sync completed." | |
# Step 2: Create a snapshot with hardlinks | |
DATE=$(date -I) # ISO format (YYYY-MM-DD) | |
SNAPSHOT_DIR="$BACKUP_DIR/backup-$DATE" | |
echo "Creating snapshot for $DATE..." | |
if ! rsync -a --link-dest="$BACKUP_DIR/backup-main" "$BACKUP_DIR/backup-main/" "$SNAPSHOT_DIR"; then | |
echo "Error: rsync snapshot creation failed" | |
exit 1 | |
fi | |
echo "Snapshot $SNAPSHOT_DIR created successfully." | |
# Step 3: Check disk usage and delete old snapshots if necessary | |
current_usage=$(calculate_usage) | |
echo "Current total backup usage: $current_usage MB" | |
if [ "$current_usage" -gt "$SNAPSHOT_LIMIT" ]; then | |
echo "Storage limit exceeded. Cleaning up old snapshots..." | |
while [ "$current_usage" -gt "$SNAPSHOT_LIMIT" ]; do | |
# Find the oldest snapshot (excluding 'backup-main') | |
oldest_snapshot=$(ls -1d "$BACKUP_DIR"/backup-* 2>/dev/null | grep -v "backup-main" | sort | head -n 1) | |
if [ -z "$oldest_snapshot" ]; then | |
echo "No snapshots found to delete. Exiting cleanup." | |
break | |
fi | |
# Failsafe: Ensure $oldest_snapshot is within $BACKUP_DIR | |
if [[ "$oldest_snapshot" != "$BACKUP_DIR/"* ]]; then | |
echo "Error: $oldest_snapshot is outside the backup directory. Aborting deletion." | |
exit 1 | |
fi | |
echo "Deleting oldest snapshot: $oldest_snapshot" | |
if ! rm -rf "$oldest_snapshot"; then | |
echo "Error: Failed to delete $oldest_snapshot" | |
exit 1 | |
fi | |
current_usage=$(calculate_usage) | |
echo "Updated total backup usage: $current_usage MB" | |
done | |
else | |
echo "Storage usage is within limit." | |
fi | |
echo "Backup process completed successfully." | |
exit 0 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment