#!/bin/bash # Plex Backup Restoration Script # Usage: ./restore-plex.sh [backup_date] [--dry-run] set -e RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' NC='\033[0m' # Configuration SCRIPT_DIR="$(dirname "$(readlink -f "$0")")" BACKUP_ROOT="/mnt/share/media/backups/plex" PLEX_DATA_DIR="/var/lib/plexmediaserver/Library/Application Support/Plex Media Server" # Plex file locations declare -A RESTORE_LOCATIONS=( ["com.plexapp.plugins.library.db"]="$PLEX_DATA_DIR/Plug-in Support/Databases/" ["com.plexapp.plugins.library.blobs.db"]="$PLEX_DATA_DIR/Plug-in Support/Databases/" ["Preferences.xml"]="$PLEX_DATA_DIR/" ) log_message() { echo -e "$(date '+%H:%M:%S') $1" } log_error() { log_message "${RED}ERROR: $1${NC}" } log_success() { log_message "${GREEN}SUCCESS: $1${NC}" } log_warning() { log_message "${YELLOW}WARNING: $1${NC}" } # List available backups list_backups() { log_message "Available backups:" find "$BACKUP_ROOT" -maxdepth 1 -type d -name "????????" | sort -r | while read backup_dir; do local backup_date=$(basename "$backup_dir") local readable_date=$(date -d "${backup_date:0:4}-${backup_date:4:2}-${backup_date:6:2}" '+%B %d, %Y') local file_count=$(ls -1 "$backup_dir" 2>/dev/null | wc -l) echo " $backup_date ($readable_date) - $file_count files" done } # Validate backup integrity validate_backup() { local backup_date="$1" local backup_dir="$BACKUP_ROOT/$backup_date" if [ ! -d "$backup_dir" ]; then log_error "Backup directory not found: $backup_dir" return 1 fi log_message "Validating backup integrity for $backup_date..." for file in "${!RESTORE_LOCATIONS[@]}"; do local backup_file="$backup_dir/$file" if [ -f "$backup_file" ]; then log_success "Found: $file" else log_warning "Missing: $file" fi done } # Create backup of current Plex data backup_current_data() { local backup_suffix=$(date '+%Y%m%d_%H%M%S') local current_backup_dir="$SCRIPT_DIR/plex_current_backup_$backup_suffix" log_message "Creating backup of current Plex data..." mkdir -p "$current_backup_dir" for file in "${!RESTORE_LOCATIONS[@]}"; do local src="${RESTORE_LOCATIONS[$file]}$file" if [ -f "$src" ]; then if sudo cp "$src" "$current_backup_dir/"; then log_success "Backed up current: $file" else log_error "Failed to backup current: $file" return 1 fi fi done log_success "Current data backed up to: $current_backup_dir" echo "$current_backup_dir" } # Restore files from backup restore_files() { local backup_date="$1" local dry_run="$2" local backup_dir="$BACKUP_ROOT/$backup_date" if [ "$dry_run" = "true" ]; then log_message "DRY RUN: Would restore the following files:" else log_message "Restoring files from backup $backup_date..." fi for file in "${!RESTORE_LOCATIONS[@]}"; do local backup_file="$backup_dir/$file" local restore_location="${RESTORE_LOCATIONS[$file]}$file" if [ -f "$backup_file" ]; then if [ "$dry_run" = "true" ]; then echo " $backup_file -> $restore_location" else log_message "Restoring: $file" if sudo cp "$backup_file" "$restore_location"; then sudo chown plex:plex "$restore_location" log_success "Restored: $file" else log_error "Failed to restore: $file" return 1 fi fi else log_warning "Backup file not found: $backup_file" fi done } # Manage Plex service manage_plex_service() { local action="$1" log_message "$action Plex Media Server..." case "$action" in "stop") sudo systemctl stop plexmediaserver.service sleep 3 log_success "Plex stopped" ;; "start") sudo systemctl start plexmediaserver.service sleep 3 log_success "Plex started" ;; esac } # Main function main() { local backup_date="$1" local dry_run=false # Check for dry-run flag if [ "$2" = "--dry-run" ] || [ "$1" = "--dry-run" ]; then dry_run=true fi # If no backup date provided, list available backups if [ -z "$backup_date" ] || [ "$backup_date" = "--dry-run" ]; then list_backups echo echo "Usage: $0 [--dry-run]" echo "Example: $0 20250125" exit 0 fi # Validate backup exists and is complete if ! validate_backup "$backup_date"; then log_error "Backup validation failed" exit 1 fi if [ "$dry_run" = "true" ]; then restore_files "$backup_date" true log_message "Dry run completed. No changes were made." exit 0 fi # Confirm restoration echo log_warning "This will restore Plex data from backup $backup_date" log_warning "Current Plex data will be backed up before restoration" read -p "Continue? (y/N): " -n 1 -r echo if [[ ! $REPLY =~ ^[Yy]$ ]]; then log_message "Restoration cancelled" exit 0 fi # Stop Plex service manage_plex_service stop # Backup current data local current_backup=$(backup_current_data) if [ $? -ne 0 ]; then log_error "Failed to backup current data" manage_plex_service start exit 1 fi # Restore files if restore_files "$backup_date" false; then log_success "Restoration completed successfully" log_message "Current data backup saved at: $current_backup" else log_error "Restoration failed" manage_plex_service start exit 1 fi # Start Plex service manage_plex_service start log_success "Plex restoration completed. Please verify your server is working correctly." } # Trap to ensure Plex is restarted on script exit trap 'manage_plex_service start' EXIT main "$@"