246 lines
5.9 KiB
Bash
Executable File
246 lines
5.9 KiB
Bash
Executable File
#!/bin/sh
|
||
|
||
set -eu
|
||
|
||
WEBAPP_ROOT="/home/webapp"
|
||
ENV_ROOT="$WEBAPP_ROOT/env"
|
||
APP_ROOT="$WEBAPP_ROOT/loan-pricing"
|
||
JAVA_HOME="$ENV_ROOT/java"
|
||
NGINX_HOME="$ENV_ROOT/nginx"
|
||
NGINX_CONF="$NGINX_HOME/conf/nginx.conf"
|
||
BACKEND_DIR="$APP_ROOT/backend"
|
||
FRONTEND_DIR="$APP_ROOT/frontend"
|
||
FRONTEND_DIST_DIR="$FRONTEND_DIR/dist"
|
||
BACKUP_DIR="$APP_ROOT/backup"
|
||
LOG_DIR="$APP_ROOT/logs"
|
||
RUN_DIR="$APP_ROOT/run"
|
||
TMP_DIR="$APP_ROOT/tmp"
|
||
BACKEND_JAR="$BACKEND_DIR/ruoyi-admin.jar"
|
||
FRONTEND_PORT=63311
|
||
JAVA_RESTART_SCRIPT="$WEBAPP_ROOT/restart_java.sh"
|
||
|
||
timestamp() {
|
||
date "+%Y-%m-%d %H:%M:%S"
|
||
}
|
||
|
||
log_info() {
|
||
printf '[%s] %s\n' "$(timestamp)" "$1"
|
||
}
|
||
|
||
log_error() {
|
||
printf '[%s] %s\n' "$(timestamp)" "$1" >&2
|
||
}
|
||
|
||
usage() {
|
||
cat <<'EOF'
|
||
用法:
|
||
./bin/prod/deploy_release.sh <发布压缩包路径>
|
||
EOF
|
||
}
|
||
|
||
require_root() {
|
||
if [ "$(id -u)" -ne 0 ]; then
|
||
log_error "请使用 root 用户执行部署脚本"
|
||
exit 1
|
||
fi
|
||
}
|
||
|
||
require_command() {
|
||
if ! command -v "$1" >/dev/null 2>&1; then
|
||
log_error "缺少命令: $1"
|
||
exit 1
|
||
fi
|
||
}
|
||
|
||
ensure_runtime_dirs() {
|
||
mkdir -p "$BACKEND_DIR" "$FRONTEND_DIR" "$BACKUP_DIR" "$LOG_DIR" "$RUN_DIR" "$TMP_DIR"
|
||
}
|
||
|
||
cleanup() {
|
||
if [ -n "${WORK_DIR:-}" ] && [ -d "$WORK_DIR" ]; then
|
||
rm -rf "$WORK_DIR"
|
||
fi
|
||
}
|
||
|
||
extract_release_package() {
|
||
release_archive="$1"
|
||
release_extract_dir="$2"
|
||
|
||
mkdir -p "$release_extract_dir"
|
||
|
||
case "$release_archive" in
|
||
*.zip)
|
||
unzip -oq "$release_archive" -d "$release_extract_dir"
|
||
;;
|
||
*.tar.gz|*.tgz)
|
||
tar -xzf "$release_archive" -C "$release_extract_dir"
|
||
;;
|
||
*.tar)
|
||
tar -xf "$release_archive" -C "$release_extract_dir"
|
||
;;
|
||
*)
|
||
log_error "不支持的发布包格式: $release_archive"
|
||
exit 1
|
||
;;
|
||
esac
|
||
}
|
||
|
||
assert_single_file() {
|
||
search_dir="$1"
|
||
file_name="$2"
|
||
description="$3"
|
||
count=$(find "$search_dir" -type f -name "$file_name" | wc -l | tr -d ' ')
|
||
|
||
if [ "$count" -ne 1 ]; then
|
||
log_error "$description 数量不正确,期望 1 个,实际 $count 个"
|
||
exit 1
|
||
fi
|
||
|
||
find "$search_dir" -type f -name "$file_name" | head -n 1
|
||
}
|
||
|
||
assert_single_jar() {
|
||
search_dir="$1"
|
||
count=$(find "$search_dir" -type f -name '*.jar' | wc -l | tr -d ' ')
|
||
|
||
if [ "$count" -ne 1 ]; then
|
||
log_error "后端 jar 数量不正确,期望 1 个,实际 $count 个"
|
||
exit 1
|
||
fi
|
||
|
||
find "$search_dir" -type f -name '*.jar' | head -n 1
|
||
}
|
||
|
||
backup_current_release() {
|
||
backup_stamp=$(date "+%Y%m%d%H%M%S")
|
||
CURRENT_BACKUP_DIR="$BACKUP_DIR/$backup_stamp"
|
||
|
||
mkdir -p "$CURRENT_BACKUP_DIR/backend" "$CURRENT_BACKUP_DIR/frontend"
|
||
|
||
if [ -f "$BACKEND_JAR" ]; then
|
||
cp -a "$BACKEND_JAR" "$CURRENT_BACKUP_DIR/backend/"
|
||
fi
|
||
|
||
if [ -d "$FRONTEND_DIST_DIR" ]; then
|
||
cp -a "$FRONTEND_DIST_DIR" "$CURRENT_BACKUP_DIR/frontend/"
|
||
fi
|
||
|
||
log_info "旧版本已备份到: $CURRENT_BACKUP_DIR"
|
||
}
|
||
|
||
deploy_backend() {
|
||
source_jar="$1"
|
||
|
||
rm -f "$BACKEND_DIR"/*.jar
|
||
cp "$source_jar" "$BACKEND_JAR"
|
||
}
|
||
|
||
resolve_frontend_source_dir() {
|
||
unzip_dir="$1"
|
||
|
||
if [ -f "$unzip_dir/index.html" ]; then
|
||
printf '%s\n' "$unzip_dir"
|
||
return 0
|
||
fi
|
||
|
||
if [ -f "$unzip_dir/dist/index.html" ]; then
|
||
printf '%s\n' "$unzip_dir/dist"
|
||
return 0
|
||
fi
|
||
|
||
candidate=$(find "$unzip_dir" -type f -name 'index.html' | head -n 1)
|
||
if [ -z "${candidate:-}" ]; then
|
||
log_error "dist.zip 解压后未找到 index.html"
|
||
exit 1
|
||
fi
|
||
|
||
dirname "$candidate"
|
||
}
|
||
|
||
deploy_frontend() {
|
||
dist_zip="$1"
|
||
dist_unpack_dir="$WORK_DIR/frontend"
|
||
|
||
mkdir -p "$dist_unpack_dir"
|
||
unzip -oq "$dist_zip" -d "$dist_unpack_dir"
|
||
|
||
frontend_source_dir=$(resolve_frontend_source_dir "$dist_unpack_dir")
|
||
rm -rf "$FRONTEND_DIST_DIR"
|
||
mkdir -p "$FRONTEND_DIST_DIR"
|
||
cp -a "$frontend_source_dir"/. "$FRONTEND_DIST_DIR"/
|
||
}
|
||
|
||
reload_nginx() {
|
||
nginx_pid_file="$RUN_DIR/nginx.pid"
|
||
|
||
"$NGINX_HOME/sbin/nginx" -t -c "$NGINX_CONF"
|
||
|
||
if [ -f "$nginx_pid_file" ]; then
|
||
nginx_pid=$(cat "$nginx_pid_file" 2>/dev/null || true)
|
||
if [ -n "${nginx_pid:-}" ] && kill -0 "$nginx_pid" 2>/dev/null; then
|
||
"$NGINX_HOME/sbin/nginx" -c "$NGINX_CONF" -s reload
|
||
log_info "Nginx 已重载,前端端口: $FRONTEND_PORT"
|
||
return 0
|
||
fi
|
||
fi
|
||
|
||
"$NGINX_HOME/sbin/nginx" -c "$NGINX_CONF"
|
||
log_info "Nginx 已启动,前端端口: $FRONTEND_PORT"
|
||
}
|
||
|
||
main() {
|
||
if [ "$#" -ne 1 ]; then
|
||
usage
|
||
exit 1
|
||
fi
|
||
|
||
require_root
|
||
require_command tar
|
||
require_command unzip
|
||
require_command find
|
||
|
||
release_archive="$1"
|
||
if [ ! -f "$release_archive" ]; then
|
||
log_error "发布压缩包不存在: $release_archive"
|
||
exit 1
|
||
fi
|
||
|
||
if [ ! -x "$JAVA_HOME/bin/java" ]; then
|
||
log_error "未检测到 Java,请先执行 ./bin/prod/install_env.sh"
|
||
exit 1
|
||
fi
|
||
|
||
if [ ! -x "$NGINX_HOME/sbin/nginx" ]; then
|
||
log_error "未检测到 Nginx,请先执行 ./bin/prod/install_env.sh"
|
||
exit 1
|
||
fi
|
||
|
||
if [ ! -x "$JAVA_RESTART_SCRIPT" ]; then
|
||
log_error "未检测到 Java 重启脚本: $JAVA_RESTART_SCRIPT"
|
||
exit 1
|
||
fi
|
||
|
||
ensure_runtime_dirs
|
||
WORK_DIR=$(mktemp -d "$TMP_DIR/release.XXXXXX")
|
||
trap cleanup EXIT INT TERM
|
||
|
||
extract_release_package "$release_archive" "$WORK_DIR/package"
|
||
|
||
backend_jar_source=$(assert_single_jar "$WORK_DIR/package")
|
||
frontend_dist_source=$(assert_single_file "$WORK_DIR/package" 'dist.zip' '前端 dist.zip')
|
||
|
||
backup_current_release
|
||
"$JAVA_RESTART_SCRIPT" stop
|
||
deploy_backend "$backend_jar_source"
|
||
deploy_frontend "$frontend_dist_source"
|
||
"$JAVA_RESTART_SCRIPT" start
|
||
reload_nginx
|
||
|
||
log_info "部署完成"
|
||
log_info "后端 jar: $BACKEND_JAR"
|
||
log_info "前端目录: $FRONTEND_DIST_DIR"
|
||
log_info "备份目录: $CURRENT_BACKUP_DIR"
|
||
}
|
||
|
||
main "$@"
|