234 lines
9.8 KiB
Bash
234 lines
9.8 KiB
Bash
#!/bin/bash
|
|
|
|
BASE_URL=$2
|
|
BACKUP_TYPE=$3
|
|
BACKUP_LOG_FILE=$4
|
|
ENV_NAME=$5
|
|
BACKUP_COUNT=$6
|
|
APP_PATH=$7
|
|
USER_SESSION=$8
|
|
USER_EMAIL=$9
|
|
BACKUP_PATH=${10}
|
|
|
|
# Ensure restic is installed
|
|
if ! which restic &>/dev/null; then
|
|
if which dnf &>/dev/null; then
|
|
dnf install -y epel-release
|
|
dnf install -y restic
|
|
elif which yum &>/dev/null; then
|
|
yum-config-manager --add-repo https://copr.fedorainfracloud.org/coprs/copart/restic/repo/epel-7/copart-restic-epel-7.repo
|
|
yum-config-manager --enable copart-restic
|
|
yum -y install restic
|
|
yum-config-manager --disable copart-restic
|
|
fi
|
|
fi
|
|
|
|
# Function definitions remain the same, but adjustments are made to use $BACKUP_PATH
|
|
function update_restic(){
|
|
restic self-update 2>&1;
|
|
}
|
|
|
|
function check_backup_repo(){
|
|
local backup_repo_path="/mnt/backups/${ENV_NAME}"
|
|
[ -d "${backup_repo_path}" ] || mkdir -p "${backup_repo_path}"
|
|
export FILES_COUNT=$(find "${backup_repo_path}" -mindepth 1 | wc -l)
|
|
|
|
if [ "${FILES_COUNT}" -gt 0 ]; then
|
|
echo "$(date) ${ENV_NAME} Checking the backup repository integrity and consistency" | tee -a "${BACKUP_LOG_FILE}"
|
|
|
|
if [[ $(ls -A "${backup_repo_path}/locks") ]]; then
|
|
echo "$(date) ${ENV_NAME} Backup repository has a stale lock, removing" | tee -a "${BACKUP_LOG_FILE}"
|
|
GOGC=20 RESTIC_PASSWORD="${ENV_NAME}" restic -r "${backup_repo_path}" unlock
|
|
sendEmailNotification
|
|
fi
|
|
|
|
if ! GOGC=20 RESTIC_PASSWORD="${ENV_NAME}" restic -q -r "${backup_repo_path}" check --read-data-subset=5%; then
|
|
echo "Backup repository integrity check failed." | tee -a "${BACKUP_LOG_FILE}"
|
|
exit 1
|
|
fi
|
|
else
|
|
echo "$(date) ${ENV_NAME} Initializing new backup repository" | tee -a "${BACKUP_LOG_FILE}"
|
|
GOGC=20 RESTIC_PASSWORD="${ENV_NAME}" restic init -r "${backup_repo_path}"
|
|
fi
|
|
}
|
|
|
|
function sendEmailNotification() {
|
|
if [ -e "/usr/lib/jelastic/modules/api.module" ]; then
|
|
[ -e "/var/run/jem.pid" ] && return 0;
|
|
CURRENT_PLATFORM_MAJOR_VERSION=$(jem api apicall -s --connect-timeout 3 --max-time 15 [API_DOMAIN]/1.0/statistic/system/rest/getversion 2>/dev/null | jq .version | grep -o [0-9.]* | awk -F . '{print $1}')
|
|
if [ "${CURRENT_PLATFORM_MAJOR_VERSION}" -ge "7" ]; then
|
|
echo "$(date) ${ENV_NAME} Sending e-mail notification about removing the stale lock" | tee -a "$BACKUP_LOG_FILE"
|
|
SUBJECT="Stale lock is removed on ${BACKUP_PATH}/${ENV_NAME} backup repo"
|
|
BODY="Please pay attention to ${BACKUP_PATH}/${ENV_NAME} backup repo because the stale lock left from previous operation is removed during the integrity check and backup rotation. Manual check of backup repo integrity and consistency is highly desired."
|
|
jem api apicall -s --connect-timeout 3 --max-time 15 [API_DOMAIN]/1.0/message/email/rest/send --data-urlencode "session=$USER_SESSION" --data-urlencode "to=$USER_EMAIL" --data-urlencode "subject=$SUBJECT" --data-urlencode "body=$BODY"
|
|
if [[ $? != 0 ]]; then
|
|
echo "$(date) ${ENV_NAME} Sending of e-mail notification failed" | tee -a "$BACKUP_LOG_FILE"
|
|
else
|
|
echo "$(date) ${ENV_NAME} E-mail notification is sent successfully" | tee -a "$BACKUP_LOG_FILE"
|
|
fi
|
|
elif [ -z "${CURRENT_PLATFORM_MAJOR_VERSION}" ]; then
|
|
echo "$(date) ${ENV_NAME} Error when checking the platform version" | tee -a "$BACKUP_LOG_FILE"
|
|
else
|
|
echo "$(date) ${ENV_NAME} Email notification is not sent because this functionality is unavailable for current platform version." | tee -a "$BACKUP_LOG_FILE"
|
|
fi
|
|
else
|
|
echo "$(date) ${ENV_NAME} Email notification is not sent because this functionality is unavailable for current platform version." | tee -a "$BACKUP_LOG_FILE"
|
|
fi
|
|
}
|
|
|
|
function rotate_snapshots(){
|
|
local backup_repo_path="/mnt/backups/${ENV_NAME}"
|
|
echo "$(date) ${ENV_NAME} Rotating snapshots by keeping the last ${BACKUP_COUNT}" | tee -a "${BACKUP_LOG_FILE}"
|
|
|
|
if [[ $(ls -A "${backup_repo_path}/locks") ]]; then
|
|
echo "$(date) ${ENV_NAME} Backup repository has a stale lock, removing" | tee -a "${BACKUP_LOG_FILE}"
|
|
GOGC=20 RESTIC_PASSWORD="${ENV_NAME}" restic -r "${backup_repo_path}" unlock
|
|
sendEmailNotification
|
|
fi
|
|
|
|
if ! GOGC=20 RESTIC_COMPRESSION=off RESTIC_PACK_SIZE=8 RESTIC_PASSWORD="${ENV_NAME}" restic forget -q -r "${backup_repo_path}" --keep-last "${BACKUP_COUNT}" --prune | tee -a "${BACKUP_LOG_FILE}"; then
|
|
echo "Backup rotation failed." | tee -a "${BACKUP_LOG_FILE}"
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
function create_snapshot(){
|
|
local backup_repo_path="/mnt/backups/${ENV_NAME}"
|
|
DUMP_NAME=$(date "+%F_%H%M%S_%Z")
|
|
echo "$(date) ${ENV_NAME} Begin uploading the ${DUMP_NAME} snapshot to backup storage" | tee -a "${BACKUP_LOG_FILE}"
|
|
|
|
if ! GOGC=20 RESTIC_COMPRESSION=off RESTIC_PACK_SIZE=8 RESTIC_READ_CONCURRENCY=8 RESTIC_PASSWORD="${ENV_NAME}" restic backup -q -r "${backup_repo_path}" --tag "${DUMP_NAME} ${BACKUP_ADDON_COMMIT_ID} ${BACKUP_TYPE}" "${APP_PATH}" ~/wp_db_backup.sql | tee -a "${BACKUP_LOG_FILE}"; then
|
|
echo "Backup snapshot creation failed." | tee -a "${BACKUP_LOG_FILE}"
|
|
exit 1
|
|
fi
|
|
|
|
echo "$(date) ${ENV_NAME} End uploading the ${DUMP_NAME} snapshot to backup storage" | tee -a "${BACKUP_LOG_FILE}"
|
|
}
|
|
|
|
function backup_database() {
|
|
local backup_repo_path="/mnt/backups/${ENV_NAME}/db"
|
|
local log_file="/home/litespeed/mbmanager/logs/${ENV_NAME}_db_backup.log"
|
|
|
|
# Ensure the backup and log directories exist
|
|
mkdir -p "${backup_repo_path}"
|
|
mkdir -p "$(dirname "${log_file}")"
|
|
|
|
echo "$(date) ${ENV_NAME} Starting database backup..." | tee -a "${log_file}"
|
|
|
|
# Extract database credentials from wp-config.php
|
|
DB_NAME=$(grep DB_NAME /var/www/webroot/ROOT/wp-config.php | cut -d "'" -f 4)
|
|
DB_USER=$(grep DB_USER /var/www/webroot/ROOT/wp-config.php | cut -d "'" -f 4)
|
|
DB_PASSWORD=$(grep DB_PASSWORD /var/www/webroot/ROOT/wp-config.php | cut -d "'" -f 4)
|
|
DB_HOST=$(grep DB_HOST /var/www/webroot/ROOT/wp-config.php | cut -d "'" -f 4 | awk -F':' '{print $1}')
|
|
DB_PORT=$(grep DB_HOST /var/www/webroot/ROOT/wp-config.php | cut -d "'" -f 4 | awk -F':' '{print $2}' | sed 's/)//')
|
|
DB_PORT=${DB_PORT:-3306}
|
|
|
|
# Determine the correct --column-statistics option based on MySQL or MariaDB version
|
|
local column_statistics_option=""
|
|
SERVER_VERSION=$(mysql -h "${DB_HOST}" -u "${DB_USER}" -p"${DB_PASSWORD}" -e 'SELECT VERSION();' -s -N)
|
|
if [[ "${SERVER_VERSION}" =~ ^5\.7|^8\.0|MariaDB ]]; then
|
|
column_statistics_option="--column-statistics=0"
|
|
fi
|
|
|
|
# Create a database dump
|
|
local dump_file="${backup_repo_path}/${ENV_NAME}_$(date "+%Y-%m-%d_%H-%M-%S").sql"
|
|
mysqldump -h "${DB_HOST}" -P "${DB_PORT}" -u "${DB_USER}" -p"${DB_PASSWORD}" ${column_statistics_option} --force --single-transaction --quote-names --opt "${DB_NAME}" > "${dump_file}"
|
|
if [ $? -ne 0 ]; then
|
|
echo "$(date) ${ENV_NAME} Database backup process failed." | tee -a "${log_file}"
|
|
exit 1
|
|
fi
|
|
|
|
# Backup the dump file using Restic
|
|
restic -r "${backup_repo_path}" backup "${dump_file}" --tag "db" --host "${ENV_NAME}"
|
|
if [ $? -ne 0 ]; then
|
|
echo "$(date) ${ENV_NAME} Restic backup process failed." | tee -a "${log_file}"
|
|
exit 1
|
|
fi
|
|
|
|
echo "$(date) ${ENV_NAME} Database backup completed successfully." | tee -a "${log_file}"
|
|
# Optionally, remove the dump file after successful backup
|
|
rm -f "${dump_file}"
|
|
}
|
|
|
|
function backup_wp_core() {
|
|
echo "Starting backup of WordPress core files excluding uploads directory..."
|
|
# Define the path to the WordPress installation and the backup tag
|
|
local wp_path="$APP_PATH"
|
|
local backup_tag="wp-core-$(date "+%F_%H%M%S_%Z")"
|
|
|
|
# Exclude the uploads directory using the --exclude option
|
|
GOGC=20 RESTIC_PASSWORD="$RESTIC_PASSWORD" restic -r "$backupPath" backup \
|
|
--tag "$backup_tag" \
|
|
--exclude="$wp_path/wp-content/uploads" \
|
|
"$wp_path"
|
|
|
|
echo "WordPress core files backup completed."
|
|
}
|
|
|
|
function backup_uploads() {
|
|
echo "Starting backup of WordPress uploads directory..."
|
|
# Define the path to the uploads directory and the backup tag
|
|
local uploads_path="$APP_PATH/wp-content/uploads"
|
|
local backup_tag="wp-uploads-$(date "+%F_%H%M%S_%Z")"
|
|
|
|
# Perform the backup
|
|
GOGC=20 RESTIC_PASSWORD="$RESTIC_PASSWORD" restic -r "$backupPath" backup \
|
|
--tag "$backup_tag" \
|
|
"$uploads_path"
|
|
|
|
echo "WordPress uploads directory backup completed."
|
|
}
|
|
|
|
function backup_database() {
|
|
echo "Starting backup of WordPress database..."
|
|
# Define the backup tag and the path for the temporary SQL dump
|
|
local backup_tag="wp-db-$(date "+%F_%H%M%S_%Z")"
|
|
local sql_dump_path="/tmp/wp_db_backup.sql"
|
|
|
|
# Create a database dump
|
|
mysqldump -h "$DB_HOST" -u "$DB_USER" -p"$DB_PASSWORD" "$DB_NAME" > "$sql_dump_path"
|
|
|
|
# Perform the backup
|
|
GOGC=20 RESTIC_PASSWORD="$RESTIC_PASSWORD" restic -r "$backupPath" backup \
|
|
--tag "$backup_tag" \
|
|
"$sql_dump_path"
|
|
|
|
# Remove the temporary SQL dump file
|
|
rm -f "$sql_dump_path"
|
|
echo "WordPress database backup completed."
|
|
}
|
|
|
|
case "$1" in
|
|
backup)
|
|
backup_wp_core
|
|
backup_uploads
|
|
backup_database
|
|
;;
|
|
backup_wp_core)
|
|
backup_wp_core
|
|
;;
|
|
backup_uploads)
|
|
backup_uploads
|
|
;;
|
|
backup_database)
|
|
backup_database
|
|
;;
|
|
check_backup_repo)
|
|
check_backup_repo
|
|
;;
|
|
rotate_snapshots)
|
|
rotate_snapshots
|
|
;;
|
|
create_snapshot)
|
|
create_snapshot
|
|
;;
|
|
update_restic)
|
|
update_restic
|
|
;;
|
|
*)
|
|
echo "Usage: $0 {backup|backup_wp_core|backup_uploads|backup_database|check_backup_repo|rotate_snapshots|create_snapshot|update_restic}"
|
|
exit 2
|
|
esac
|
|
|
|
|
|
exit $? |