197 lines
5.1 KiB
Bash
Executable File
197 lines
5.1 KiB
Bash
Executable File
#!/bin/bash
|
|
# ============================================================
|
|
# backup_api.sh
|
|
# 导出 pricing, llmage, uapi 三个模块的表数据为 SQL 文件
|
|
#
|
|
# 用法:
|
|
# ./backup_api.sh [options]
|
|
#
|
|
# 选项:
|
|
# -h HOST MySQL 主机 (默认: localhost)
|
|
# -P PORT MySQL 端口 (默认: 3306)
|
|
# -u USER MySQL 用户名 (默认: root)
|
|
# -p PASSWORD MySQL 密码
|
|
# -d DATABASE 数据库名 (默认: sage)
|
|
# -o OUTPUT_DIR 输出目录 (默认: ./sql_dumps)
|
|
# --no-data 只导出表结构,不导出数据
|
|
# --help 显示帮助
|
|
# ============================================================
|
|
|
|
set -euo pipefail
|
|
|
|
# 默认参数
|
|
HOST="localhost"
|
|
PORT="3306"
|
|
USER="root"
|
|
PASSWORD=""
|
|
DATABASE="sage"
|
|
OUTPUT_DIR="./sql_dumps"
|
|
NO_DATA=""
|
|
REPOS_DIR="$(cd "$(dirname "$0")/../.." 2>/dev/null && pwd || echo "/home/hermesai/repos")"
|
|
|
|
# 各模块排除的表
|
|
declare -A MODULE_EXCLUDES
|
|
MODULE_EXCLUDES["llmage"]="llmusage llmusage_accounting_failed llmusage_history"
|
|
MODULE_EXCLUDES["uapi"]="uapiset uptask"
|
|
|
|
usage() {
|
|
sed -n '2,/^# ===/p' "$0" | grep '^#' | sed 's/^# \?//'
|
|
exit 0
|
|
}
|
|
|
|
# 解析参数
|
|
while [[ $# -gt 0 ]]; do
|
|
case "$1" in
|
|
-h) HOST="$2"; shift 2 ;;
|
|
-P) PORT="$2"; shift 2 ;;
|
|
-u) USER="$2"; shift 2 ;;
|
|
-p) PASSWORD="$2"; shift 2 ;;
|
|
-d) DATABASE="$2"; shift 2 ;;
|
|
-o) OUTPUT_DIR="$2"; shift 2 ;;
|
|
--no-data) NO_DATA="--no-data"; shift ;;
|
|
--help) usage ;;
|
|
*) echo "未知参数: $1"; exit 1 ;;
|
|
esac
|
|
done
|
|
|
|
# 构建 mysqldump 基础命令
|
|
MYSQLDUMP_BASE="mysqldump -h${HOST} -P${PORT} -u${USER}"
|
|
if [[ -n "$PASSWORD" ]]; then
|
|
MYSQLDUMP_BASE="${MYSQLDUMP_BASE} -p${PASSWORD}"
|
|
fi
|
|
|
|
# 从 models/*.json 提取表名
|
|
get_tables() {
|
|
local module_dir="$1"
|
|
shift
|
|
local excludes=("$@")
|
|
local tables=()
|
|
|
|
if [[ ! -d "$module_dir/models" ]]; then
|
|
echo "警告: 目录不存在 $module_dir/models" >&2
|
|
return
|
|
fi
|
|
|
|
for f in "$module_dir/models"/*.json; do
|
|
[[ -f "$f" ]] || continue
|
|
# 从 summary[0].name 提取表名
|
|
local tbl
|
|
tbl=$(python3 -c "
|
|
import json, sys
|
|
try:
|
|
d = json.load(open('$f'))
|
|
s = d.get('summary', [])
|
|
if isinstance(s, list) and len(s) > 0:
|
|
print(s[0].get('name', ''))
|
|
elif isinstance(s, dict):
|
|
print(s.get('name', ''))
|
|
except:
|
|
pass
|
|
" 2>/dev/null)
|
|
if [[ -z "$tbl" ]]; then
|
|
continue
|
|
fi
|
|
# 检查是否在排除列表中
|
|
local excluded=false
|
|
for ex in "${excludes[@]}"; do
|
|
if [[ "$tbl" == "$ex" ]]; then
|
|
excluded=true
|
|
break
|
|
fi
|
|
done
|
|
if [[ "$excluded" == "false" ]]; then
|
|
tables+=("$tbl")
|
|
fi
|
|
done
|
|
echo "${tables[@]}"
|
|
}
|
|
|
|
# 创建输出目录
|
|
mkdir -p "$OUTPUT_DIR"
|
|
|
|
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
|
|
|
|
echo "============================================================"
|
|
echo " Sage 模块表数据导出"
|
|
echo " 时间: $(date '+%Y-%m-%d %H:%M:%S')"
|
|
echo " 数据库: ${DATABASE}@${HOST}:${PORT}"
|
|
echo " 输出目录: ${OUTPUT_DIR}"
|
|
echo "============================================================"
|
|
|
|
# 定义模块
|
|
declare -A MODULES
|
|
MODULES=(
|
|
["pricing"]="$REPOS_DIR/pricing"
|
|
["llmage"]="$REPOS_DIR/llmage"
|
|
["uapi"]="$REPOS_DIR/uapi"
|
|
)
|
|
|
|
TOTAL_TABLES=0
|
|
TOTAL_FILES=0
|
|
|
|
for module in pricing llmage uapi; do
|
|
module_dir="${MODULES[$module]}"
|
|
echo ""
|
|
echo "--- 模块: $module ---"
|
|
|
|
if [[ ! -d "$module_dir" ]]; then
|
|
echo " 跳过: 模块目录不存在 $module_dir"
|
|
continue
|
|
fi
|
|
|
|
# 获取表名(按模块排除指定表)
|
|
excludes_str="${MODULE_EXCLUDES[$module]:-}"
|
|
excludes_arr=()
|
|
if [[ -n "$excludes_str" ]]; then
|
|
read -ra excludes_arr <<< "$excludes_str"
|
|
fi
|
|
tables=$(get_tables "$module_dir" "${excludes_arr[@]+"${excludes_arr[@]}"}")
|
|
|
|
if [[ -z "$tables" ]]; then
|
|
echo " 跳过: 未找到表定义"
|
|
continue
|
|
fi
|
|
|
|
echo " 表: $tables"
|
|
|
|
# 生成 SQL 文件
|
|
outfile="${OUTPUT_DIR}/${module}_${TIMESTAMP}.sql"
|
|
table_count=0
|
|
|
|
for tbl in $tables; do
|
|
echo -n " 导出 $tbl ... "
|
|
if ${MYSQLDUMP_BASE} \
|
|
--single-transaction \
|
|
--routines \
|
|
--triggers \
|
|
--set-gtid-purged=OFF \
|
|
--column-names \
|
|
--complete-insert \
|
|
$NO_DATA \
|
|
"$DATABASE" "$tbl" >> "$outfile" 2>/dev/null; then
|
|
echo "OK"
|
|
((table_count++))
|
|
else
|
|
# 如果表不存在,跳过
|
|
echo "跳过(表不存在或无权限)"
|
|
fi
|
|
done
|
|
|
|
if [[ $table_count -gt 0 ]]; then
|
|
echo " => $outfile ($table_count 个表)"
|
|
((TOTAL_TABLES += table_count))
|
|
((TOTAL_FILES++))
|
|
else
|
|
rm -f "$outfile"
|
|
echo " => 无有效表数据"
|
|
fi
|
|
done
|
|
|
|
echo ""
|
|
echo "============================================================"
|
|
echo " 导出完成"
|
|
echo " 文件数: $TOTAL_FILES"
|
|
echo " 表总数: $TOTAL_TABLES"
|
|
echo " 输出目录: $(cd "$OUTPUT_DIR" && pwd)"
|
|
echo "============================================================"
|