#!/bin/bash # 固定资产系统备份脚本 set -euo pipefail PROJECT_DIR="${PROJECT_DIR:-/opt/equipment-management}" PROJECT_NAME="${PROJECT_NAME:-equipment-management}" BACKUP_ROOT="${BACKUP_ROOT:-/opt/backups/equipment-management}" KEEP_BACKUPS="${KEEP_BACKUPS:-3}" DB_CONTAINER="${DB_CONTAINER:-equipment-mysql}" BACKEND_CONTAINER="${BACKEND_CONTAINER:-equipment-backend}" DB_NAME="${DB_NAME:-equipment_management}" DB_USER="${DB_USER:-root}" DB_PASSWORD="${DB_PASSWORD:-jsjj8888}" UPLOADS_PATH="${UPLOADS_PATH:-/app/uploads}" TIMESTAMP="$(date +%Y%m%d_%H%M%S)" BACKUP_DIR="${BACKUP_ROOT}/${TIMESTAMP}" mkdir -p "${BACKUP_DIR}" mkdir -p "${BACKUP_DIR}/db" "${BACKUP_DIR}/uploads" "${BACKUP_DIR}/config" cleanup_on_error() { echo "备份失败,清理不完整目录: ${BACKUP_DIR}" rm -rf "${BACKUP_DIR}" } prune_old_backups() { if ! [[ "${KEEP_BACKUPS}" =~ ^[0-9]+$ ]]; then echo "KEEP_BACKUPS 不是有效数字: ${KEEP_BACKUPS}" exit 1 fi mapfile -t existing_backups < <(find "${BACKUP_ROOT}" -mindepth 1 -maxdepth 1 -type d | sort) local total="${#existing_backups[@]}" if [ "${total}" -le "${KEEP_BACKUPS}" ]; then echo ">>> 当前备份数量 ${total},无需清理" return fi local delete_count=$((total - KEEP_BACKUPS)) echo ">>> 仅保留最近 ${KEEP_BACKUPS} 份备份,清理 ${delete_count} 份旧备份" for backup_dir in "${existing_backups[@]:0:${delete_count}}"; do echo " 删除: ${backup_dir}" rm -rf "${backup_dir}" done } trap cleanup_on_error ERR echo "备份目录: ${BACKUP_DIR}" echo "保留策略: 最近 ${KEEP_BACKUPS} 份" if ! docker inspect "${DB_CONTAINER}" >/dev/null 2>&1; then echo "数据库容器不存在: ${DB_CONTAINER}" exit 1 fi if ! docker inspect "${BACKEND_CONTAINER}" >/dev/null 2>&1; then echo "后端容器不存在: ${BACKEND_CONTAINER}" exit 1 fi echo ">>> 备份数据库 ${DB_NAME}" docker exec "${DB_CONTAINER}" \ sh -lc "exec mysqldump -u${DB_USER} -p'${DB_PASSWORD}' --single-transaction --routines --triggers ${DB_NAME}" \ | gzip > "${BACKUP_DIR}/db/${DB_NAME}.sql.gz" echo ">>> 备份上传目录 ${UPLOADS_PATH}" docker exec "${BACKEND_CONTAINER}" \ sh -lc "if [ -d '${UPLOADS_PATH}' ]; then tar -C '${UPLOADS_PATH}' -czf - .; else printf '' | gzip; fi" \ > "${BACKUP_DIR}/uploads/uploads.tar.gz" echo ">>> 备份部署配置" cp "${PROJECT_DIR}/docker-compose.yml" "${BACKUP_DIR}/config/docker-compose.yml" cp "${PROJECT_DIR}/deploy.sh" "${BACKUP_DIR}/config/deploy.sh" cp "${PROJECT_DIR}/Dockerfile" "${BACKUP_DIR}/config/Dockerfile" cat > "${BACKUP_DIR}/backup-info.txt" <>> 生成校验信息" ( cd "${BACKUP_DIR}" sha256sum db/${DB_NAME}.sql.gz uploads/uploads.tar.gz config/docker-compose.yml config/deploy.sh config/Dockerfile > SHA256SUMS ) prune_old_backups trap - ERR echo "备份完成: ${BACKUP_DIR}"