D7net
Home
Console
Upload
information
Create File
Create Folder
About
Tools
:
/
opt
/
dedrads
/
Filename :
migrate2central.sh
back
Copy
#!/bin/bash set -e ARCHIVE_FILE="" DB_IMPORT_FILE="" DEBUG=false REVERT=false DOC_ROOT="doc_root" BACKUP_DIR="${DOC_ROOT}.bak" DB_BACKUP_FILE="backup_db.sql" TEMP_DIR="temp_extraction" LOG_FILE="migration_debug.log" # Options directory, contains central_connect, bg_connect_configs, boldgrid_api_key OPTIONS_DIR="options_backup" TABLE_PREFIX="" WP_ROOT="" DB_PASS="" WP_OPTIONS=("bg_connect_configs" "central_connect" "boldgrid_api_key") # Color codes RED='\033[1;31m' GREEN='\033[1;32m' YELLOW='\033[0;33m' BLUE='\033[1;34m' NC='\033[0m' # No Color # Logging functions log() { local level="$1" local color="$2" local message="$3" # Print to terminal with color echo -e "${color}[${level}] ${message}${NC}" # Log to file if debug is enabled if [ "$DEBUG" = true ]; then echo -e "\n[$(date '+%F %T ET')] [${level}] ${message}" >>"$LOG_FILE" fi } log_error() { log "ERROR" "$RED" "$1"; } log_info() { log "INFO" "$BLUE" "$1"; } log_warning() { log "WARNING" "$YELLOW" "$1"; } log_success() { log "SUCCESS" "$GREEN" "$1"; } # Function to enable debug mode enable_debug() { readonly DEBUG=true touch "$LOG_FILE" log_info "Debug mode enabled. Logging to $LOG_FILE" } # Parse command-line arguments parse_args() { while (("$#")); do case "$1" in --debug) enable_debug shift ;; --revert) REVERT=true shift ;; --help | -h) display_help exit 0 ;; *) if [ -z "$ARCHIVE_FILE" ]; then ARCHIVE_FILE="$1" elif [ -z "$DB_IMPORT_FILE" ]; then DB_IMPORT_FILE="$1" else log_error "Unexpected argument: $1" display_help exit 1 fi shift ;; esac done } # Function to revert changes revert_to_backup() { if [ ! -d "$BACKUP_DIR" ]; then log_error "Backup directory ${BACKUP_DIR} does not exist" exit 1 fi log_info "Reverting..." if { find "$DOC_ROOT" -delete 2>/dev/null mv "$BACKUP_DIR" "$DOC_ROOT" || echo "Failed to move document root." wp --path="$DOC_ROOT" db reset --yes || echo "Failed to reset database." wp --path="$DOC_ROOT" db import "${DOC_ROOT}/${DB_BACKUP_FILE}" || echo "Failed to import database." wp --path="$DOC_ROOT" cache flush || echo "Failed to import database." redis-cli flushall || echo "Failed to import database." }; then log_success "Reverted successfully" else log_error "Failed to revert" fi } #### Helper Functions #### # Function to export a WordPress option to a JSON file export_wp_option() { # Export the WordPress option to a JSON file if ! wp --path="$BACKUP_DIR" --skip-plugins --skip-themes --format=json option get "$1" >"${OPTIONS_DIR}/${1}.json" 2>>"$LOG_FILE"; then log_warning "Failed to export $1" return 1 fi } # Function to import a WordPress option from a JSON file import_wp_option() { local option_name option_file option_name="$1" option_file="${OPTIONS_DIR}/${option_name}.json" # Check if the JSON file exists if [ ! -f "$option_file" ]; then log_warning "Option file ${option_file} does not exist" return 1 fi # Import the WordPress option from the JSON file if ! wp --path="$DOC_ROOT" option update "$option_name" --format=json <"$option_file" >>"$LOG_FILE" 2>&1; then log_warning "Failed to import ${option_name}, skipping..." fi } # Function to run search and replace on the database run_search_replace() { from_url="$1" to_url="$2" log_info "Running search-replace for $from_url to $to_url..." if ! SHELL_PIPE=0 wp --path="$DOC_ROOT" search-replace --skip-plugins --skip-themes --report-changed-only --all-tables "$from_url" "$to_url" >>"$LOG_FILE" 2>&1; then log_error "Failed to run search-replace for '$from_url' to '$to_url'" exit 1 fi } #### END Helper Functions #### #### Main Functions #### # Function to remove the temporary directory to prevent 'more than 1 WordPress installation beging found, please review the paths.' # This can happen if the script is run multiple times without cleaning up the temporary directory remove_temp_dir() { log_info "Removing temporary directory $TEMP_DIR if it exists" if [ -d "$TEMP_DIR" ]; then find "$TEMP_DIR" -delete 2>/dev/null fi } # Function to backup the document root and database backup_document_root_and_database() { if [ ! -d "$BACKUP_DIR" ]; then log_info "Backing up $DOC_ROOT to $BACKUP_DIR..." if ! cp -r "$DOC_ROOT" "$BACKUP_DIR"; then log_error "Failed to backup the original document root" exit 1 else log_info "Backed up $DOC_ROOT to $BACKUP_DIR" fi # Backup the database if it does not exist if [ ! -f "${BACKUP_DIR}/${DB_BACKUP_FILE}" ]; then log_info "Backing up current database..." if ! wp --path="$BACKUP_DIR" db export "${BACKUP_DIR}/${DB_BACKUP_FILE}"; then log_warning "Unable to backup the local database ... skipping backup" fi fi fi } # Function to extract the archive extract_archive() { if [ ! -f "$ARCHIVE_FILE" ]; then log_error "The specified archive file '$ARCHIVE_FILE' does not exist" exit 1 fi log_info "Extracting $ARCHIVE_FILE..." mkdir -p "$TEMP_DIR" case "$ARCHIVE_FILE" in *.zip) unzip -oq "$ARCHIVE_FILE" -d "$TEMP_DIR" ;; *.tar) tar -xf "$ARCHIVE_FILE" -C "$TEMP_DIR" ;; *.tar.gz | *.tgz) tar -xzf "$ARCHIVE_FILE" -C "$TEMP_DIR" ;; *) log_error "Unsupported file type: $ARCHIVE_FILE" exit 1 ;; esac } # Function to export specified WordPress options export_central_options() { log_info "Exporting original WordPress options..." mkdir -p "$OPTIONS_DIR" export_failed=false for option in "${WP_OPTIONS[@]}"; do if ! export_wp_option "$option"; then export_failed=true fi done } # Function to find the WordPress directory in the extracted archive or extracted directory specified find_wp_directory() { # Find the WordPress directory in the extracted archive or extracted directory specified WP_ROOT=$(find "$TEMP_DIR" -maxdepth 10 \( -path "*/wp-content" -o -path "*/uploads" \) -prune -o -path "*/wp-includes/version.php" -type f -exec sh -c 'dirname "$(dirname "$1")"' _ {} \;) # Count the number of times path wp-includes/wp-config.php was found WP_COUNT=$(echo "$WP_ROOT" | wc -l) # If more than one wp-includes/version.php is found provide errors and paths if [ "$WP_COUNT" -gt 1 ]; then log_error "Error: More than 1 WordPress installation found, please review the paths." log_info "Paths:\n${WP_ROOT}" exit 1 fi # Check if the WordPress directory is found if [ -z "$WP_ROOT" ]; then log_error "Could not detect a wordpress installation" exit 1 fi } # Function to sync the new document root with the existing one sync_document_root() { log_info "Syncing new document root from $WP_ROOT to $DOC_ROOT..." find "${DOC_ROOT}" -delete rsync -a --exclude wp-config.php "$WP_ROOT/" "$DOC_ROOT/" log_info "Synced ${WP_ROOT}/ to ${DOC_ROOT}/" } # Function to get the table prefix from the WordPress configuration get_table_prefix() { log_info "Getting table prefix from the WordPress configuration..." # Get the table prefix from the WordPress configuration TABLE_PREFIX=$(wp --path="$WP_ROOT" config get table_prefix) # Check if the table prefix is empty if [ -z "$TABLE_PREFIX" ]; then log_error "Failed to get table prefix from the WordPress configuration" exit 1 fi log_info "Table prefix is: ${TABLE_PREFIX}" } # Function to create the WordPress configuration create_wp_config() { local pass log_info "Creating WordPress configuration..." # Get the database password from the wp-config.php file pass="$(wp --path="$BACKUP_DIR" config get DB_PASSWORD)" if [ -z "$pass" ]; then log_warning "Failed to get database password using wp-cli, falling back to grep" pass=$(grep -E "DB_PASSWORD" "$BACKUP_DIR/wp-config.php" | cut -d \' -f 4) fi if [ -z "$pass" ]; then log_warning "Failed to get database password from the wp-config.php file using grep" fi DB_PASS="$pass" # Create the WordPress configuration if ! wp --path="$DOC_ROOT" config create \ --dbname=wordpress \ --dbuser=wordpress \ --dbpass="$pass" \ --dbhost='localhost:/var/lib/mysql/mysql.sock' \ --dbcharset=utf8 \ --dbprefix="${TABLE_PREFIX}_" \ --config-file="${DOC_ROOT}/wp-config.php" \ --force \ >>"$LOG_FILE" 2>&1; then log_error "Failed to create WordPress configuration" exit 1 fi if ! wp --path="$DOC_ROOT" config set "RT_WP_NGINX_HELPER_CACHE_PATH" "/var/nginx/cache/sitecache" >>"$LOG_FILE" 2>&1; then log_error "Failed to set RT_WP_NGINX_HELPER_CACHE_PATH" exit 1 fi } # Function to reset the database reset_database() { log_info "Resetting database..." if ! wp --path="$BACKUP_DIR" db reset --yes >>"$LOG_FILE" 2>&1; then log_error "Failed to reset database" exit 1 fi } # Function to import the database from the database file import_database() { if [ -f "$DB_IMPORT_FILE" ]; then log_info "Importing database from $DB_IMPORT_FILE..." if ! sed 's/utf8mb4_0900_ai_ci/utf8mb4_unicode_ci/g' "$DB_IMPORT_FILE" | wp --path="$DOC_ROOT" --skip-plugins --skip-themes db import - >>"$LOG_FILE" 2>&1; then log_warning "Failed to import database from $DB_IMPORT_FILE using wp-cli, falling back to mysql command" # fallback to mysql command if ! sed 's/utf8mb4_0900_ai_ci/utf8mb4_unicode_ci/g' "$DB_IMPORT_FILE" | mysql -u wordpress wordpress -p"$DB_PASS"; then log_error "Failed to import database from $DB_IMPORT_FILE" exit 1 fi fi else log_error "Unable to import database from $DB_IMPORT_FILE, does it exist?" exit 1 fi } # Function to import specified WordPress options import_central_options() { if [ "$export_failed" = false ]; then log_info "Restoring original WordPress options..." for option in "${WP_OPTIONS[@]}"; do import_wp_option "$option" done else log_warning "Option export failed; skipping import" fi } # Function to install and activate the Central Connect plugin activate_central_connect() { log_info "Installing and activating Central Connect plugin..." if ! wp --path="$DOC_ROOT" plugin install central-connect >>"$LOG_FILE" 2>&1; then log_warning "Failed to install Central Connect plugin" fi if ! wp --path="$DOC_ROOT" plugin activate central-connect >>"$LOG_FILE" 2>&1; then log_warning "Failed to activate Central Connect plugin" fi } # Function to remove proprietary plugins remove_proprietary_plugins() { log_info "Removing proprietary plugins..." if [ -d "$DOC_ROOT/wp-content/mu-plugins" ]; then find "$DOC_ROOT/wp-content/mu-plugins" -mindepth 1 -delete log_info "Removed mu-plugins" fi if [ -d "$DOC_ROOT/wp-content/drop-ins/wp-cache-memcached" ]; then \rm -rf "$DOC_ROOT/wp-content/drop-ins/wp-cache-memcached" log_info "Removed wp-cache-memcached" fi } # Function to perform search and replace on the database perform_search_replace() { local site_url log_info "Performing search and replace..." site_url="$(wp --path=$DOC_ROOT option get siteurl --skip-plugins --skip-themes)" site_url=$(echo "$site_url" | awk -F'//' '{print $2}') if [ -z "$site_url" ]; then log_error "Failed to get site URL from the database" exit 1 fi # Run search and replace for http and https run_search_replace "http://${site_url}" "https://$(hostname)" run_search_replace "https://${site_url}" "https://$(hostname)" } # Function to flush the caches flush_caches() { log_info "Flushing caches..." if ! wp --path=$DOC_ROOT cache flush >>"$LOG_FILE" 2>&1; then log_warning "Failed to flush cache" fi if ! redis-cli flushall >>"$LOG_FILE" 2>&1; then log_warning "Failed to flush Redis cache" fi } # Function to fix permissions fix_permissions() { log_info "Fixing permissions..." fixperms wordpress } #### END Main Functions #### # Function to display help message display_help() { cat <<EOF Usage: $(basename "$0") [COMPRESSED FILE|DIRECTORY] [SQL_FILE] [--debug] [--revert] [--help|-h] Arguments: COMPRESSED FILE|DIRECTORY - The path to the compressed archive file or directory containing the WordPress site. SQL_FILE - The path to the SQL file for database import. Options: --debug - Enables debug mode, logging detailed information to a log file. --revert - Reverts the changes made by the script and restores from backup. --help, -h - Displays this help message. EOF } # Main function main() { # Exit immediately if not Platform i VPS if [ ! -f "/etc/ansible/wordpress-ultrastack" ]; then log_error "This script can only be ran on a Platform i VPS" exit 1 fi parse_args "$@" # If revert flag is set, revert changes and exit if [ "$REVERT" = true ]; then revert_to_backup exit 0 fi # Display help if no archive file/directory to extract is provided if [ -z "$ARCHIVE_FILE" ]; then display_help exit 1 fi # Check if document root exists and is a directory if [ ! -d "$DOC_ROOT" ]; then log_error "The specified document root '$DOC_ROOT' does not exist or is not a directory" exit 1 fi if [ ! -f "$ARCHIVE_FILE" ] && [ ! -d "$ARCHIVE_FILE" ]; then log_error "The specified archive file or directory '$ARCHIVE_FILE' does not exist" exit 1 fi # Check if the database import file exists and set it to empty if it is not if [ -n "$DB_IMPORT_FILE" ] && [ ! -f "$DB_IMPORT_FILE" ]; then log_error "The specified database import file '$DB_IMPORT_FILE' does not exist" exit 1 fi # Remove the temporary directory remove_temp_dir # Backup the document root and database backup_document_root_and_database # Checks if the first argument is a directory or an archive file and handles it accordingly. if [ -d "$ARCHIVE_FILE" ]; then TEMP_DIR="$ARCHIVE_FILE" log_info "Using existing directory $TEMP_DIR" else log_info "Using archive file $ARCHIVE_FILE" extract_archive "$ARCHIVE_FILE" fi export_central_options find_wp_directory sync_document_root get_table_prefix create_wp_config reset_database import_database import_central_options activate_central_connect remove_proprietary_plugins perform_search_replace flush_caches fix_permissions log_success "Migration completed successfully" } main "$@"