Files
upage-git/docker-entrypoint.sh
2025-09-25 15:24:13 +08:00

261 lines
6.2 KiB
Bash
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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
set -eo pipefail
SCRIPT_NAME=$(basename "$0")
START_TIME=$(date +%s)
MAX_DB_RETRIES=10
DB_RETRY_INTERVAL=5
TEMP_FILES=()
cleanup() {
log_info "正在清理资源..."
for temp_file in "${TEMP_FILES[@]}"; do
if [[ -f "$temp_file" ]]; then
rm -f "$temp_file"
log_debug "已删除临时文件: $temp_file"
fi
done
log_info "清理完成"
}
handle_exit() {
log_info "接收到退出信号,正在退出..."
cleanup
exit 0
}
trap handle_exit SIGTERM SIGINT
trap cleanup EXIT
LOG_LEVEL_DEBUG=0
LOG_LEVEL_INFO=1
LOG_LEVEL_WARN=2
LOG_LEVEL_ERROR=3
CURRENT_LOG_LEVEL=${LOG_LEVEL_INFO}
if [[ "$LOG_LEVEL" == "debug" ]]; then
CURRENT_LOG_LEVEL=${LOG_LEVEL_DEBUG}
elif [[ "$LOG_LEVEL" == "info" ]]; then
CURRENT_LOG_LEVEL=${LOG_LEVEL_INFO}
elif [[ "$LOG_LEVEL" == "warn" ]]; then
CURRENT_LOG_LEVEL=${LOG_LEVEL_WARN}
elif [[ "$LOG_LEVEL" == "error" ]]; then
CURRENT_LOG_LEVEL=${LOG_LEVEL_ERROR}
fi
log_debug() {
if [[ ${CURRENT_LOG_LEVEL} -le ${LOG_LEVEL_DEBUG} ]]; then
echo "🔍 [$(date '+%Y-%m-%d %H:%M:%S')] [DEBUG] $*"
fi
}
log_info() {
if [[ ${CURRENT_LOG_LEVEL} -le ${LOG_LEVEL_INFO} ]]; then
echo " [$(date '+%Y-%m-%d %H:%M:%S')] [INFO] $*"
fi
}
log_warn() {
if [[ ${CURRENT_LOG_LEVEL} -le ${LOG_LEVEL_WARN} ]]; then
echo "⚠️ [$(date '+%Y-%m-%d %H:%M:%S')] [WARN] $*"
fi
}
log_error() {
if [[ ${CURRENT_LOG_LEVEL} -le ${LOG_LEVEL_ERROR} ]]; then
echo "❌ [$(date '+%Y-%m-%d %H:%M:%S')] [ERROR] $*"
fi
}
log_success() {
if [[ ${CURRENT_LOG_LEVEL} -le ${LOG_LEVEL_INFO} ]]; then
echo "✅ [$(date '+%Y-%m-%d %H:%M:%S')] [SUCCESS] $*"
fi
}
# 创建安全的临时文件
create_temp_file() {
local temp_file
temp_file=$(mktemp)
TEMP_FILES+=("$temp_file")
echo "$temp_file"
}
safe_db_url() {
# 直接返回固定的数据库路径
echo "sqlite://data/upage.db"
}
# 设置数据库信息
extract_db_info() {
DB_FILE="data/upage.db"
return 0
}
# 检查数据库连接
check_db_connection() {
log_info "检查 SQLite 数据库..."
if ! extract_db_info; then
return 1
fi
log_info "SQLite 数据库文件路径: $DB_FILE"
# 如果数据库文件已存在,检查是否可读写
if [[ -f "$DB_FILE" && ! -w "$DB_FILE" ]]; then
log_error "SQLite 数据库文件存在但不可写: $DB_FILE"
return 1
fi
# 验证 Prisma 配置
local output_file
output_file=$(create_temp_file)
if pnpm prisma validate --schema=./prisma/schema.prisma > "$output_file" 2>&1; then
log_success "Prisma 配置验证成功"
else
log_warn "Prisma 配置验证警告,但将继续执行:"
cat "$output_file"
fi
log_success "SQLite 数据库检查通过"
return 0
}
# 等待数据库就绪
wait_for_db() {
log_info "准备 SQLite 数据库..."
if check_db_connection; then
log_success "SQLite 数据库就绪"
return 0
else
log_error "SQLite 数据库检查失败"
return 1
fi
}
# 处理数据库迁移
handle_db_migration() {
log_info "处理数据库迁移..."
# 1. 尝试直接应用迁移
local migrate_output
migrate_output=$(create_temp_file)
log_info "尝试应用数据库迁移..."
if pnpm prisma migrate deploy --schema=./prisma/schema.prisma > "$migrate_output" 2>&1; then
log_success "数据库迁移成功应用"
return 0
fi
if grep -q "P3005" "$migrate_output" || grep -q "数据库架构不为空" "$migrate_output"; then
log_warn "检测到已存在的数据库结构,需要应用 baseline..."
local migration_dirs
migration_dirs=$(find prisma/migrations -maxdepth 1 -type d | grep -v "^prisma/migrations$" | sort)
if [[ -z "$migration_dirs" ]]; then
log_warn "未找到迁移,跳过 baseline 处理"
else
log_info "找到以下迁移:"
for migration_dir in $migration_dirs; do
local migration_name
migration_name=$(basename "$migration_dir")
log_info " - $migration_name"
log_info "将迁移 $migration_name 标记为已应用..."
local resolve_output
resolve_output=$(create_temp_file)
if ! pnpm prisma migrate resolve --applied "$migration_name" > "$resolve_output" 2>&1; then
log_warn "标记迁移 $migration_name 时出错:"
cat "$resolve_output"
fi
done
log_success "Baseline 应用成功"
log_info "检查并应用新的迁移..."
local deploy_output
deploy_output=$(create_temp_file)
if ! pnpm prisma migrate deploy > "$deploy_output" 2>&1; then
log_warn "应用新迁移时出错:"
cat "$deploy_output"
log_info "尝试使用 db push 作为备选方案..."
local push_output
push_output=$(create_temp_file)
if ! pnpm prisma db push --accept-data-loss --skip-generate > "$push_output" 2>&1; then
log_error "使用 db push 也失败了:"
cat "$push_output"
return 1
else
log_success "使用 db push 成功应用架构"
fi
else
log_success "新迁移应用成功"
fi
fi
else
log_warn "迁移失败,错误信息:"
cat "$migrate_output"
log_info "尝试使用 db push 作为备选方案..."
local push_output
push_output=$(create_temp_file)
if ! pnpm prisma db push --accept-data-loss --skip-generate > "$push_output" 2>&1; then
log_error "使用 db push 也失败了:"
cat "$push_output"
return 1
else
log_success "使用 db push 成功应用架构"
fi
fi
return 0
}
main() {
log_info "🚀 启动 UPage 应用..."
log_info "系统环境信息:"
log_info " - NODE_ENV: $NODE_ENV"
log_info " - 当前用户: $(whoami)"
log_info " - 工作目录: $(pwd)"
if extract_db_info; then
log_info "SQLite 数据库信息:"
log_info " - 数据库文件: $DB_FILE"
fi
if ! wait_for_db; then
log_error "数据库连接失败,退出启动流程"
exit 1
fi
if ! handle_db_migration; then
log_error "数据库迁移失败,退出启动流程"
exit 1
fi
local end_time
end_time=$(date +%s)
local duration=$((end_time - START_TIME))
log_success "初始化完成,耗时 ${duration}"
log_info "启动应用服务..."
log_info "执行命令: $*"
exec "$@"
}
main "$@"