Phase 4: Implement backup/restore system with PHP-FPM restart capability
NEW LIBRARY: lib/php-config-manager.sh (14 functions, 442 lines)
BACKUP FUNCTIONS:
- initialize_backup_system() - Creates /root/server-toolkit/backups/php/
- backup_php_config() - Backs up single config file with metadata
- backup_fpm_pool() - Backs up PHP-FPM pool configuration
- backup_user_php_configs() - Backs up ALL PHP configs for a user
- list_backups() - Lists all backups with metadata (date, user, domain, file count)
RESTORE FUNCTIONS:
- restore_php_config() - Restores single config file
- restore_from_backup() - Restores entire backup set
- delete_backup() - Removes old backups
CONFIGURATION MODIFICATION:
- modify_fpm_pool_setting() - Changes single FPM pool setting
- modify_php_ini_setting() - Changes single php.ini setting
- apply_fpm_pool_settings() - Applies multiple settings at once
PHP-FPM MANAGEMENT:
- restart_php_fpm() - Restarts PHP-FPM service (systemd/sysvinit)
- reload_php_fpm() - Graceful reload (no downtime)
- verify_php_fpm_running() - Checks if service is active
MENU OPTIONS B & R IMPLEMENTED:
Option B: Backup Current Configurations
- Select domain to backup
- Backs up all php.ini files (priority 1-4)
- Backs up PHP-FPM pool config
- Creates metadata.txt with timestamp, user, domain
- Preserves directory structure
- Shows list of backed up files
- Backup location: /root/server-toolkit/backups/php/YYYYMMDD_HHMMSS/
Option R: Restore from Backup
- Lists all available backups with details
- Shows: backup name, date, username, domain, file count
- Numbered selection menu
- Confirmation prompt: "This will overwrite current configurations!"
- Requires typing "yes" to proceed
- Restores all files with metadata preservation
- Shows success/failure for each file
- Reminder to restart PHP-FPM
BACKUP STRUCTURE:
/root/server-toolkit/backups/php/
├── 20250102_143045/
│ ├── metadata.txt (backup info)
│ ├── opt/cpanel/ea-php82/root/etc/php-fpm.d/username.conf
│ ├── home/username/.php/8.2/php.ini
│ └── home/username/public_html/.user.ini
└── 20250102_150830/
└── ...
SAFETY FEATURES:
- Metadata tracking (who, what, when)
- Confirmation required for restore
- Non-destructive backups (never overwrites backups)
- Timestamp-based naming (no conflicts)
- Preserves file permissions and ownership
FUTURE USE:
These functions will be used by Phase 5 (apply/action menu) to:
1. Auto-backup before applying changes
2. Rollback if changes cause issues
3. Compare current vs backed up configs
This commit is contained in:
@@ -0,0 +1,508 @@
|
||||
#!/bin/bash
|
||||
# PHP Configuration Manager
|
||||
# Handles backup, restore, and modification of PHP configurations
|
||||
# Part of Server Toolkit - Configuration Management
|
||||
|
||||
# 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 <config_file> [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 <username> [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 <username> <domain> [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" <<EOF
|
||||
Backup Created: $(date)
|
||||
Username: $username
|
||||
Domain: $domain
|
||||
Backup Name: $backup_name
|
||||
EOF
|
||||
|
||||
local backed_up_files=()
|
||||
|
||||
# Find and backup all config files
|
||||
local configs
|
||||
configs=$(find_all_php_configs "$username" "$domain")
|
||||
|
||||
while IFS= read -r config; do
|
||||
[ -z "$config" ] && continue
|
||||
[ ! -f "$config" ] && continue
|
||||
|
||||
local backup_path
|
||||
backup_path=$(backup_php_config "$config" "$backup_name")
|
||||
|
||||
if [ $? -eq 0 ]; then
|
||||
backed_up_files+=("$config")
|
||||
echo "Files backed up:" >> "$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")
|
||||
|
||||
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 <backup_path> <original_path>
|
||||
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 <backup_name>
|
||||
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 <backup_name>
|
||||
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 <pool_config_file> <setting> <value>
|
||||
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 <php_ini_file> <setting> <value>
|
||||
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 <pool_config_file> <settings_array>
|
||||
# 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 <php_version>
|
||||
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 <php_version>
|
||||
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 <php_version>
|
||||
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
|
||||
Reference in New Issue
Block a user