Initial commit of MyWorkspace - contains multiple projects and global workspace configuration

This commit is contained in:
DavidSaylor
2026-05-06 22:59:37 -05:00
commit 019e35b488
2520 changed files with 13634 additions and 0 deletions

319
BackupScript/backup.sh Normal file
View File

@@ -0,0 +1,319 @@
#!/bin/bash
# Prevent set -e from causing issues in testing
set -uo pipefail
SCRIPT_NAME=$(basename "$0")
# Log to stderr with timestamp
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $SCRIPT_NAME: $*" >&2
}
# Get current timestamp in seconds since epoch
get_timestamp() {
date +%s
}
# Set file modification time to a specific date
set_file_mtime() {
local file="$1"
local new_date="$2"
touch -d "$new_date" "$file"
}
# --- Testing Functions ---
# Function to create test backup files with manipulated timestamps
create_test_backups() {
local dest_dir="${1:-/mnt/Backup/Ubuntu/Backups}"
local use_test_timestamp="${2:-now}"
log "Creating test backup files in $dest_dir (using timestamp: $use_test_timestamp)"
# Create the directory
mkdir -p "$dest_dir"
local now_ts=$(get_timestamp)
local now_date=$(date '+%Y-%m-%d')
# Convert relative days to timestamp
days_ago() {
local d="$1"
date -d "${d} days ago" +%s 2>/dev/null || echo ""
}
case "$use_test_timestamp" in
"today")
set_file_mtime "$dest_dir/test-today.tgz" "$now_date"
log "Created test file: test-today.tgz (today)"
;;
"yesterday")
set_file_mtime "$dest_dir/test-yesterday.tgz" "$(days_ago 1)"
log "Created test file: test-yesterday.tgz (1 day ago)"
;;
"3days")
set_file_mtime "$dest_dir/test-3days.tgz" "$(days_ago 3)"
log "Created test file: test-3days.tgz (3 days ago)"
;;
"6days")
set_file_mtime "$dest_dir/test-6days.tgz" "$(days_ago 6)"
log "Created test file: test-6days.tgz (6 days ago)"
;;
"7days")
set_file_mtime "$dest_dir/test-7days.tgz" "$(days_ago 7)"
log "Created test file: test-7days.tgz (7 days ago)"
;;
"14days")
set_file_mtime "$dest_dir/test-14days.tgz" "$(days_ago 14)"
log "Created test file: test-14days.tgz (14 days ago)"
;;
"29days")
set_file_mtime "$dest_dir/test-29days.tgz" "$(days_ago 29)"
log "Created test file: test-29days.tgz (29 days ago)"
;;
"60days")
set_file_mtime "$dest_dir/test-60days.tgz" "$(days_ago 60)"
log "Created test file: test-60days.tgz (60 days ago)"
;;
"90days")
set_file_mtime "$dest_dir/test-90days.tgz" "$(days_ago 90)"
log "Created test file: test-90days.tgz (90 days ago)"
;;
"monday")
# Get yesterday's date, check if Monday, otherwise find next Monday
local check_date=$(date -d "yesterday" '+%A')
if [ "$check_date" = "Monday" ]; then
set_file_mtime "$dest_dir/test-monday.tgz" "$(days_ago 1)"
log "Created test file: test-monday.tgz (yesterday/Monday)"
else
# Find next Monday (2 days from now if today is Saturday, etc.)
local days_to_monday=$(( (1 + (6 - $(date +%w))) % 7 ))
set_file_mtime "$dest_dir/test-monday.tgz" "$(days_ago $days_to_monday)"
log "Created test file: test-monday.tgz (previous Monday)"
fi
;;
"sunday")
# Find the most recent Sunday
local days_to_sunday=$(( (date +%w) % 7 ))
set_file_mtime "$dest_dir/test-sunday.tgz" "$(days_ago $days_to_sunday)"
log "Created test file: test-sunday.tgz (most recent Sunday)"
;;
"1st")
# Get the 1st day of current month
current_month=$(date +%m)
set_file_mtime "$dest_dir/test-1st.tgz" "$(date -d "${current_month}-01" '+%s')"
log "Created test file: test-1st.tgz (1st of this month)"
;;
*)
log "Unknown timestamp option: $use_test_timestamp"
;;
esac
}
# Create test files for multiple scenarios
create_all_test_backups() {
local dest_dir="${1:-/mnt/Backup/Ubuntu/Backups}"
log "Creating comprehensive test backup files in $dest_dir"
create_test_backups "$dest_dir" "today"
create_test_backups "$dest_dir" "yesterday"
create_test_backups "$dest_dir" "3days"
create_test_backups "$dest_dir" "6days"
create_test_backups "$dest_dir" "7days"
create_test_backups "$dest_dir" "14days"
create_test_backups "$dest_dir" "29days"
create_test_backups "$dest_dir" "60days"
create_test_backups "$dest_dir" "90days"
create_test_backups "$dest_dir" "monday"
create_test_backups "$dest_dir" "sunday"
create_test_backups "$dest_dir" "1st"
log "Test backup files created. Run ./backup.sh to test retention logic."
}
# --- Configuration ---
# Backup 1: /mnt/Content → /mnt/Backup (rsync sync)
CONTENT_SRC="/mnt/Content"
CONTENT_DEST="/mnt/Backup"
CONTENT_EXCLUDES="/etc/backup-excludes/content.exclude"
# Backup 2: / (root filesystem) → /mnt/Backup/Ubuntu/Backups (compressed tar)
UBUNTU_DEST="/mnt/Backup/Ubuntu/Backups"
UBUNTU_EXCLUDES="/etc/backup-excludes/ubuntu.exclude"
# === Helper Functions ===
# Run rsync with low CPU and I/O priority
run_rsync() {
local label="$1"
shift
log "Starting low-priority rsync ($label)"
nice -n 19 ionice -c 3 rsync -avHAX "$@"
}
# Run a command with low CPU and I/O priority
run_low_priority() {
local label="$1"
shift
log "Starting low-priority $label..."
nice -n 19 ionice -c 3 "$@"
}
# === Task 1: Sync /mnt/Content → /mnt/Backup ===
if [ -d "$CONTENT_SRC" ]; then
log "Starting rsync of $CONTENT_SRC$CONTENT_DEST (with excludes)"
# Ensure destination directory exists
run_low_priority "Create destination" \
mkdir -p "$CONTENT_DEST"
# Use --delete to sync deletions - frees space at destination
run_rsync "Content -> Backup (media)" \
--delete-before \
--exclude-from="$CONTENT_EXCLUDES" \
"$CONTENT_SRC"/ "$CONTENT_DEST"/
log "Finished $CONTENT_SRC$CONTENT_DEST backup."
else
log "WARNING: $CONTENT_SRC not found or not a directory; skipping."
fi
# === Task 2: Full filesystem backup with compression ===
log "Starting tar backup of / → $UBUNTU_DEST (excluding system paths)"
# Ensure destination directory exists
run_low_priority "Create destination" \
mkdir -p "$UBUNTU_DEST"
# Generate timestamp for backup filename
timestamp=$(date +%Y-%m-%d)
# Create backup filename with timestamp
tar_output="$UBUNTU_DEST/backup-full-$timestamp.tgz"
log "Starting compressed backup of /..."
# Run tar with low priority (compression is I/O intensive)
run_low_priority "Full system backup" \
tar -czf "$tar_output" \
--exclude-from="$UBUNTU_EXCLUDES" \
/
log "Finished / → $UBUNTU_DEST backup."
# === Retention Management ===
log "Managing backup retention in $UBUNTU_DEST..."
# Create the directory if it doesn't exist (already done above, but for safety)
[ ! -d "$UBUNTU_DEST" ] && sudo mkdir -p "$UBUNTU_DEST"
# Count current totals
daily_count=0
weekly_count=0
monthly_count=0
if [ -n "$(ls -A "$UBUNTU_DEST"/*.tgz 2>/dev/null)" ]; then
# First pass: count existing files by type
for file in "$UBUNTU_DEST"/*.tgz; do
[ -f "$file" ] || continue
mtime=$(stat -c %Y "$file")
age=$(( ($(date +%s) - $mtime) / (3600 * 24) ))
backup_date=$(date -d "@$mtime" '+%Y-%m-%d')
day=$(date -d "$backup_date" +%d)
weekday=$(date -d "$backup_date" +%w) # 0=Sunday
if [ $age -lt 7 ]; then
((daily_count++))
fi
if [ $weekday -eq 0 ]; then
((weekly_count++))
fi
if [ $day -eq 01 ]; then
((monthly_count++))
fi
done
log "Current counts - Daily: $daily_count, Weekly: $weekly_count, Monthly: $monthly_count"
fi
# Process each backup file
if [ -n "$(ls -A "$UBUNTU_DEST"/*.tgz 2>/dev/null)" ]; then
for backup_file in $(ls -1 "$UBUNTU_DEST"/*.tgz | sort --key=1.2 --reverse); do
filename=$(basename "$backup_file")
mtime=$(stat -c %Y "$backup_file")
age=$(( ($(date +%s) - $mtime) / (3600 * 24) ))
# Calculate date of the backup
backup_date=$(date -d "@$mtime" '+%Y-%m-%d')
day=$(date -d "$backup_date" +%d)
month=$(date -d "$backup_date" +%m)
weekday=$(date -d "$backup_date" +%w) # 0=Sunday
# Calculate months since backup
backup_year=$(date -d "$backup_date" +%Y)
backup_month_int=$((10#$month))
current_month_int=$((10#$month))
current_year_int=$((10#$backup_year))
if [ $backup_month_int -lt $current_month_int ]; then
months_since=$(( (current_month_int - backup_month_int) + 12 ))
else
months_since=$(( current_month_int - backup_month_int ))
fi
if [ $backup_year_int -lt $current_year_int ]; then
months_since=$(( months_since + 12 ))
fi
# Determine backup type
is_daily=0
is_weekly=0
is_monthly=0
if [ $age -lt 7 ]; then
is_daily=1
fi
if [ $weekday -eq 0 ]; then
is_weekly=1
fi
if [ $day -eq 01 ]; then
is_monthly=1
fi
# Keep daily backups (less than 7 days old)
if [ $is_daily -eq 1 ]; then
log "Backup $filename: Keeping (daily backup, age: $age days)"
((daily_count++))
continue
fi
# Keep Sunday backups for the last month (31 days)
if [ $is_weekly -eq 1 ] && [ $age -lt 31 ]; then
log "Backup $filename: Keeping (weekly Sunday backup, age: $age days)"
((weekly_count++))
continue
fi
# Keep 1st-of-month backups for the last 3 months
if [ $is_monthly -eq 1 ] && [ $months_since -lt 3 ]; then
log "Backup $filename: Keeping (monthly 1st-of-month backup, age: $age days)"
((monthly_count++))
continue
fi
# Delete backup that doesn't meet retention criteria
log "Deleting backup: $filename (age: $age days, days_since: $months_since, type: none)"
sudo rm "$backup_file"
done
else
log "No backup files found in $UBUNTU_DEST"
fi
log "All backups completed."

View File

@@ -0,0 +1,31 @@
# Windows cruft
$RECYCLE.BIN
'$RECYCLE.BIN'
System Volume Information
'System Volume Information'
Thumbs.db
desktop.ini
*.tmp
temp/
Temp/
Temp.*
tmp/
*.log
# Syncthing internal state
.stfolder
*.stfolder
.syncthing
*.stignore
.index.*
.clones
*.idx*
# Skip the old Windows DockerContainers on /mnt/Content
DockerContainers
# Android / user cache style (if present under Data/Test)
*/.cache/*
*/temp/*
*/cache/*
*/DCIM/.thumbnails/*

4
BackupScript/cronjob Normal file
View File

@@ -0,0 +1,4 @@
# Cron job for daily backups at 3:00 AM
# Copy this file to /etc/cron.d/backup or create an entry in /etc/crontab
0 3 * * * root /opt/backup.sh >> /var/log/backup.log 2>&1

124
BackupScript/example.sh Normal file
View File

@@ -0,0 +1,124 @@
#!/bin/bash
set -euo pipefail
SCRIPT_NAME=$(basename "$0")
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $SCRIPT_NAME: $*" >&2
}
cd / || exit 1
#UBUNTU_DEST="/mnt/Backup/Ubuntu"
UBUNTU_DEST="/mnt/Backup/Ubuntu/Backups"
CONTENT_SRC="/mnt/Content"
CONTENT_DEST="/mnt/Backup"
# helper wrapper: run rsync with low CPU and low I/O priority
run_rsync() {
local label="$1"
shift
log "Starting lowpriority rsync ($label)"
nice -n 19 ionice -c 3 rsync -avHAX --delete "$@"
}
# Helper function: Run a command with low CPU and I/O priority
run_low_priority() {
local label="$1"
shift
log "Starting low-priority $label..."
nice -n 19 ionice -c 3 "$@"
}
# Function to manage backup lifecycle - keep dailies for the past week, keep weeklies for the past month, keep montlies for 6 months.
manage_backups() {
#local dir="/mnt/Backup/Ubuntu/Backups" - use UBUNTU_DEST
log "Managing backups in $dir..."
# Create the directory if it doesn't exist
[ ! -d "$UBUNTU_DEST" ] && sudo mkdir -p "$UBUNTU_DEST"
# List all .tgz files and sort them by modification time (oldest first)
for backup_file in $(sudo ls -1 $UBUNTU_DEST/*.tgz | sort --key=1.2 --reverse); do
filename=$(basename "$backup_file")
timestamp=$(echo "$filename" | cut -d'-' -f3- | cut -d '.' -f1)
# Calculate age in days
mtime=$(stat -c %Y "$backup_file")
age=$(( ($(date +%s) - $mtime) / (3600 * 24) ))
# Extract day, month, and weekday from timestamp
day=$(date -d "@$timestamp" +%d)
month=$(date -d "@$timestamp" +%m)
weekday=$(date -d "@$timestamp" +%w)
# Check if backup is less than a week old (daily retention)
if [ $age -lt 7 ]; then
log "Backup $filename is less than a week old. Keeping."
continue
fi
# Check for weekly backups on Sundays within the last month
if [ $weekday == '0' ]; then
current_month=$(date +%m)
months_since=$(( (current_month - $month) % 12 ))
if [ $months_since -lt 1 ]; then
log "Backup $filename is a weekly backup on Sunday within the last month. Keeping."
continue
fi
fi
# Check for monthly backups on first day of the month within six months
if [ $day == '01' ]; then
current_month=$(date +%m)
months_since=$(( (current_month - $month) % 12 ))
if [ $months_since -lt 6 ]; then
log "Backup $filename is a monthly backup on the first day within six months. Keeping."
continue
fi
fi
# Delete backups older than retention criteria
log "Deleting backup: $filename"
sudo rm "$backup_file"
done
}
# --- 1. Backup / → /mnt/Backup/Ubuntu (fast, configs + Docker) ---
log "Starting tar backup of / → $UBUNTU_DEST (excluding /mnt and pseudodirs)"
sudo mkdir -p "$UBUNTU_DEST"
# no longer using rsync to backup main filesystem as single file backup using compression works better with remote sync - does not interfere with syncthing state files and folders at the destination
#run_rsync "Ubuntu configs & Docker" \
# --exclude-from=/etc/backup-excludes/ubuntu.exclude \
# / "$UBUNTU_DEST"/
# Create a compressed tar backup with timestamp in the filename
timestamp=$(date +%Y%m%d-%H%M%S)
tar_output="$UBUNTU_DEST/backup-full-$timestamp.tgz"
log "Starting backup of /..."
run_low_priority "Ubuntu full backup" \
tar -czf "$tar_output" --exclude-from=/etc/backup-excludes/ubuntu.exclude /
log "Finished / → $UBUNTU_DEST backup."
# --- 2. Backup /mnt/Content → /mnt/Backup (large mediaheavy sync) ---
if [ -d "$CONTENT_SRC" ]; then
log "Starting rsync of $CONTENT_SRC$CONTENT_DEST (with excludes)"
# using --delete-before to ensure space is freed at destination for new and updated files
run_rsync "Content -> Backup (media)" \
--delete-before
--exclude-from=/etc/backup-excludes/content.exclude \
"$CONTENT_SRC"/ "$CONTENT_DEST"/
log "Finished $CONTENT_SRC$CONTENT_DEST backup."
else
log "WARNING: $CONTENT_SRC not found or not a directory; skipping."
fi
log "All backups completed."

View File

@@ -0,0 +1,12 @@
# Don't back up /mnt (Content, Backup, etc.)
/mnt
# OS pseudodirs
/dev
/proc
/run
/sys
/tmp
/var/cache/apt/archives/
/var/run
/var/tmp