213 lines
5.3 KiB
Bash
Executable File
213 lines
5.3 KiB
Bash
Executable File
#!/bin/sh
|
|
|
|
set -eu
|
|
|
|
SCRIPT_DIR=$(CDPATH= cd -- "$(dirname "$0")" && pwd)
|
|
BACKEND_DIR="${SCRIPT_DIR}/backend"
|
|
FRONTEND_DIR="${SCRIPT_DIR}/frontend"
|
|
START_SCRIPT="${SCRIPT_DIR}/start-java-backend-prod.sh"
|
|
BACKUP_ROOT="${SCRIPT_DIR}/backups"
|
|
WORK_ROOT="${SCRIPT_DIR}/.deploy-work"
|
|
TIMESTAMP=$(date '+%Y%m%d%H%M%S')
|
|
BACKUP_DIR="${BACKUP_ROOT}/${TIMESTAMP}"
|
|
WORK_DIR="${WORK_ROOT}/release-${TIMESTAMP}"
|
|
RELEASE_ZIP="${1:-}"
|
|
|
|
RELEASE_JAR=""
|
|
RELEASE_DIST_ZIP=""
|
|
FRONTEND_SOURCE_DIR=""
|
|
|
|
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'
|
|
用法: ./deploy-release-prod.sh [上线压缩包路径]
|
|
|
|
目录要求:
|
|
deploy-release-prod.sh
|
|
start-java-backend-prod.sh
|
|
backend/
|
|
frontend/
|
|
ccdi_YYYYMMDD.zip
|
|
|
|
说明:
|
|
未传上线压缩包路径时,脚本会自动使用当前脚本目录下唯一的 .zip 文件。
|
|
上线压缩包根层必须包含 ruoyi-admin.jar 和 dist.zip。
|
|
EOF
|
|
}
|
|
|
|
require_command() {
|
|
if ! command -v "$1" >/dev/null 2>&1; then
|
|
log_error "缺少命令: $1"
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
resolve_path() {
|
|
input_path="$1"
|
|
|
|
case "${input_path}" in
|
|
/*)
|
|
printf '%s\n' "${input_path}"
|
|
;;
|
|
*)
|
|
input_dir=$(dirname "${input_path}")
|
|
input_base=$(basename "${input_path}")
|
|
printf '%s/%s\n' "$(CDPATH= cd -- "${input_dir}" && pwd)" "${input_base}"
|
|
;;
|
|
esac
|
|
}
|
|
|
|
resolve_release_zip() {
|
|
if [ -n "${RELEASE_ZIP}" ]; then
|
|
RELEASE_ZIP=$(resolve_path "${RELEASE_ZIP}")
|
|
else
|
|
mkdir -p "${WORK_ROOT}"
|
|
candidate_file="${WORK_ROOT}/zip-candidates-${TIMESTAMP}.txt"
|
|
find "${SCRIPT_DIR}" -maxdepth 1 -type f -name '*.zip' ! -name 'dist.zip' | sort > "${candidate_file}"
|
|
candidate_count=$(wc -l < "${candidate_file}" | tr -d ' ')
|
|
|
|
if [ "${candidate_count}" -eq 0 ]; then
|
|
log_error "未在脚本目录找到上线压缩包,请传入压缩包路径"
|
|
exit 1
|
|
fi
|
|
|
|
if [ "${candidate_count}" -gt 1 ]; then
|
|
log_error "脚本目录存在多个上线压缩包,请显式传入压缩包路径"
|
|
cat "${candidate_file}" >&2
|
|
exit 1
|
|
fi
|
|
|
|
RELEASE_ZIP=$(sed -n '1p' "${candidate_file}")
|
|
rm -f "${candidate_file}"
|
|
fi
|
|
|
|
if [ ! -f "${RELEASE_ZIP}" ]; then
|
|
log_error "上线压缩包不存在: ${RELEASE_ZIP}"
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
assert_layout() {
|
|
if [ ! -d "${BACKEND_DIR}" ]; then
|
|
log_error "未找到后端目录: ${BACKEND_DIR}"
|
|
exit 1
|
|
fi
|
|
|
|
if [ ! -d "${FRONTEND_DIR}" ]; then
|
|
log_error "未找到前端目录: ${FRONTEND_DIR}"
|
|
exit 1
|
|
fi
|
|
|
|
if [ ! -f "${START_SCRIPT}" ]; then
|
|
log_error "未找到后端启动脚本: ${START_SCRIPT}"
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
backup_dir() {
|
|
source_dir="$1"
|
|
target_dir="$2"
|
|
|
|
mkdir -p "${target_dir}"
|
|
if [ -n "$(find "${source_dir}" -mindepth 1 -maxdepth 1 -print -quit)" ]; then
|
|
cp -a "${source_dir}/." "${target_dir}/"
|
|
log_info "已备份 ${source_dir} 到 ${target_dir}"
|
|
else
|
|
log_info "目录为空,已创建空备份目录: ${target_dir}"
|
|
fi
|
|
}
|
|
|
|
backup_current_files() {
|
|
mkdir -p "${BACKUP_DIR}"
|
|
backup_dir "${BACKEND_DIR}" "${BACKUP_DIR}/backend"
|
|
backup_dir "${FRONTEND_DIR}" "${BACKUP_DIR}/frontend"
|
|
}
|
|
|
|
extract_release_package() {
|
|
mkdir -p "${WORK_DIR}/release" "${WORK_DIR}/frontend"
|
|
log_info "开始解压上线压缩包: ${RELEASE_ZIP}"
|
|
unzip -q "${RELEASE_ZIP}" -d "${WORK_DIR}/release"
|
|
|
|
RELEASE_JAR="${WORK_DIR}/release/ruoyi-admin.jar"
|
|
RELEASE_DIST_ZIP="${WORK_DIR}/release/dist.zip"
|
|
if [ ! -f "${RELEASE_JAR}" ]; then
|
|
log_error "上线压缩包根层缺少 ruoyi-admin.jar"
|
|
exit 1
|
|
fi
|
|
if [ ! -f "${RELEASE_DIST_ZIP}" ]; then
|
|
log_error "上线压缩包根层缺少 dist.zip"
|
|
exit 1
|
|
fi
|
|
|
|
unzip -q "${RELEASE_DIST_ZIP}" -d "${WORK_DIR}/frontend"
|
|
FRONTEND_SOURCE_DIR="${WORK_DIR}/frontend/dist"
|
|
if [ ! -f "${FRONTEND_SOURCE_DIR}/index.html" ]; then
|
|
log_error "dist.zip 解压后未找到 dist/index.html"
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
deploy_backend() {
|
|
target_jar="${BACKEND_DIR}/ruoyi-admin.jar"
|
|
deploying_jar="${BACKEND_DIR}/.ruoyi-admin.jar.deploying"
|
|
|
|
cp "${RELEASE_JAR}" "${deploying_jar}"
|
|
mv "${deploying_jar}" "${target_jar}"
|
|
log_info "后端 Jar 已部署: ${target_jar}"
|
|
}
|
|
|
|
deploy_frontend() {
|
|
find "${FRONTEND_DIR}" -mindepth 1 -maxdepth 1 -exec rm -rf {} +
|
|
cp -a "${FRONTEND_SOURCE_DIR}/." "${FRONTEND_DIR}/"
|
|
log_info "前端文件已部署到: ${FRONTEND_DIR}"
|
|
}
|
|
|
|
cleanup_work_dir() {
|
|
rm -rf "${WORK_DIR}"
|
|
}
|
|
|
|
main() {
|
|
case "${1:-}" in
|
|
-h|--help|help)
|
|
usage
|
|
exit 0
|
|
;;
|
|
esac
|
|
|
|
if [ "$#" -gt 1 ]; then
|
|
usage
|
|
exit 1
|
|
fi
|
|
|
|
require_command "unzip"
|
|
require_command "find"
|
|
|
|
resolve_release_zip
|
|
assert_layout
|
|
backup_current_files
|
|
|
|
trap cleanup_work_dir 0
|
|
extract_release_package
|
|
deploy_backend
|
|
deploy_frontend
|
|
cleanup_work_dir
|
|
trap - 0
|
|
|
|
log_info "部署完成,备份目录: ${BACKUP_DIR}"
|
|
log_info "开始重启后端并输出日志"
|
|
bash "${START_SCRIPT}" restart
|
|
}
|
|
|
|
main "$@"
|