mirror of
https://github.com/acedanger/shell.git
synced 2025-12-06 03:20:12 -08:00
feat: Refactor backup script to initialize performance log file and ensure full backups every time
This commit is contained in:
@@ -23,9 +23,10 @@ MAX_BACKUPS_TO_KEEP=10
|
|||||||
BACKUP_ROOT="/mnt/share/media/backups/plex"
|
BACKUP_ROOT="/mnt/share/media/backups/plex"
|
||||||
LOG_ROOT="/mnt/share/media/backups/logs"
|
LOG_ROOT="/mnt/share/media/backups/logs"
|
||||||
SCRIPT_DIR="$(dirname "$(readlink -f "$0")")"
|
SCRIPT_DIR="$(dirname "$(readlink -f "$0")")"
|
||||||
JSON_LOG_FILE="${SCRIPT_DIR}/logs/plex-backup.json"
|
|
||||||
PERFORMANCE_LOG_FILE="${SCRIPT_DIR}/logs/plex-backup-performance.json"
|
PERFORMANCE_LOG_FILE="${SCRIPT_DIR}/logs/plex-backup-performance.json"
|
||||||
|
|
||||||
|
# Backup strategy configuration - Always perform full backups
|
||||||
|
|
||||||
# Plex SQLite path (custom Plex SQLite binary)
|
# Plex SQLite path (custom Plex SQLite binary)
|
||||||
PLEX_SQLITE="/usr/lib/plexmediaserver/Plex SQLite"
|
PLEX_SQLITE="/usr/lib/plexmediaserver/Plex SQLite"
|
||||||
|
|
||||||
@@ -81,6 +82,7 @@ while [[ $# -gt 0 ]]; do
|
|||||||
echo " --webhook=URL Send notifications to webhook URL"
|
echo " --webhook=URL Send notifications to webhook URL"
|
||||||
echo " --email=ADDRESS Send notifications to email address"
|
echo " --email=ADDRESS Send notifications to email address"
|
||||||
echo " -h, --help Show this help message"
|
echo " -h, --help Show this help message"
|
||||||
|
echo ""
|
||||||
exit 0
|
exit 0
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
@@ -170,48 +172,15 @@ track_performance() {
|
|||||||
log_info "Performance: $operation completed in ${duration}s"
|
log_info "Performance: $operation completed in ${duration}s"
|
||||||
}
|
}
|
||||||
|
|
||||||
# Initialize JSON log file
|
# Initialize log directory
|
||||||
initialize_json_log() {
|
initialize_logs() {
|
||||||
if [ ! -f "${JSON_LOG_FILE}" ] || ! jq empty "${JSON_LOG_FILE}" 2>/dev/null; then
|
mkdir -p "$(dirname "$PERFORMANCE_LOG_FILE")"
|
||||||
echo "{}" > "${JSON_LOG_FILE}"
|
if [ ! -f "$PERFORMANCE_LOG_FILE" ]; then
|
||||||
log_message "Initialized JSON log file"
|
echo "[]" > "$PERFORMANCE_LOG_FILE"
|
||||||
|
log_message "Initialized performance log file"
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
# Check if file needs backup based on modification time
|
|
||||||
needs_backup() {
|
|
||||||
local file="$1"
|
|
||||||
|
|
||||||
if [ ! -f "$file" ]; then
|
|
||||||
log_warning "File not found: $file"
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
local current_mod_date=$(stat -c %Y "$file")
|
|
||||||
local last_backup_date=$(jq -r --arg file "$file" '.[$file] // 0' "${JSON_LOG_FILE}")
|
|
||||||
|
|
||||||
if [ "$last_backup_date" == "null" ] || [ "$last_backup_date" == "0" ]; then
|
|
||||||
log_message "File has never been backed up: $(basename "$file")"
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ "$current_mod_date" -gt "$last_backup_date" ]; then
|
|
||||||
log_message "File modified since last backup: $(basename "$file")"
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
log_message "File unchanged since last backup: $(basename "$file")"
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
|
|
||||||
# Update backup time in JSON log
|
|
||||||
update_backup_time() {
|
|
||||||
local file="$1"
|
|
||||||
local timestamp="$2"
|
|
||||||
|
|
||||||
jq --arg file "$file" --arg timestamp "$timestamp" '.[$file] = ($timestamp | tonumber)' "${JSON_LOG_FILE}" > "${JSON_LOG_FILE}.tmp" && mv "${JSON_LOG_FILE}.tmp" "${JSON_LOG_FILE}"
|
|
||||||
}
|
|
||||||
|
|
||||||
# Enhanced notification system
|
# Enhanced notification system
|
||||||
send_notification() {
|
send_notification() {
|
||||||
local title="$1"
|
local title="$1"
|
||||||
@@ -754,7 +723,7 @@ estimate_backup_size() {
|
|||||||
|
|
||||||
for nickname in "${!PLEX_FILES[@]}"; do
|
for nickname in "${!PLEX_FILES[@]}"; do
|
||||||
local file="${PLEX_FILES[$nickname]}"
|
local file="${PLEX_FILES[$nickname]}"
|
||||||
if [ -f "$file" ] && needs_backup "$file" >/dev/null 2>&1; then
|
if [ -f "$file" ]; then
|
||||||
local size_kb=$(du -k "$file" 2>/dev/null | cut -f1)
|
local size_kb=$(du -k "$file" 2>/dev/null | cut -f1)
|
||||||
total_size=$((total_size + size_kb))
|
total_size=$((total_size + size_kb))
|
||||||
fi
|
fi
|
||||||
@@ -907,8 +876,8 @@ main() {
|
|||||||
mkdir -p "${BACKUP_ROOT}"
|
mkdir -p "${BACKUP_ROOT}"
|
||||||
mkdir -p "${LOG_ROOT}"
|
mkdir -p "${LOG_ROOT}"
|
||||||
|
|
||||||
# Initialize JSON log
|
# Initialize logs
|
||||||
initialize_json_log
|
initialize_logs
|
||||||
|
|
||||||
# Check if only doing integrity check
|
# Check if only doing integrity check
|
||||||
if [ "$INTEGRITY_CHECK_ONLY" = true ]; then
|
if [ "$INTEGRITY_CHECK_ONLY" = true ]; then
|
||||||
@@ -983,43 +952,34 @@ main() {
|
|||||||
# Handle WAL files backup
|
# Handle WAL files backup
|
||||||
handle_wal_files "backup" "$BACKUP_PATH"
|
handle_wal_files "backup" "$BACKUP_PATH"
|
||||||
|
|
||||||
# Backup files
|
# Backup files - always perform full backup
|
||||||
local backup_start=$(date +%s)
|
local backup_start=$(date +%s)
|
||||||
for nickname in "${!PLEX_FILES[@]}"; do
|
for nickname in "${!PLEX_FILES[@]}"; do
|
||||||
local file="${PLEX_FILES[$nickname]}"
|
local file="${PLEX_FILES[$nickname]}"
|
||||||
|
|
||||||
if [ -f "$file" ]; then
|
if [ -f "$file" ]; then
|
||||||
if needs_backup "$file" ]; then
|
log_message "Backing up: $(basename "$file")"
|
||||||
log_message "Backing up: $(basename "$file")"
|
|
||||||
|
|
||||||
# Create backup filename without timestamp (use original filename)
|
# Create backup filename without timestamp (use original filename)
|
||||||
local backup_file="${BACKUP_PATH}/$(basename "$file")"
|
local backup_file="${BACKUP_PATH}/$(basename "$file")"
|
||||||
|
|
||||||
# Copy file
|
# Copy file
|
||||||
if sudo cp "$file" "$backup_file"; then
|
if sudo cp "$file" "$backup_file"; then
|
||||||
log_success "Copied: $(basename "$file")"
|
log_success "Copied: $(basename "$file")"
|
||||||
|
|
||||||
# Verify backup
|
# Verify backup
|
||||||
if verify_backup "$file" "$backup_file"; then
|
if verify_backup "$file" "$backup_file"; then
|
||||||
log_success "Verified: $(basename "$file")"
|
log_success "Verified: $(basename "$file")"
|
||||||
|
files_backed_up=$((files_backed_up + 1))
|
||||||
# Update backup time in JSON log
|
|
||||||
local current_timestamp=$(date +%s)
|
|
||||||
update_backup_time "$file" "$current_timestamp"
|
|
||||||
|
|
||||||
files_backed_up=$((files_backed_up + 1))
|
|
||||||
else
|
|
||||||
log_error "Verification failed: $(basename "$file")"
|
|
||||||
backup_errors=$((backup_errors + 1))
|
|
||||||
# Remove failed backup
|
|
||||||
rm -f "$backup_file"
|
|
||||||
fi
|
|
||||||
else
|
else
|
||||||
log_error "Failed to copy: $(basename "$file")"
|
log_error "Verification failed: $(basename "$file")"
|
||||||
backup_errors=$((backup_errors + 1))
|
backup_errors=$((backup_errors + 1))
|
||||||
|
# Remove failed backup
|
||||||
|
rm -f "$backup_file"
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
log_message "Skipping unchanged file: $(basename "$file")"
|
log_error "Failed to copy: $(basename "$file")"
|
||||||
|
backup_errors=$((backup_errors + 1))
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
log_warning "File not found: $file"
|
log_warning "File not found: $file"
|
||||||
|
|||||||
@@ -1,24 +1,34 @@
|
|||||||
# Enhanced Plex Backup Script Documentation
|
# Enhanced Plex Backup Script Documentation
|
||||||
|
|
||||||
This document provides comprehensive documentation for the enhanced `backup-plex.sh` script. This advanced backup solution includes performance monitoring, parallel processing, intelligent notifications, WAL file handling, and automated testing capabilities.
|
This document provides comprehensive documentation for the enhanced `backup-plex.sh` script. This advanced backup solution includes performance monitoring, parallel processing, intelligent notifications, and WAL file handling.
|
||||||
|
|
||||||
## Script Overview
|
## Script Overview
|
||||||
|
|
||||||
The enhanced script performs the following advanced tasks:
|
The enhanced script performs the following advanced tasks:
|
||||||
|
|
||||||
1. **Performance Monitoring**: Tracks backup operations with JSON-based performance logging
|
1. **Performance Monitoring**: Tracks backup operations with JSON-based performance logging
|
||||||
2. **Intelligent Backup Detection**: Only backs up files that have changed since last backup
|
2. **Full Backup Operations**: Performs complete backups of all Plex files every time
|
||||||
3. **WAL File Handling**: Properly handles SQLite Write-Ahead Logging files
|
3. **WAL File Handling**: Properly handles SQLite Write-Ahead Logging files
|
||||||
4. **Database Integrity Verification**: Comprehensive integrity checks with automated repair options
|
4. **Database Integrity Verification**: Comprehensive integrity checks with automated repair options
|
||||||
5. **Parallel Processing**: Concurrent verification for improved performance
|
5. **Parallel Processing**: Concurrent verification for improved performance
|
||||||
6. **Multi-Channel Notifications**: Console, webhook, and email notification support
|
6. **Multi-Channel Notifications**: Console, webhook, and email notification support
|
||||||
7. **Checksum Caching**: Intelligent caching to avoid recalculating unchanged file checksums
|
7. **Enhanced Service Management**: Safe Plex service management with progress indicators
|
||||||
8. **Enhanced Service Management**: Safe Plex service management with progress indicators
|
8. **Comprehensive Logging**: Detailed logs with color-coded output and timestamps
|
||||||
9. **Comprehensive Logging**: Detailed logs with color-coded output and timestamps
|
9. **Safe Automated Cleanup**: Retention policies based on age and backup count
|
||||||
10. **Automated Cleanup**: Configurable retention policies for old backups
|
|
||||||
|
|
||||||
## Enhanced Features
|
## Enhanced Features
|
||||||
|
|
||||||
|
### Full Backup Operation
|
||||||
|
|
||||||
|
The script performs complete backups every time it runs:
|
||||||
|
|
||||||
|
- **What it does**: Backs up all Plex files regardless of modification status
|
||||||
|
- **Benefits**:
|
||||||
|
- Guarantees every backup is a complete restoration point
|
||||||
|
- Eliminates risk of file loss from incomplete backup coverage
|
||||||
|
- Simplifies backup management and restoration
|
||||||
|
- **Usage**: `./backup-plex.sh` (no options needed)
|
||||||
|
|
||||||
### Performance Tracking
|
### Performance Tracking
|
||||||
|
|
||||||
- **JSON Performance Logs**: All operations are timed and logged to `logs/plex-backup-performance.json`
|
- **JSON Performance Logs**: All operations are timed and logged to `logs/plex-backup-performance.json`
|
||||||
@@ -208,17 +218,6 @@ The performance log (`logs/plex-backup-performance.json`) contains entries like:
|
|||||||
]
|
]
|
||||||
```
|
```
|
||||||
|
|
||||||
### Backup Tracking Log
|
|
||||||
|
|
||||||
The backup tracking log (`logs/plex-backup.json`) tracks last backup times:
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"/var/lib/plexmediaserver/.../com.plexapp.plugins.library.db": 1732567523,
|
|
||||||
"/var/lib/plexmediaserver/.../Preferences.xml": 1732567523
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Usage Examples
|
## Usage Examples
|
||||||
|
|
||||||
### Basic Backup
|
### Basic Backup
|
||||||
@@ -406,15 +405,14 @@ The enhanced script implements a robust backup strategy with a streamlined tar.g
|
|||||||
|
|
||||||
The new backup system eliminates intermediate dated directories and stores only compressed archives:
|
The new backup system eliminates intermediate dated directories and stores only compressed archives:
|
||||||
|
|
||||||
```bash
|
```text
|
||||||
/mnt/share/media/backups/plex/
|
/mnt/share/media/backups/plex/
|
||||||
├── plex-backup-20250125_143022.tar.gz # Latest backup
|
├── plex-backup-20250125_143022.tar.gz # Latest backup
|
||||||
├── plex-backup-20250124_143011.tar.gz # Previous backup
|
├── plex-backup-20250124_143011.tar.gz # Previous backup
|
||||||
├── plex-backup-20250123_143008.tar.gz # Older backup
|
├── plex-backup-20250123_143008.tar.gz # Older backup
|
||||||
└── logs/
|
└── logs/
|
||||||
├── backup_log_20250125_143022.md
|
├── backup_log_20250125_143022.md
|
||||||
├── plex-backup-performance.json
|
└── plex-backup-performance.json
|
||||||
└── plex-backup.json
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### Archive Naming Convention
|
### Archive Naming Convention
|
||||||
@@ -434,15 +432,14 @@ Backup files follow the naming convention `plex-backup-YYYYMMDD_HHMMSS.tar.gz` f
|
|||||||
|
|
||||||
## Final Directory Structure
|
## Final Directory Structure
|
||||||
|
|
||||||
```
|
```text
|
||||||
/mnt/share/media/backups/plex/
|
/mnt/share/media/backups/plex/
|
||||||
├── plex-backup-20250125_143022.tar.gz # Latest backup
|
├── plex-backup-20250125_143022.tar.gz # Latest backup
|
||||||
├── plex-backup-20250124_143011.tar.gz # Previous backup
|
├── plex-backup-20250124_143011.tar.gz # Previous backup
|
||||||
├── plex-backup-20250123_143008.tar.gz # Older backup
|
├── plex-backup-20250123_143008.tar.gz # Older backup
|
||||||
└── logs/
|
└── logs/
|
||||||
├── backup_log_20250125_143022.md
|
├── backup_log_20250125_143022.md
|
||||||
├── plex-backup-performance.json
|
└── plex-backup-performance.json
|
||||||
└── plex-backup.json
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Backup files follow the pattern: `plex-backup-YYYYMMDD_HHMMSS.tar.gz`
|
Backup files follow the pattern: `plex-backup-YYYYMMDD_HHMMSS.tar.gz`
|
||||||
|
|||||||
Reference in New Issue
Block a user