Files
timebank-cc-public/scripts/backup-all.sh
Ronald Huynen 2547717edb Initial commit
2026-03-23 21:37:59 +01:00

324 lines
9.5 KiB
Bash
Executable File

#!/bin/bash
# Laravel Timebank Master Backup Script
# Orchestrates database and storage backups with health checks
# Usage: ./backup-all.sh [backup_type] [options]
# backup_type: daily (default), weekly, monthly
# options: --storage-only, --database-only, --verify, --notify
set -e # Exit on any error
# Configuration
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(dirname "$SCRIPT_DIR")"
BACKUP_ROOT_DIR="$PROJECT_ROOT/backups"
LOG_FILE="$BACKUP_ROOT_DIR/backup.log"
HEALTH_CHECK_FILE="$BACKUP_ROOT_DIR/health_check.json"
# Create backup directories
mkdir -p "$BACKUP_ROOT_DIR/logs"
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# Logging function with colors
log() {
local level="$1"
local message="$2"
local timestamp="[$(date '+%Y-%m-%d %H:%M:%S')]"
case "$level" in
"INFO")
echo -e "${timestamp} ${BLUE}[INFO]${NC} $message" | tee -a "$LOG_FILE"
;;
"SUCCESS")
echo -e "${timestamp} ${GREEN}[SUCCESS]${NC} $message" | tee -a "$LOG_FILE"
;;
"WARNING")
echo -e "${timestamp} ${YELLOW}[WARNING]${NC} $message" | tee -a "$LOG_FILE"
;;
"ERROR")
echo -e "${timestamp} ${RED}[ERROR]${NC} $message" | tee -a "$LOG_FILE"
;;
*)
echo -e "${timestamp} $level $message" | tee -a "$LOG_FILE"
;;
esac
}
# Function to show usage
show_usage() {
echo "Usage: $0 [backup_type] [options]"
echo ""
echo "Backup Types:"
echo " daily - Daily backup (default)"
echo " weekly - Weekly backup"
echo " monthly - Monthly backup"
echo ""
echo "Options:"
echo " --storage-only - Backup only storage files"
echo " --database-only - Backup only database"
echo " --verify - Verify backups after creation"
echo " --notify - Send notification on completion"
echo " --help - Show this help message"
echo ""
exit 0
}
# Health check function
health_check() {
log "INFO" "Starting backup health check"
local status="healthy"
local issues=()
# Check disk space (warn if less than 1GB free)
local available_space=$(df "$BACKUP_ROOT_DIR" | awk 'NR==2 {print $4}')
local available_mb=$((available_space / 1024))
if [ "$available_mb" -lt 1024 ]; then
status="warning"
issues+=("Low disk space: ${available_mb}MB available")
fi
# Check if backup scripts exist and are executable
for script in "backup-database.sh" "backup-storage.sh"; do
if [ ! -x "$SCRIPT_DIR/$script" ]; then
status="error"
issues+=("Script not found or not executable: $script")
fi
done
# Check environment file
if [ ! -f "$PROJECT_ROOT/.env" ]; then
status="error"
issues+=("Environment file (.env) not found")
fi
# Generate health check report
cat > "$HEALTH_CHECK_FILE" <<EOF
{
"timestamp": "$(date -Iseconds)",
"status": "$status",
"available_space_mb": $available_mb,
"issues": [$(printf '"%s",' "${issues[@]}" | sed 's/,$//')],
"backup_directory": "$BACKUP_ROOT_DIR",
"last_check": "$(date)"
}
EOF
if [ "$status" = "error" ]; then
log "ERROR" "Health check failed. Issues found:"
for issue in "${issues[@]}"; do
log "ERROR" " - $issue"
done
return 1
elif [ "$status" = "warning" ]; then
log "WARNING" "Health check completed with warnings:"
for issue in "${issues[@]}"; do
log "WARNING" " - $issue"
done
else
log "SUCCESS" "Health check passed"
fi
return 0
}
# Backup verification function
verify_backups() {
log "INFO" "Verifying recent backups"
local verification_passed=true
# Verify database backups
local latest_db_backup=$(find "$BACKUP_ROOT_DIR/database" -name "*.sql.gz" -type f -mtime -1 | head -n 1)
if [ -n "$latest_db_backup" ]; then
if gzip -t "$latest_db_backup" 2>/dev/null; then
log "SUCCESS" "Database backup verified: $(basename "$latest_db_backup")"
else
log "ERROR" "Database backup verification failed: $(basename "$latest_db_backup")"
verification_passed=false
fi
else
log "WARNING" "No recent database backup found"
fi
# Verify storage backups
local latest_storage_backup=$(find "$BACKUP_ROOT_DIR/storage" -name "*.tar.gz" -type f -mtime -1 | head -n 1)
if [ -n "$latest_storage_backup" ]; then
if tar -tzf "$latest_storage_backup" >/dev/null 2>&1; then
log "SUCCESS" "Storage backup verified: $(basename "$latest_storage_backup")"
else
log "ERROR" "Storage backup verification failed: $(basename "$latest_storage_backup")"
verification_passed=false
fi
else
log "WARNING" "No recent storage backup found"
fi
return $verification_passed
}
# Notification function
send_notification() {
local subject="$1"
local message="$2"
local status="$3"
# Try multiple notification methods
# Method 1: Email (if mail is available and configured)
if command -v mail >/dev/null 2>&1; then
echo "$message" | mail -s "$subject" "${BACKUP_NOTIFY_EMAIL:-$USER@localhost}" 2>/dev/null || true
fi
# Method 2: System notification (if notify-send is available)
if command -v notify-send >/dev/null 2>&1 && [ -n "$DISPLAY" ]; then
notify-send "$subject" "$message" 2>/dev/null || true
fi
# Method 3: Webhook (if BACKUP_WEBHOOK_URL is set)
if [ -n "$BACKUP_WEBHOOK_URL" ] && command -v curl >/dev/null 2>&1; then
curl -X POST "$BACKUP_WEBHOOK_URL" \
-H "Content-Type: application/json" \
-d "{\"subject\":\"$subject\",\"message\":\"$message\",\"status\":\"$status\"}" \
2>/dev/null || true
fi
# Method 4: Log file notification marker
log "INFO" "NOTIFICATION: $subject - $message"
}
# Parse command line arguments
BACKUP_TYPE="daily"
STORAGE_ONLY=false
DATABASE_ONLY=false
VERIFY=false
NOTIFY=false
while [[ $# -gt 0 ]]; do
case $1 in
daily|weekly|monthly)
BACKUP_TYPE="$1"
shift
;;
--storage-only)
STORAGE_ONLY=true
shift
;;
--database-only)
DATABASE_ONLY=true
shift
;;
--verify)
VERIFY=true
shift
;;
--notify)
NOTIFY=true
shift
;;
--help)
show_usage
;;
*)
log "ERROR" "Unknown option: $1"
show_usage
;;
esac
done
# Main execution
main() {
log "INFO" "============================================"
log "INFO" "Starting Timebank $BACKUP_TYPE backup process"
log "INFO" "Time: $(date)"
log "INFO" "============================================"
local start_time=$(date +%s)
local backup_success=true
local status_message=""
# Pre-backup health check
if ! health_check; then
log "ERROR" "Health check failed, aborting backup"
exit 1
fi
# Database backup
if [ "$STORAGE_ONLY" = false ]; then
log "INFO" "Starting database backup..."
if "$SCRIPT_DIR/backup-database.sh" "$BACKUP_TYPE"; then
log "SUCCESS" "Database backup completed"
else
log "ERROR" "Database backup failed"
backup_success=false
fi
fi
# Storage backup
if [ "$DATABASE_ONLY" = false ]; then
log "INFO" "Starting storage backup..."
if "$SCRIPT_DIR/backup-storage.sh" "$BACKUP_TYPE"; then
log "SUCCESS" "Storage backup completed"
else
log "ERROR" "Storage backup failed"
backup_success=false
fi
fi
# Backup verification
if [ "$VERIFY" = true ]; then
if verify_backups; then
log "SUCCESS" "Backup verification passed"
else
log "WARNING" "Backup verification had issues"
fi
fi
# Calculate execution time
local end_time=$(date +%s)
local execution_time=$((end_time - start_time))
local execution_time_formatted=$(date -d@$execution_time -u +%H:%M:%S)
# Generate final status
if [ "$backup_success" = true ]; then
status_message="Backup completed successfully in $execution_time_formatted"
log "SUCCESS" "$status_message"
# Generate backup summary
log "INFO" "Backup Summary:"
log "INFO" " - Type: $BACKUP_TYPE"
log "INFO" " - Duration: $execution_time_formatted"
log "INFO" " - Location: $BACKUP_ROOT_DIR"
if [ "$NOTIFY" = true ]; then
send_notification "Timebank Backup Success" "$status_message" "success"
fi
else
status_message="Backup completed with errors in $execution_time_formatted"
log "ERROR" "$status_message"
if [ "$NOTIFY" = true ]; then
send_notification "Timebank Backup Failed" "$status_message" "error"
fi
exit 1
fi
log "INFO" "============================================"
log "INFO" "Backup process finished"
log "INFO" "============================================"
}
# Trap to handle interrupts
trap 'log "ERROR" "Backup interrupted by user"; exit 1' INT TERM
# Run main function
main "$@"