Files
shell-scripts/0-部署应用/CloudCone-备份中心/deepseek-v3.1/b-nextcloud-dsv3.1.sh
2025-09-03 14:14:19 +08:00

362 lines
9.6 KiB
Bash
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/bin/bash
# =============================================================================
# nextcloud备份脚本
# 功能远程Nextcloud维护模式切换、数据库备份、文件同步及清理
# 版本1.0.0
# 作者Shell脚本工程师
# 许可证MIT License
# 依赖ssh, rsync, docker (远程主机), mariadb-client (远程主机)
# =============================================================================
set -euo pipefail
IFS=$'\n\t'
# > 全局常量定义
readonly SCRIPT_NAME="$(basename "$0")"
readonly SCRIPT_DIR="/root/wdd/backup"
readonly LOCK_FILE="/root/wdd/backup/${SCRIPT_NAME}.lock"
# > 远程主机配置
readonly REMOTE_HOST="s5"
readonly REMOTE_PORT="22333"
readonly REMOTE_USER="root"
readonly REMOTE_NEXTCLOUD_DIR="/data/nextcloud"
readonly REMOTE_DB_CONTAINER="nextcloud-db"
readonly REMOTE_WEB_CONTAINER="nextcloud_web"
# > 数据库配置
readonly DB_NAME="nextcloud"
readonly DB_USER="nextcloud"
readonly DB_PASSWORD="boge14@Level5"
# > 本地配置
readonly LOCAL_BACKUP_DIR="/data/s5_146-56-159-175/nextcloud"
# > 日志配置
readonly LOG_DIR="${SCRIPT_DIR}/logs"
readonly LOG_FILE="${LOG_DIR}/nextcloud_backup_$(date +%Y%m%d).log"
# > 颜色输出定义
readonly RED='\033[0;31m'
readonly GREEN='\033[0;32m'
readonly YELLOW='\033[1;33m'
readonly BLUE='\033[0;34m'
readonly NC='\033[0m'
# =============================================================================
# 日志函数集
# =============================================================================
###
# 初始化日志系统
# @require 无
# @return 0 成功 | >0 失败
###
init_log_system() {
mkdir -p "${LOG_DIR}" || return 1
touch "${LOG_FILE}" || return 1
return 0
}
###
# 记录日志消息
# @param level string 日志级别DEBUG/INFO/WARN/ERROR
# @param message string 日志消息
# @require LOG_FILE
# @return 0 成功
###
log_message() {
local level="$1"
local message="$2"
local timestamp
timestamp=$(date '+%Y-%m-%d %H:%M:%S')
case "${level}" in
"DEBUG") echo -e "${BLUE}[DEBUG]${NC} ${timestamp} - ${message}" | tee -a "${LOG_FILE}" ;;
"INFO") echo -e "${GREEN}[INFO]${NC} ${timestamp} - ${message}" | tee -a "${LOG_FILE}" ;;
"WARN") echo -e "${YELLOW}[WARN]${NC} ${timestamp} - ${message}" | tee -a "${LOG_FILE}" >&2 ;;
"ERROR") echo -e "${RED}[ERROR]${NC} ${timestamp} - ${message}" | tee -a "${LOG_FILE}" >&2 ;;
*) echo "${timestamp} - ${message}" | tee -a "${LOG_FILE}" ;;
esac
return 0
}
# =============================================================================
# 工具函数集
# =============================================================================
###
# 检查命令是否存在
# @param command_name string 命令名称
# @require 无
# @return 0 存在 | 1 不存在
###
check_command() {
local command_name="$1"
if ! command -v "${command_name}" >/dev/null 2>&1; then
log_message "ERROR" "命令不存在: ${command_name}"
return 1
fi
return 0
}
###
# 执行远程SSH命令
# @param command string 要执行的命令
# @require REMOTE_HOST, REMOTE_PORT, REMOTE_USER
# @return 远程命令的退出码
###
execute_remote_command() {
local command="$1"
ssh -p "${REMOTE_PORT}" "${REMOTE_USER}@${REMOTE_HOST}" "${command}"
return $?
}
###
# 创建锁文件防止并发执行
# @require LOCK_FILE
# @return 0 成功获取锁 | 1 锁已存在
###
acquire_lock() {
if [ -e "${LOCK_FILE}" ]; then
log_message "ERROR" "备份任务正在运行或异常退出,请检查锁文件: ${LOCK_FILE}"
return 1
fi
echo "$$" > "${LOCK_FILE}"
trap 'release_lock' EXIT
return 0
}
###
# 释放锁文件
# @require LOCK_FILE
# @return 0 成功
###
release_lock() {
[ -e "${LOCK_FILE}" ] && rm -f "${LOCK_FILE}"
return 0
}
# =============================================================================
# Nextcloud核心备份函数
# =============================================================================
###
# 启用Nextcloud维护模式
# @require execute_remote_command, REMOTE_WEB_CONTAINER
# @return 0 成功 | >0 失败
###
enable_maintenance_mode() {
log_message "INFO" "启用Nextcloud维护模式..."
local maintenance_cmd="docker exec -u www-data ${REMOTE_WEB_CONTAINER} php occ maintenance:mode --on"
if ! execute_remote_command "${maintenance_cmd}"; then
log_message "ERROR" "启用维护模式失败"
return 1
fi
log_message "INFO" "维护模式已启用"
return 0
}
###
# 禁用Nextcloud维护模式
# @require execute_remote_command, REMOTE_WEB_CONTAINER
# @return 0 成功 | >0 失败
###
disable_maintenance_mode() {
log_message "INFO" "禁用Nextcloud维护模式..."
local maintenance_cmd="docker exec -u www-data ${REMOTE_WEB_CONTAINER} php occ maintenance:mode --off"
if ! execute_remote_command "${maintenance_cmd}"; then
log_message "ERROR" "禁用维护模式失败"
return 1
fi
log_message "INFO" "维护模式已禁用"
return 0
}
###
# 远程执行MariaDB数据库备份
# @require execute_remote_command, REMOTE_DB_CONTAINER, DB_NAME, DB_USER, DB_PASSWORD, REMOTE_NEXTCLOUD_DIR
# @return 0 成功 | >0 失败
###
backup_database() {
log_message "INFO" "开始数据库备份..."
local backup_file="${REMOTE_NEXTCLOUD_DIR}/nextcloud-db_backup_$(date +%Y%m%d-%H%M%S).sql"
local backup_cmd="docker exec ${REMOTE_DB_CONTAINER} mariadb-dump --single-transaction -h localhost -u ${DB_USER} -p'${DB_PASSWORD}' ${DB_NAME} > ${backup_file}"
if ! execute_remote_command "${backup_cmd}"; then
log_message "ERROR" "数据库备份失败"
return 1
fi
# > 验证备份文件是否创建成功
local verify_cmd="[ -f \"${backup_file}\" ] && echo \"exists\" || echo \"missing\""
if [ "$(execute_remote_command "${verify_cmd}")" != "exists" ]; then
log_message "ERROR" "数据库备份文件创建失败"
return 1
fi
log_message "INFO" "数据库备份完成: ${backup_file}"
return 0
}
###
# 使用rsync同步Nextcloud文件到本地
# @require REMOTE_HOST, REMOTE_PORT, REMOTE_USER, REMOTE_NEXTCLOUD_DIR, LOCAL_BACKUP_DIR
# @return 0 成功 | >0 失败
###
sync_nextcloud_files() {
log_message "INFO" "开始同步Nextcloud文件到本地..."
# > 创建本地暂存目录
mkdir -p "${LOCAL_BACKUP_DIR}" || {
log_message "ERROR" "创建本地暂存目录失败: ${LOCAL_BACKUP_DIR}"
return 1
}
# > 构建rsync命令
local rsync_cmd="rsync -avz --progress -e 'ssh -p ${REMOTE_PORT}'"
rsync_cmd+=" ${REMOTE_USER}@${REMOTE_HOST}:${REMOTE_NEXTCLOUD_DIR}/"
rsync_cmd+=" ${LOCAL_BACKUP_DIR}/"
# > 执行rsync同步
if ! eval "${rsync_cmd}"; then
log_message "ERROR" "Nextcloud文件同步失败"
return 1
fi
log_message "INFO" "Nextcloud文件同步完成"
return 0
}
###
# 远程删除数据库备份文件
# @require execute_remote_command, REMOTE_NEXTCLOUD_DIR
# @return 0 成功 | >0 失败
###
remote_cleanup_backup() {
log_message "INFO" "清理远程数据库备份文件..."
local cleanup_cmd="rm -f ${REMOTE_NEXTCLOUD_DIR}/nextcloud-db_backup_*.sql"
if ! execute_remote_command "${cleanup_cmd}"; then
log_message "ERROR" "远程清理失败"
return 1
fi
log_message "INFO" "远程清理完成"
return 0
}
###
# 清理本地暂存目录
# @require LOCAL_BACKUP_DIR
# @return 0 成功
###
local_cleanup() {
log_message "INFO" "清理本地暂存目录..."
[ -d "${LOCAL_BACKUP_DIR}" ] && rm -rf "${LOCAL_BACKUP_DIR}"
return 0
}
# =============================================================================
# 主执行流程
# =============================================================================
###
# 主备份流程
# @require 所有上述函数
# @return 0 成功 | >0 失败
###
main_backup_process() {
log_message "INFO" "=== 开始Nextcloud备份任务 ==="
# > 检查依赖命令
local required_commands=("ssh" "rsync")
for cmd in "${required_commands[@]}"; do
if ! check_command "${cmd}"; then
return 1
fi
done
# > 执行备份流程
local steps=(
enable_maintenance_mode
backup_database
sync_nextcloud_files
remote_cleanup_backup
disable_maintenance_mode
# local_cleanup
)
for step in "${steps[@]}"; do
if ! "${step}"; then
log_message "ERROR" "备份任务失败,正在尝试恢复..."
# > 尝试禁用维护模式
disable_maintenance_mode || true
return 1
fi
done
log_message "INFO" "=== Nextcloud备份任务完成 ==="
return 0
}
# =============================================================================
# 脚本入口点
# =============================================================================
# > 设置错误处理
trap 'log_message "ERROR" "脚本异常退出"; disable_maintenance_mode || true; release_lock; exit 1' ERR
# > 主执行块
main() {
if ! acquire_lock; then
exit 1
fi
if ! init_log_system; then
log_message "ERROR" "日志系统初始化失败"
exit 1
fi
if ! main_backup_process; then
log_message "ERROR" "备份任务执行失败"
exit 1
fi
release_lock
exit 0
}
# > 脚本执行入口
main "$@"
# =============================================================================
# 函数调用关系图
# =============================================================================
# main
# ├── acquire_lock
# ├── init_log_system
# └── main_backup_process
# ├── check_command (多次调用)
# ├── enable_maintenance_mode
# │ └── execute_remote_command
# ├── backup_database
# │ └── execute_remote_command
# ├── sync_nextcloud_files
# ├── move_to_backup_dir
# ├── remote_cleanup_backup
# │ └── execute_remote_command
# ├── disable_maintenance_mode
# │ └── execute_remote_command
# └── local_cleanup