#!/bin/bash # 获取脚本所在目录的绝对路径 SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd) # 切换工作目录到脚本所在目录 cd $SCRIPT_DIR # 加载环境变量 load_env_variables() { if [ -f ".envrc" ]; then # 使用direnv加载环境变量 if command -v direnv &> /dev/null; then eval "$(direnv export bash)" # 检查POSTGRES_PASSWORD是否已设置,如果没有设置,尝试执行direnv allow if [ -z "$POSTGRES_PASSWORD" ]; then echo "检测到POSTGRES_PASSWORD未设置,尝试执行direnv allow..." direnv allow # 再次加载环境变量 eval "$(direnv export bash)" # 再次检查POSTGRES_PASSWORD if [ -z "$POSTGRES_PASSWORD" ]; then echo "错误: 密码验证失败,无法继续操作" return 1 fi fi else echo "错误: 未安装direnv,请先安装direnv" return 1 fi else echo "错误: 找不到.envrc文件" return 1 fi return 0 } # 调用函数加载环境变量 if ! load_env_variables; then echo "无法加载环境变量,脚本退出" exit 1 fi # 声明变量 container_name=${POSTGRES_CONTAINER_NAME:-postgres} pg_user=${POSTGRES_USER:-postgres} backup_dir="./data/backup/" # 获取宿主机上的绝对备份路径 HOST_BACKUP_DIR="$(pwd)/${backup_dir}" # 清除几天前的备份 days=${2:-15} # 备份单个数据库的函数 backup_database() { local db_name=$1 local datetime=$(date +"%Y%m%d_%H%M%S") local filename="${db_name}_full_${datetime}" local backup_path="${backup_dir}${filename}" local host_backup_path="${HOST_BACKUP_DIR}${filename}" echo "开始备份数据库 $db_name..." # 创建新备份 docker exec -i "$container_name" pg_dump -U postgres -Fd "$db_name" -f "$backup_path" -j 4 # 检查备份是否成功 if [ $? -eq 0 ]; then echo "备份完成!" echo "宿主机上的备份文件路径: ${host_backup_path}" echo "备份目录名: ${filename}" echo "注意:PostgreSQL目录格式备份包含多个文件,其中toc.dat是目录文件,包含备份内容的表目录信息" # 显示宿主机上备份文件大小信息 du -sh "${host_backup_path}" 2>/dev/null || echo "无法获取备份大小信息" # 显示备份目录中的文件数量 find "${host_backup_path}" -type f | wc -l | xargs echo "备份目录中的文件数量:" echo "" return 0 else echo "备份失败!" return 1 fi } # 主逻辑 if [ -n "$1" ]; then # 如果指定了数据库名称,则只备份该数据库 pg_database=$1 echo "将备份指定的数据库: $pg_database" # 清除该数据库几天前的备份 echo "清理 $pg_database 数据库 $days 天前的备份..." find $backup_dir -maxdepth 1 -name "${pg_database}*" -mtime +$days -exec sh -c 'echo "$(date): $1" >> cleardump.log; rm -rf $1' sh {} \; # 备份指定数据库 backup_database "$pg_database" else # 如果未指定数据库名称,则备份所有用户数据库(排除系统数据库) echo "未指定数据库名称,将备份所有用户数据库" # 获取所有用户数据库(排除postgres, template0, template1系统数据库) echo "正在获取数据库列表..." databases=$(docker exec -i "$container_name" psql -U postgres -t -c "SELECT datname FROM pg_database WHERE datistemplate = false AND datname NOT IN ('postgres', 'template0', 'template1');") # 检查是否成功获取数据库列表 if [ -z "$databases" ]; then echo "警告: 未找到用户数据库,将备份默认的postgres数据库" # 清理postgres数据库几天前的备份 echo "清理 postgres 数据库 $days 天前的备份..." find $backup_dir -maxdepth 1 -name "postgres*" -mtime +$days -exec sh -c 'echo "$(date): $1" >> cleardump.log; rm -rf $1' sh {} \; # 备份postgres数据库 backup_database "postgres" else echo "找到以下用户数据库:" echo "$databases" echo "" # 清理所有数据库几天前的备份 echo "清理所有数据库 $days 天前的备份..." find $backup_dir -maxdepth 1 -name "*_full_*" -mtime +$days -exec sh -c 'echo "$(date): $1" >> cleardump.log; rm -rf $1' sh {} \; # 备份每个用户数据库 for db in $databases; do # 去除可能的空格和换行符 db=$(echo "$db" | tr -d ' \n\r') if [ -n "$db" ]; then backup_database "$db" fi done fi fi # 检查是否有备份成功完成 if [ $? -eq 0 ]; then echo "所有指定的数据库备份完成!" exit 0 else echo "备份过程中出现错误,请检查日志" exit 1 fi