Initial commit
This commit is contained in:
324
scripts/backup-all.sh
Executable file
324
scripts/backup-all.sh
Executable file
@@ -0,0 +1,324 @@
|
||||
#!/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 "$@"
|
||||
Reference in New Issue
Block a user