mirror of
https://hk.gh-proxy.com/https://github.com/CaptainCore/do.git
synced 2025-10-03 23:34:10 +08:00
209 lines
10 KiB
Bash
209 lines
10 KiB
Bash
# ----------------------------------------------------
|
|
# Performs a WordPress database-only backup to a secure, private directory.
|
|
# ----------------------------------------------------
|
|
function db_backup() {
|
|
echo "Starting database-only backup..."
|
|
local home_directory; home_directory=$(pwd);
|
|
local private_directory
|
|
if ! private_directory=$(_get_private_dir); then
|
|
return 1
|
|
fi
|
|
if ! setup_wp_cli; then echo "Error: wp-cli is not installed." >&2; return 1; fi
|
|
local database_name; database_name=$("$WP_CLI_CMD" config get DB_NAME --skip-plugins --skip-themes --quiet); local database_username; database_username=$("$WP_CLI_CMD" config get DB_USER --skip-plugins --skip-themes --quiet); local database_password; database_password=$("$WP_CLI_CMD" config get DB_PASSWORD --skip-plugins --skip-themes --quiet);
|
|
local dump_command; if command -v mariadb-dump &> /dev/null; then dump_command="mariadb-dump"; elif command -v mysqldump &> /dev/null; then dump_command="mysqldump"; else echo "Error: Neither mariadb-dump nor mysqldump could be found." >&2; return 1; fi
|
|
echo "Using ${dump_command} for the backup."
|
|
local backup_file="${private_directory}/database-backup-$(date +"%Y-%m-%d").sql"
|
|
if ! "${dump_command}" -u"${database_username}" -p"${database_password}" --max_allowed_packet=512M --default-character-set=utf8mb4 --add-drop-table --single-transaction --quick --lock-tables=false "${database_name}" > "${backup_file}"; then echo "Error: Database dump failed." >&2; rm -f "${backup_file}"; return 1; fi
|
|
chmod 600 "${backup_file}"; echo "✅ Database backup complete!"; echo " Backup file located at: ${backup_file}"
|
|
}
|
|
|
|
# ----------------------------------------------------
|
|
# Checks the size and contents of autoloaded options in the WordPress database.
|
|
# ----------------------------------------------------
|
|
function db_check_autoload() {
|
|
echo "Checking autoloaded options in the database..."
|
|
# Ensure the 'gum' utility is available for formatting
|
|
if ! setup_gum; then
|
|
echo "Aborting check: gum setup failed." >&2
|
|
return 1
|
|
fi
|
|
if ! setup_wp_cli; then echo "Error: wp-cli is not installed." >&2; return 1; fi
|
|
if ! "$WP_CLI_CMD" core is-installed --quiet; then echo "Error: This does not appear to be a WordPress installation." >&2; return 1; fi
|
|
|
|
echo
|
|
echo "--- Total Autoloaded Size ---"
|
|
"$WP_CLI_CMD" db query "SELECT ROUND(SUM(LENGTH(option_value))/1024/1024, 2) as 'Autoload MB', COUNT(*) as 'Count' FROM $($WP_CLI_CMD db prefix)options WHERE autoload IN ('yes', 'on');" | "$GUM_CMD" table --print --separator $'\t'
|
|
echo
|
|
echo "--- Top 25 Autoloaded Options & Totals ---"
|
|
"$WP_CLI_CMD" db query "SELECT option_name, round(length(option_value) / 1024 / 1024, 2) as 'Size (MB)' FROM $($WP_CLI_CMD db prefix)options WHERE autoload IN ('yes', 'on') ORDER BY length(option_value) DESC LIMIT 25" | "$GUM_CMD" table --print --separator $'\t'
|
|
echo
|
|
echo "✅ Autoload check complete."
|
|
}
|
|
|
|
# ----------------------------------------------------
|
|
# Optimizes the database by converting tables to InnoDB, reporting large tables, and cleaning transients.
|
|
# ----------------------------------------------------
|
|
function db_optimize() {
|
|
# --- Pre-flight checks ---
|
|
if ! setup_gum; then
|
|
echo "Aborting optimization: gum setup failed." >&2
|
|
return 1
|
|
fi
|
|
if ! setup_wp_cli; then echo "Error: WP-CLI not found." >&2; return 1; fi
|
|
if ! "$WP_CLI_CMD" core is-installed --quiet; then echo "Error: This does not appear to be a WordPress installation." >&2; return 1; fi
|
|
|
|
echo "🚀 Starting database optimization..."
|
|
echo ""
|
|
|
|
# --- Step 1: Convert MyISAM to InnoDB ---
|
|
echo "--- Step 1: Checking for MyISAM tables to convert to InnoDB ---"
|
|
local myisam_tables
|
|
myisam_tables=$("$WP_CLI_CMD" db query "SELECT TABLE_NAME FROM information_schema.TABLES WHERE ENGINE = 'MyISAM' AND TABLE_SCHEMA = DATABASE()" --skip-column-names)
|
|
|
|
if [[ -z "$myisam_tables" ]]; then
|
|
echo "✅ All tables are already using the InnoDB engine. No conversion needed."
|
|
else
|
|
echo "Found the following MyISAM tables to convert:"
|
|
# Use gum to format the list of tables
|
|
"$WP_CLI_CMD" db query "SELECT TABLE_NAME AS 'MyISAM Tables' FROM information_schema.TABLES WHERE ENGINE = 'MyISAM' AND TABLE_SCHEMA = DATABASE()" | "$GUM_CMD" table --print --separator $'\t'
|
|
|
|
echo "Converting tables to InnoDB..."
|
|
"$WP_CLI_CMD" db query "SELECT CONCAT('ALTER TABLE \`', TABLE_NAME, '\` ENGINE=InnoDB;') FROM information_schema.TABLES WHERE ENGINE = 'MyISAM' AND TABLE_SCHEMA = DATABASE()" --skip-column-names | "$WP_CLI_CMD" db query
|
|
|
|
if [ $? -eq 0 ]; then
|
|
echo "✅ Successfully converted tables to InnoDB."
|
|
else
|
|
echo "❌ An error occurred during the conversion."
|
|
return 1
|
|
fi
|
|
fi
|
|
|
|
# --- Step 2: List Top 10 Largest Tables ---
|
|
echo ""
|
|
echo "--- Step 2: Top 10 Tables Larger Than 1MB ---"
|
|
# Use gum to format the table of large tables
|
|
"$WP_CLI_CMD" db query "
|
|
SELECT
|
|
TABLE_NAME,
|
|
CASE
|
|
WHEN (data_length + index_length) >= 1073741824 THEN CONCAT(ROUND((data_length + index_length) / 1073741824, 2), ' GB')
|
|
WHEN (data_length + index_length) >= 1048576 THEN CONCAT(ROUND((data_length + index_length) / 1048576, 2), ' MB')
|
|
WHEN (data_length + index_length) >= 1024 THEN CONCAT(ROUND((data_length + index_length) / 1024, 2), ' KB')
|
|
ELSE CONCAT((data_length + index_length), ' B')
|
|
END AS Size
|
|
FROM
|
|
information_schema.TABLES
|
|
WHERE
|
|
TABLE_SCHEMA = DATABASE() AND (data_length + index_length) > 1048576
|
|
ORDER BY
|
|
(data_length + index_length) DESC
|
|
LIMIT 10;
|
|
" | "$GUM_CMD" table --print --separator $'\t'
|
|
|
|
# --- Step 3: Delete Expired Transients ---
|
|
echo ""
|
|
echo "--- Step 3: Deleting Expired Transients ---"
|
|
"$WP_CLI_CMD" transient delete --expired
|
|
|
|
echo ""
|
|
echo "✅ Database optimization complete."
|
|
}
|
|
|
|
# ----------------------------------------------------
|
|
# Changes the database table prefix for a WordPress installation.
|
|
# ----------------------------------------------------
|
|
function db_change_prefix() {
|
|
echo "🚀 Starting Database Prefix Change 🚀"
|
|
|
|
# --- Pre-flight Checks ---
|
|
if ! setup_wp_cli; then echo "❌ Error: WP-CLI not found." >&2; return 1; fi
|
|
if ! "$WP_CLI_CMD" core is-installed --quiet; then echo "❌ Error: This does not appear to be a WordPress installation." >&2; return 1; fi
|
|
if ! setup_gum; then echo "❌ Error: gum is required for interactive prompts." >&2; return 1; fi
|
|
if ! command -v sed &>/dev/null; then echo "❌ Error: sed command not found." >&2; return 1; fi
|
|
|
|
# --- Get Current and New Prefix ---
|
|
local db_prefix
|
|
db_prefix=$("$WP_CLI_CMD" db prefix)
|
|
echo "Current database prefix is: $db_prefix"
|
|
|
|
local random_string
|
|
# Use a more portable random string generator to avoid locale issues.
|
|
if command -v openssl &>/dev/null; then
|
|
random_string=$(openssl rand -hex 3) # 6 hex characters
|
|
elif command -v md5sum &>/dev/null; then
|
|
random_string=$(date +%s | md5sum | head -c 5)
|
|
elif command -v sha1sum &>/dev/null; then
|
|
random_string=$(date +%s | sha1sum | head -c 5)
|
|
else
|
|
# A simpler fallback if no hashing tool is found
|
|
random_string=$(date +%s | cut -c 6-10) # last 5 digits of timestamp
|
|
fi
|
|
local db_prefix_new
|
|
db_prefix_new=$("$GUM_CMD" input --value="wp_${random_string}_" --prompt="Enter the new database prefix: ")
|
|
|
|
if [ -z "$db_prefix_new" ]; then
|
|
echo "❌ No new prefix entered. Aborting."
|
|
return 1
|
|
fi
|
|
|
|
if [ "$db_prefix" == "$db_prefix_new" ]; then
|
|
echo "❌ The new prefix is the same as the current prefix. Aborting."
|
|
return 1
|
|
fi
|
|
|
|
echo "You are about to change the database prefix from '${db_prefix}' to '${db_prefix_new}'."
|
|
"$GUM_CMD" confirm "This is a potentially destructive operation. Are you sure you want to continue?" || { echo "Operation cancelled."; return 0; }
|
|
|
|
# --- Backup Database ---
|
|
local private_dir
|
|
if ! private_dir=$(_get_private_dir); then
|
|
return 1
|
|
fi
|
|
local db_file="${private_dir}/prefix-change-backup-$(date +"%Y-%m-%d-%H%M%S").sql"
|
|
echo "Step 1/5: Backing up database to a temporary file..."
|
|
if ! "$WP_CLI_CMD" db export "$db_file" --add-drop-table; then
|
|
echo "❌ Error: Failed to create database backup. Aborting."
|
|
return 1
|
|
fi
|
|
echo "✅ Database backup created at: $db_file"
|
|
|
|
# --- Modify SQL File ---
|
|
echo "Step 2/5: Modifying the database backup with the new prefix..."
|
|
# The -i flag for sed behaves differently on macOS/BSD vs Linux.
|
|
# Providing a backup extension (e.g., -i.bak) makes it work on both.
|
|
sed -i.bak "s#\`${db_prefix}#\`${db_prefix_new}#g" "$db_file"
|
|
sed -i.bak "s#'${db_prefix}user_roles#'${db_prefix_new}user_roles#g" "$db_file"
|
|
sed -i.bak "s#'${db_prefix}capabilities#'${db_prefix_new}capabilities#g" "$db_file"
|
|
sed -i.bak "s#'${db_prefix}user_level#'${db_prefix_new}user_level#g" "$db_file"
|
|
echo "✅ SQL file modified."
|
|
|
|
# --- Reset and Import ---
|
|
echo "Step 3/5: Resetting the database (dropping all tables)..."
|
|
"$WP_CLI_CMD" db reset --yes
|
|
|
|
echo "Step 4/5: Importing the modified database..."
|
|
if ! "$WP_CLI_CMD" db import "$db_file"; then
|
|
echo "❌ Error: Failed to import the modified database."
|
|
echo " Your original database is backed up at: $db_file"
|
|
echo " You may need to manually restore it."
|
|
# Clean up the .bak file
|
|
rm -f "${db_file}.bak"
|
|
return 1
|
|
fi
|
|
echo "✅ Database imported successfully."
|
|
# Clean up the .bak file created by sed
|
|
rm -f "${db_file}.bak"
|
|
|
|
# --- Update wp-config.php ---
|
|
echo "Step 5/5: Updating wp-config.php with the new prefix..."
|
|
if ! "$WP_CLI_CMD" config set table_prefix "$db_prefix_new" --skip-plugins --skip-themes; then
|
|
echo "❌ Error: Failed to update the table_prefix in your wp-config.php file."
|
|
echo " Please update it manually to: \$table_prefix = '$db_prefix_new';"
|
|
return 1
|
|
fi
|
|
echo "✅ wp-config.php updated."
|
|
|
|
echo ""
|
|
echo "✨ Database prefix change complete!"
|
|
echo " The backup file from before the change is still available at: $db_file"
|
|
}
|