mirror of
https://github.com/acedanger/shell.git
synced 2025-12-06 05:40:11 -08:00
feat: Revamp Plex backup system to streamline archive structure and enhance validation processes
This commit is contained in:
163
backup-plex.sh
163
backup-plex.sh
@@ -466,7 +466,7 @@ handle_wal_files() {
|
||||
"backup")
|
||||
if [ -f "$wal_file" ]; then
|
||||
log_info "Found WAL/SHM file: $wal_basename"
|
||||
local backup_file="${backup_path}/${wal_basename}.$(date '+%Y%m%d_%H%M%S')"
|
||||
local backup_file="${backup_path}/${wal_basename}"
|
||||
|
||||
if sudo cp "$wal_file" "$backup_file"; then
|
||||
log_success "Backed up WAL/SHM file: $wal_basename"
|
||||
@@ -799,20 +799,23 @@ cleanup_old_backups() {
|
||||
log_message "Cleaning up old backups..."
|
||||
|
||||
# Remove backups older than MAX_BACKUP_AGE_DAYS
|
||||
find "${BACKUP_ROOT}" -maxdepth 1 -type d -name "????????" -mtime +${MAX_BACKUP_AGE_DAYS} -exec rm -rf {} \; 2>/dev/null || true
|
||||
find "${BACKUP_ROOT}" -maxdepth 1 -type f -name "plex-backup-*.tar.gz" -mtime +${MAX_BACKUP_AGE_DAYS} -delete 2>/dev/null || true
|
||||
|
||||
# Keep only MAX_BACKUPS_TO_KEEP most recent backups
|
||||
local backup_count=$(find "${BACKUP_ROOT}" -maxdepth 1 -type d -name "????????" | wc -l)
|
||||
local backup_count=$(find "${BACKUP_ROOT}" -maxdepth 1 -type f -name "plex-backup-*.tar.gz" | wc -l)
|
||||
|
||||
if [ "$backup_count" -gt "$MAX_BACKUPS_TO_KEEP" ]; then
|
||||
local excess_count=$((backup_count - MAX_BACKUPS_TO_KEEP))
|
||||
log_message "Removing $excess_count old backup(s)..."
|
||||
|
||||
find "${BACKUP_ROOT}" -maxdepth 1 -type d -name "????????" -printf '%T@ %p\n' | \
|
||||
find "${BACKUP_ROOT}" -maxdepth 1 -type f -name "plex-backup-*.tar.gz" -printf '%T@ %p\n' | \
|
||||
sort -n | head -n "$excess_count" | cut -d' ' -f2- | \
|
||||
xargs -r rm -rf
|
||||
xargs -r rm -f
|
||||
fi
|
||||
|
||||
# Clean up any remaining dated directories from old backup structure
|
||||
find "${BACKUP_ROOT}" -maxdepth 1 -type d -name "????????" -exec rm -rf {} \; 2>/dev/null || true
|
||||
|
||||
log_message "Backup cleanup completed"
|
||||
}
|
||||
|
||||
@@ -929,9 +932,9 @@ main() {
|
||||
|
||||
local backup_errors=0
|
||||
local files_backed_up=0
|
||||
local BACKUP_PATH="${BACKUP_ROOT}/$(date '+%Y%m%d')"
|
||||
local BACKUP_PATH="${BACKUP_ROOT}"
|
||||
|
||||
# Create today's backup directory
|
||||
# Ensure backup root directory exists
|
||||
mkdir -p "$BACKUP_PATH"
|
||||
|
||||
# Handle WAL files and check database integrity before backup
|
||||
@@ -989,8 +992,8 @@ main() {
|
||||
if needs_backup "$file" ]; then
|
||||
log_message "Backing up: $(basename "$file")"
|
||||
|
||||
# Create backup filename with timestamp
|
||||
local backup_file="${BACKUP_PATH}/$(basename "$file").$(date '+%Y%m%d_%H%M%S')"
|
||||
# Create backup filename without timestamp (use original filename)
|
||||
local backup_file="${BACKUP_PATH}/$(basename "$file")"
|
||||
|
||||
# Copy file
|
||||
if sudo cp "$file" "$backup_file"; then
|
||||
@@ -1029,32 +1032,136 @@ main() {
|
||||
# Create archive if files were backed up
|
||||
if [ "$files_backed_up" -gt 0 ]; then
|
||||
log_message "Creating compressed archive..."
|
||||
local temp_archive="/tmp/plex-backup-$(date '+%Y%m%d_%H%M%S').tar.gz"
|
||||
local final_archive="${BACKUP_PATH}/plex-backup-$(date '+%Y%m%d_%H%M%S').tar.gz"
|
||||
|
||||
# Create archive in /tmp first to avoid "file changed" issues
|
||||
if tar --exclude="*.tar.gz" -czf "$temp_archive" -C "$(dirname "$BACKUP_PATH")" "$(basename "$BACKUP_PATH")"; then
|
||||
# Move the completed archive to the backup directory
|
||||
if mv "$temp_archive" "$final_archive"; then
|
||||
log_success "Archive created: $(basename "$final_archive")"
|
||||
|
||||
# Remove individual backup files, keep only the archive
|
||||
find "$BACKUP_PATH" -type f ! -name "*.tar.gz" -delete
|
||||
else
|
||||
log_error "Failed to move archive to final location"
|
||||
rm -f "$temp_archive"
|
||||
backup_errors=$((backup_errors + 1))
|
||||
fi
|
||||
else
|
||||
log_error "Failed to create archive"
|
||||
# Check backup root directory is writable
|
||||
if [ ! -w "$BACKUP_ROOT" ]; then
|
||||
log_error "Backup root directory is not writable: $BACKUP_ROOT"
|
||||
backup_errors=$((backup_errors + 1))
|
||||
else
|
||||
local temp_archive="/tmp/plex-backup-$(date '+%Y%m%d_%H%M%S').tar.gz"
|
||||
local final_archive="${BACKUP_ROOT}/plex-backup-$(date '+%Y%m%d_%H%M%S').tar.gz"
|
||||
|
||||
log_info "Temporary archive: $temp_archive"
|
||||
log_info "Final archive: $final_archive"
|
||||
|
||||
# Create archive in /tmp first, containing only the backed up files
|
||||
local temp_dir="/tmp/plex-backup-staging-$(date '+%Y%m%d_%H%M%S')"
|
||||
if ! mkdir -p "$temp_dir"; then
|
||||
log_error "Failed to create staging directory: $temp_dir"
|
||||
backup_errors=$((backup_errors + 1))
|
||||
else
|
||||
log_info "Created staging directory: $temp_dir"
|
||||
|
||||
# Copy backed up files to staging directory
|
||||
local files_staged=0
|
||||
for nickname in "${!PLEX_FILES[@]}"; do
|
||||
local file="${PLEX_FILES[$nickname]}"
|
||||
local backup_file="${BACKUP_PATH}/$(basename "$file")"
|
||||
if [ -f "$backup_file" ]; then
|
||||
if cp "$backup_file" "$temp_dir/"; then
|
||||
files_staged=$((files_staged + 1))
|
||||
log_info "Staged for archive: $(basename "$backup_file")"
|
||||
else
|
||||
log_warning "Failed to stage file: $(basename "$backup_file")"
|
||||
fi
|
||||
else
|
||||
log_warning "Backup file not found for staging: $(basename "$backup_file")"
|
||||
fi
|
||||
done
|
||||
|
||||
# Check if any files were staged
|
||||
if [ "$files_staged" -eq 0 ]; then
|
||||
log_error "No files were staged for archive creation"
|
||||
rm -rf "$temp_dir"
|
||||
backup_errors=$((backup_errors + 1))
|
||||
else
|
||||
log_info "Staged $files_staged files for archive creation"
|
||||
|
||||
# Check disk space in /tmp
|
||||
local temp_available_kb=$(df /tmp | awk 'NR==2 {print $4}')
|
||||
local temp_available_mb=$((temp_available_kb / 1024))
|
||||
local staging_size_mb=$(du -sm "$temp_dir" | cut -f1)
|
||||
log_info "/tmp available space: ${temp_available_mb}MB, staging directory size: ${staging_size_mb}MB"
|
||||
|
||||
# Check if we have enough space (require 3x staging size for compression)
|
||||
local required_space_mb=$((staging_size_mb * 3))
|
||||
if [ "$temp_available_mb" -lt "$required_space_mb" ]; then
|
||||
log_error "Insufficient space in /tmp for archive creation. Required: ${required_space_mb}MB, Available: ${temp_available_mb}MB"
|
||||
rm -rf "$temp_dir"
|
||||
backup_errors=$((backup_errors + 1))
|
||||
else
|
||||
# Create archive with detailed error logging
|
||||
log_info "Creating archive: $(basename "$temp_archive")"
|
||||
local tar_output
|
||||
tar_output=$(tar -czf "$temp_archive" -C "$temp_dir" . 2>&1)
|
||||
local tar_exit_code=$?
|
||||
|
||||
if [ $tar_exit_code -eq 0 ]; then
|
||||
# Verify archive was actually created and has reasonable size
|
||||
if [ -f "$temp_archive" ]; then
|
||||
local archive_size_mb=$(du -sm "$temp_archive" | cut -f1)
|
||||
log_success "Archive created successfully: $(basename "$temp_archive") (${archive_size_mb}MB)"
|
||||
|
||||
# Test archive integrity before moving
|
||||
if tar -tzf "$temp_archive" >/dev/null 2>&1; then
|
||||
log_success "Archive integrity verified"
|
||||
|
||||
# Move the completed archive to the backup root
|
||||
if mv "$temp_archive" "$final_archive"; then
|
||||
log_success "Archive moved to final location: $(basename "$final_archive")"
|
||||
|
||||
# Remove individual backup files and staging directory
|
||||
rm -rf "$temp_dir"
|
||||
for nickname in "${!PLEX_FILES[@]}"; do
|
||||
local file="${PLEX_FILES[$nickname]}"
|
||||
local backup_file="${BACKUP_PATH}/$(basename "$file")"
|
||||
rm -f "$backup_file" "$backup_file.md5"
|
||||
done
|
||||
else
|
||||
log_error "Failed to move archive to final location: $final_archive"
|
||||
log_error "Temporary archive remains at: $temp_archive"
|
||||
rm -rf "$temp_dir"
|
||||
backup_errors=$((backup_errors + 1))
|
||||
fi
|
||||
else
|
||||
log_error "Archive integrity check failed - archive may be corrupted"
|
||||
log_error "Archive size: ${archive_size_mb}MB"
|
||||
rm -f "$temp_archive"
|
||||
rm -rf "$temp_dir"
|
||||
backup_errors=$((backup_errors + 1))
|
||||
fi
|
||||
else
|
||||
log_error "Archive file was not created despite tar success"
|
||||
rm -rf "$temp_dir"
|
||||
backup_errors=$((backup_errors + 1))
|
||||
fi
|
||||
else
|
||||
log_error "Failed to create archive (tar exit code: $tar_exit_code)"
|
||||
if [ -n "$tar_output" ]; then
|
||||
log_error "Tar command output: $tar_output"
|
||||
fi
|
||||
|
||||
# Additional diagnostic information
|
||||
log_error "Staging directory contents:"
|
||||
ls -la "$temp_dir" 2>&1 | while IFS= read -r line; do
|
||||
log_error " $line"
|
||||
done
|
||||
|
||||
local temp_usage=$(df -h /tmp | awk 'NR==2 {print "Used: " $3 "/" $2 " (" $5 ")"}')
|
||||
log_error "Temp filesystem status: $temp_usage"
|
||||
|
||||
rm -rf "$temp_dir"
|
||||
backup_errors=$((backup_errors + 1))
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# Send notification
|
||||
send_notification "Backup Completed" "Successfully backed up $files_backed_up files" "success"
|
||||
else
|
||||
log_message "No files needed backup, removing empty backup directory"
|
||||
rmdir "$BACKUP_PATH" 2>/dev/null || true
|
||||
log_message "No files needed backup"
|
||||
fi
|
||||
|
||||
# Cleanup old backups
|
||||
|
||||
Reference in New Issue
Block a user