#!/bin/bash # 脚本名称:pg_backup_from_docker.sh # 功能:宿主机触发Docker容器内PG备份,并拷贝文件到宿主机指定目录 # 容器名称:polardb # 备份保留规则:每日备份保留30天,小时备份保留24小时(可按需调整) # ===================== 配置项(可根据实际需求修改)===================== CONTAINER_NAME="polardb" # Docker容器名称 PG_DUMP_CMD="/u01/polardb_pg/bin/pg_dump -h 127.0.0.1 -U postgres -p 5432 -F c auseft_web" CONTAINER_BACKUP_TMP="/home/postgres" # 容器内备份临时目录 HOST_HOUR_DIR="/home/postgres/hour" # 宿主机小时备份目录 HOST_DAY_DIR="/home/postgres/day" # 宿主机每日备份目录 RETENTION_DAYS=30 # 每日备份保留天数 RETENTION_HOURS=24 # 小时备份保留小时数 LOG_FILE="/home/postgres/pg_backup.log" # 备份日志文件(注释与变量之间加空格) # ===================== 初始化操作 ===================== # 创建宿主机备份目录(不存在则创建) mkdir -p ${HOST_HOUR_DIR} mkdir -p ${HOST_DAY_DIR} # 创建日志文件(不存在则创建) touch ${LOG_FILE} # 定义日志输出函数 log() { echo "[$(date +"%Y-%m-%d %H:%M:%S")] $1" >> ${LOG_FILE} } # ===================== 核心函数 ===================== # 函数1:执行容器内备份 + 拷贝到宿主机 backup_and_copy() { local backup_type=$1 # 备份类型:hour / day local filename="" local host_dir="" # 根据备份类型定义文件名和目标目录 if [ "${backup_type}" = "hour" ]; then filename="auseft_web_$(date +"%Y_%m_%d_%H").tar" host_dir=${HOST_HOUR_DIR} elif [ "${backup_type}" = "day" ]; then filename="auseft_web_$(date +"%Y_%m_%d").tar" host_dir=${HOST_DAY_DIR} else log "错误:备份类型仅支持 hour / day,当前传入:${backup_type}" exit 1 fi # 步骤1:检查容器是否运行 if ! docker inspect ${CONTAINER_NAME} >/dev/null 2>&1; then log "错误:容器 ${CONTAINER_NAME} 不存在或未运行" exit 1 fi # 步骤2:在容器内执行备份命令 log "开始在容器 ${CONTAINER_NAME} 内执行${backup_type}备份,文件名:${filename}" docker exec ${CONTAINER_NAME} bash -c "${PG_DUMP_CMD} > ${CONTAINER_BACKUP_TMP}/${filename}" # 检查容器内备份是否成功 if [ $? -ne 0 ]; then log "错误:容器内${backup_type}备份失败" exit 1 fi # 步骤3:将备份文件从容器拷贝到宿主机 log "开始将容器内备份文件拷贝到宿主机 ${host_dir}" docker cp ${CONTAINER_NAME}:${CONTAINER_BACKUP_TMP}/${filename} ${host_dir}/${filename} # 检查拷贝是否成功 if [ $? -eq 0 ]; then log "成功:${backup_type}备份文件已拷贝到 ${host_dir}/${filename}" # 步骤4:删除容器内临时备份文件(节省容器空间) docker exec ${CONTAINER_NAME} rm -f ${CONTAINER_BACKUP_TMP}/${filename} log "已删除容器内临时备份文件:${CONTAINER_BACKUP_TMP}/${filename}" else log "错误:${backup_type}备份文件拷贝失败" exit 1 fi # 步骤5:清理过期备份 clean_expired_backups ${backup_type} } # 函数2:清理过期备份 clean_expired_backups() { local backup_type=$1 if [ "${backup_type}" = "hour" ]; then # 清理超过24小时的小时备份 find ${HOST_HOUR_DIR} -name "auseft_web_*_*.tar" -type f -mmin +$((RETENTION_HOURS*60)) -delete log "已清理超过${RETENTION_HOURS}小时的小时备份" elif [ "${backup_type}" = "day" ]; then # 清理超过30天的每日备份 find ${HOST_DAY_DIR} -name "auseft_web_*.tar" -type f -mtime +${RETENTION_DAYS} -delete log "已清理超过${RETENTION_DAYS}天的每日备份" fi } # ===================== 执行逻辑 ===================== # 判断脚本传入参数 if [ $# -ne 1 ]; then log "错误:请传入备份类型参数(hour / day)" echo "使用方法:$0 [hour|day]" exit 1 fi case $1 in "hour") backup_and_copy "hour" ;; "day") backup_and_copy "day" ;; *) log "错误:参数无效,仅支持 hour / day" echo "使用方法:$0 [hour|day]" exit 1 ;; esac log "================== ${1}备份流程结束 ==================" exit 0