#!/bin/bash # PHP Configuration Manager # Handles backup, restore, and modification of PHP configurations # Part of Server Toolkit - Configuration Management # Source required dependencies _LIB_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" source "$_LIB_DIR/php-detector.sh" 2>/dev/null || { echo "ERROR: php-detector.sh not found"; return 1; } # Backup directory BACKUP_DIR="/root/server-toolkit/backups/php" BACKUP_TIMESTAMP=$(date +%Y%m%d_%H%M%S) # ============================================================================ # BACKUP FUNCTIONS # ============================================================================ # Create backup directory structure initialize_backup_system() { mkdir -p "$BACKUP_DIR" if [ ! -d "$BACKUP_DIR" ]; then echo "ERROR: Failed to create backup directory: $BACKUP_DIR" return 1 fi return 0 } # Backup a single PHP configuration file # Usage: backup_php_config [backup_name] backup_php_config() { local config_file="$1" local backup_name="${2:-$BACKUP_TIMESTAMP}" if [ ! -f "$config_file" ]; then echo "ERROR: Config file not found: $config_file" return 1 fi # Create backup subdirectory local backup_subdir="$BACKUP_DIR/$backup_name" mkdir -p "$backup_subdir" # Preserve directory structure local relative_path="${config_file#/}" local backup_path="$backup_subdir/$relative_path" local backup_dir_path=$(dirname "$backup_path") mkdir -p "$backup_dir_path" # Copy with metadata preservation cp -p "$config_file" "$backup_path" if [ $? -eq 0 ]; then echo "$backup_path" return 0 else echo "ERROR: Failed to backup $config_file" return 1 fi } # Backup PHP-FPM pool configuration # Usage: backup_fpm_pool [backup_name] backup_fpm_pool() { local username="$1" local backup_name="${2:-$BACKUP_TIMESTAMP}" # Source php-detector to find pool config local pool_config pool_config=$(find_fpm_pool_config "$username") if [ -z "$pool_config" ] || [ ! -f "$pool_config" ]; then echo "ERROR: FPM pool config not found for $username" return 1 fi backup_php_config "$pool_config" "$backup_name" } # Backup all PHP configs for a user # Usage: backup_user_php_configs [backup_name] backup_user_php_configs() { local username="$1" local domain="$2" local backup_name="${3:-$BACKUP_TIMESTAMP}" initialize_backup_system || return 1 local backup_subdir="$BACKUP_DIR/$backup_name" mkdir -p "$backup_subdir" # Create backup metadata cat > "$backup_subdir/metadata.txt" <> "$backup_subdir/metadata.txt" echo " $config → $backup_path" >> "$backup_subdir/metadata.txt" fi done <<< "$configs" # Backup FPM pool config local pool_config pool_config=$(find_fpm_pool_config "$username" "$domain") if [ -n "$pool_config" ] && [ -f "$pool_config" ]; then local backup_path backup_path=$(backup_php_config "$pool_config" "$backup_name") if [ $? -eq 0 ]; then backed_up_files+=("$pool_config") echo " $pool_config → $backup_path" >> "$backup_subdir/metadata.txt" fi fi # Return backup location if [ ${#backed_up_files[@]} -gt 0 ]; then echo "$backup_subdir" return 0 else echo "ERROR: No files backed up" return 1 fi } # List all backups # Usage: list_backups list_backups() { if [ ! -d "$BACKUP_DIR" ]; then echo "No backups found" return 1 fi local backups backups=$(find "$BACKUP_DIR" -mindepth 1 -maxdepth 1 -type d -name "2*" | sort -r) if [ -z "$backups" ]; then echo "No backups found" return 1 fi echo "BACKUP_NAME|DATE|USERNAME|DOMAIN|FILE_COUNT" while IFS= read -r backup_dir; do local backup_name=$(basename "$backup_dir") local metadata_file="$backup_dir/metadata.txt" if [ -f "$metadata_file" ]; then local created=$(grep "^Backup Created:" "$metadata_file" | cut -d: -f2- | xargs) local username=$(grep "^Username:" "$metadata_file" | cut -d: -f2 | xargs) local domain=$(grep "^Domain:" "$metadata_file" | cut -d: -f2 | xargs) local file_count=$(find "$backup_dir" -type f ! -name "metadata.txt" | wc -l) echo "$backup_name|$created|$username|$domain|$file_count" else local file_count=$(find "$backup_dir" -type f | wc -l) echo "$backup_name|Unknown|Unknown|Unknown|$file_count" fi done <<< "$backups" } # ============================================================================ # RESTORE FUNCTIONS # ============================================================================ # Restore a single configuration file # Usage: restore_php_config restore_php_config() { local backup_path="$1" local original_path="$2" if [ ! -f "$backup_path" ]; then echo "ERROR: Backup file not found: $backup_path" return 1 fi # Create directory if needed local original_dir=$(dirname "$original_path") mkdir -p "$original_dir" # Restore with metadata preservation cp -p "$backup_path" "$original_path" if [ $? -eq 0 ]; then echo "Restored: $original_path" return 0 else echo "ERROR: Failed to restore $original_path" return 1 fi } # Restore from backup # Usage: restore_from_backup restore_from_backup() { local backup_name="$1" local backup_dir="$BACKUP_DIR/$backup_name" if [ ! -d "$backup_dir" ]; then echo "ERROR: Backup not found: $backup_name" return 1 fi # Read metadata local metadata_file="$backup_dir/metadata.txt" if [ ! -f "$metadata_file" ]; then echo "ERROR: Backup metadata not found" return 1 fi echo "Restoring from backup: $backup_name" cat "$metadata_file" echo "" # Find all backed up files (excluding metadata) local restored_count=0 local failed_count=0 while IFS= read -r backup_file; do # Extract original path from backup structure local relative_path="${backup_file#$backup_dir/}" local original_path="/$relative_path" if restore_php_config "$backup_file" "$original_path"; then restored_count=$((restored_count + 1)) else failed_count=$((failed_count + 1)) fi done < <(find "$backup_dir" -type f ! -name "metadata.txt") echo "" echo "Restore complete: $restored_count files restored, $failed_count failed" if [ "$failed_count" -eq 0 ]; then return 0 else return 1 fi } # Delete a backup # Usage: delete_backup delete_backup() { local backup_name="$1" local backup_dir="$BACKUP_DIR/$backup_name" if [ ! -d "$backup_dir" ]; then echo "ERROR: Backup not found: $backup_name" return 1 fi rm -rf "$backup_dir" if [ $? -eq 0 ]; then echo "Backup deleted: $backup_name" return 0 else echo "ERROR: Failed to delete backup" return 1 fi } # ============================================================================ # CONFIGURATION MODIFICATION FUNCTIONS # ============================================================================ # Modify a PHP-FPM pool setting # Usage: modify_fpm_pool_setting modify_fpm_pool_setting() { local pool_config="$1" local setting="$2" local value="$3" if [ ! -f "$pool_config" ]; then echo "ERROR: Pool config not found: $pool_config" return 1 fi # Check if setting exists if grep -q "^${setting}\s*=" "$pool_config"; then # Replace existing value sed -i "s|^${setting}\s*=.*|${setting} = ${value}|" "$pool_config" elif grep -q "^;${setting}\s*=" "$pool_config"; then # Uncomment and set value sed -i "s|^;${setting}\s*=.*|${setting} = ${value}|" "$pool_config" else # Add new setting at end of file echo "${setting} = ${value}" >> "$pool_config" fi if [ $? -eq 0 ]; then echo "Modified: $setting = $value in $pool_config" return 0 else echo "ERROR: Failed to modify $setting" return 1 fi } # Modify a php.ini setting # Usage: modify_php_ini_setting modify_php_ini_setting() { local php_ini="$1" local setting="$2" local value="$3" if [ ! -f "$php_ini" ]; then echo "ERROR: php.ini not found: $php_ini" return 1 fi # Check if setting exists if grep -q "^${setting}\s*=" "$php_ini"; then # Replace existing value sed -i "s|^${setting}\s*=.*|${setting} = ${value}|" "$php_ini" elif grep -q "^;${setting}\s*=" "$php_ini"; then # Uncomment and set value sed -i "s|^;${setting}\s*=.*|${setting} = ${value}|" "$php_ini" else # Add new setting at end of file echo "${setting} = ${value}" >> "$php_ini" fi if [ $? -eq 0 ]; then echo "Modified: $setting = $value in $php_ini" return 0 else echo "ERROR: Failed to modify $setting" return 1 fi } # Apply multiple FPM pool settings # Usage: apply_fpm_pool_settings # settings_array format: "setting1=value1" "setting2=value2" ... apply_fpm_pool_settings() { local pool_config="$1" shift local settings=("$@") local success_count=0 local failed_count=0 for setting_value in "${settings[@]}"; do local setting="${setting_value%%=*}" local value="${setting_value#*=}" if modify_fpm_pool_setting "$pool_config" "$setting" "$value"; then success_count=$((success_count + 1)) else failed_count=$((failed_count + 1)) fi done echo "Applied: $success_count settings, $failed_count failed" if [ "$failed_count" -eq 0 ]; then return 0 else return 1 fi } # ============================================================================ # PHP-FPM RESTART FUNCTIONS # ============================================================================ # Restart PHP-FPM service # Usage: restart_php_fpm restart_php_fpm() { local php_version="$1" # e.g., "ea-php82" or "82" # Normalize version format if [[ ! "$php_version" =~ ^ea-php ]]; then php_version="ea-php${php_version}" fi # Detect init system if command -v systemctl >/dev/null 2>&1; then # systemd local service_name="${php_version}-php-fpm" systemctl restart "$service_name" 2>/dev/null if [ $? -eq 0 ]; then echo "Restarted: $service_name (systemd)" return 0 else echo "ERROR: Failed to restart $service_name" return 1 fi elif command -v service >/dev/null 2>&1; then # sysvinit local service_name="${php_version}-php-fpm" service "$service_name" restart 2>/dev/null if [ $? -eq 0 ]; then echo "Restarted: $service_name (service)" return 0 else echo "ERROR: Failed to restart $service_name" return 1 fi else echo "ERROR: Cannot detect init system" return 1 fi } # Reload PHP-FPM service (graceful restart) # Usage: reload_php_fpm reload_php_fpm() { local php_version="$1" # Normalize version format if [[ ! "$php_version" =~ ^ea-php ]]; then php_version="ea-php${php_version}" fi # Detect init system if command -v systemctl >/dev/null 2>&1; then # systemd local service_name="${php_version}-php-fpm" systemctl reload "$service_name" 2>/dev/null if [ $? -eq 0 ]; then echo "Reloaded: $service_name (graceful)" return 0 else # Fallback to restart if reload fails restart_php_fpm "$php_version" return $? fi else # Reload not supported, use restart restart_php_fpm "$php_version" return $? fi } # Verify PHP-FPM is running # Usage: verify_php_fpm_running verify_php_fpm_running() { local php_version="$1" # Normalize version format if [[ ! "$php_version" =~ ^ea-php ]]; then php_version="ea-php${php_version}" fi if command -v systemctl >/dev/null 2>&1; then local service_name="${php_version}-php-fpm" systemctl is-active "$service_name" >/dev/null 2>&1 if [ $? -eq 0 ]; then echo "Running: $service_name" return 0 else echo "NOT running: $service_name" return 1 fi else # Check process if pgrep -f "${php_version}-php-fpm" >/dev/null 2>&1; then echo "Running: ${php_version}-php-fpm" return 0 else echo "NOT running: ${php_version}-php-fpm" return 1 fi fi } # Export all functions export -f initialize_backup_system export -f backup_php_config export -f backup_fpm_pool export -f backup_user_php_configs export -f list_backups export -f restore_php_config export -f restore_from_backup export -f delete_backup export -f modify_fpm_pool_setting export -f modify_php_ini_setting export -f apply_fpm_pool_settings export -f restart_php_fpm export -f reload_php_fpm export -f verify_php_fpm_running