部署脚本修复

This commit is contained in:
2025-12-21 18:07:31 +08:00
parent 3c102aaa7e
commit 6b9b74c9e4
3 changed files with 135 additions and 82 deletions
+22 -2
View File
@@ -47,6 +47,7 @@ check_jar() {
# 停止旧服务 # 停止旧服务
stop_service() { stop_service() {
# 1. 尝试通过 PID 文件停止
if [ -f "$PID_FILE" ]; then if [ -f "$PID_FILE" ]; then
PID=$(cat "$PID_FILE") PID=$(cat "$PID_FILE")
if ps -p "$PID" > /dev/null 2>&1; then if ps -p "$PID" > /dev/null 2>&1; then
@@ -71,8 +72,27 @@ stop_service() {
log_warn "PID 文件存在但进程不存在,清理 PID 文件" log_warn "PID 文件存在但进程不存在,清理 PID 文件"
fi fi
rm -f "$PID_FILE" rm -f "$PID_FILE"
else fi
log_info "没有找到 PID 文件,服务可能未运行"
# 2. 双重检查:通过进程名查找并停止(防止 PID 文件丢失的情况)
PIDS=$(ps aux | grep "$JAR_NAME" | grep -v grep | awk '{print $2}')
if [ -n "$PIDS" ]; then
log_warn "检测到残留进程 (PIDs: $PIDS),正在清理..."
for PID in $PIDS; do
log_info "停止残留进程 $PID"
kill "$PID" 2>/dev/null || true
done
sleep 5
# 再次检查并强制停止
PIDS=$(ps aux | grep "$JAR_NAME" | grep -v grep | awk '{print $2}')
if [ -n "$PIDS" ]; then
for PID in $PIDS; do
log_warn "强制停止残留进程 $PID"
kill -9 "$PID" 2>/dev/null || true
done
fi
fi fi
} }
+1 -1
View File
@@ -275,7 +275,7 @@ show_remote_info() {
# 检查远程服务状态 # 检查远程服务状态
log_info "检查远程服务状态..." log_info "检查远程服务状态..."
ssh $REMOTE_USER@$REMOTE_HOST "ps aux | grep $JAR_NAME | grep -v grep" || log_info "远程服务未运行" ssh $REMOTE_USER@$REMOTE_HOST "ps aux | grep $REMOTE_JAR_NAME | grep -v grep" || log_info "远程服务未运行"
} }
# 本地部署 - 主函数 # 本地部署 - 主函数
+87 -54
View File
@@ -1,100 +1,133 @@
#!/bin/bash #!/bin/bash
# 部署脚本 - 将构建好的 course-web 前端项目上传到服务器 # course-web 部署脚本
# 支持版本管理回滚 # 功能:项目构建、文件传输、原子切换、历史版本管理回滚支持
# 使用方法: ./deploy.sh [deploy|rollback]
SERVER_IP="101.200.208.45" SERVER_IP="101.200.208.45"
USERNAME="root" USERNAME="root"
REMOTE_ROOT="/data/www" APP_NAME="course-web"
APP_NAME="course-of-life" DEPLOY_BASE="/data/www/course-web-deploy"
DEPLOY_ROOT="${REMOTE_ROOT}/${APP_NAME}-releases" RELEASES_DIR="${DEPLOY_BASE}/releases"
SYMLINK_PATH="${REMOTE_ROOT}/${APP_NAME}" LINK_PATH="/data/www/course-of-life"
MAX_RELEASES=5
TIMESTAMP=$(date +%Y%m%d%H%M%S) # 打印带颜色的信息
RELEASE_PATH="${DEPLOY_ROOT}/${TIMESTAMP}" function log_info() {
echo -e "\033[32m[INFO] $1\033[0m"
}
function deploy() { function log_error() {
echo "🚀 开始部署 ${APP_NAME} 到服务器..." echo -e "\033[31m[ERROR] $1\033[0m"
}
# 1. 环境检查 # 检查环境
function check_env() {
log_info "检查本地环境..."
if ! command -v npm &> /dev/null; then if ! command -v npm &> /dev/null; then
echo "❌ 错误: 未找到npm命令" log_error "未找到npm命令,请先安装Node.js"
exit 1 exit 1
fi fi
if ! command -v scp &> /dev/null; then
log_error "未找到scp命令"
exit 1
fi
}
# 2. 项目构建 # 构建项目
echo "🧹 清理旧构建..." function build_project() {
log_info "开始构建项目..."
# 清理旧构建
rm -rf dist rm -rf dist
echo "📦 开始构建..." # 安装依赖并构建
if ! npm run build; then # npm install # 视情况开启,为了速度暂时注释,假设依赖已安装
echo "❌ 构建失败" if npm run build; then
log_info "项目构建成功"
else
log_error "项目构建失败"
exit 1 exit 1
fi fi
if [ ! -d "dist" ]; then if [ ! -d "dist" ]; then
echo "❌ 错误: dist目录不存在" log_error "dist目录不存在"
exit 1 exit 1
fi fi
# 3. 准备远程目录
echo "📁 准备远程目录: ${RELEASE_PATH}"
ssh "${USERNAME}@${SERVER_IP}" "mkdir -p ${RELEASE_PATH}" || {
echo "❌ 无法创建远程目录"
exit 1
} }
# 4. 上传文件 # 部署到服务器
echo "📤 上传文件..." function deploy() {
TIMESTAMP=$(date +%Y%m%d%H%M%S)
RELEASE_PATH="${RELEASES_DIR}/${TIMESTAMP}"
log_info "准备部署版本: ${TIMESTAMP}"
# 1. 创建远程目录结构
ssh "${USERNAME}@${SERVER_IP}" "mkdir -p ${RELEASE_PATH}"
# 2. 上传文件
log_info "上传文件到服务器..."
if scp -r dist/* "${USERNAME}@${SERVER_IP}:${RELEASE_PATH}/"; then if scp -r dist/* "${USERNAME}@${SERVER_IP}:${RELEASE_PATH}/"; then
echo "文件上传成功" log_info "文件上传成功"
else else
echo "文件上传失败" log_error "文件上传失败"
# 清理失败的发布目录
ssh "${USERNAME}@${SERVER_IP}" "rm -rf ${RELEASE_PATH}"
exit 1 exit 1
fi fi
# 5. 切换版本 (原子操作) # 3. 设置权限
echo "🔄 切换当前版本..."
# ln -sfn: force update symlink
ssh "${USERNAME}@${SERVER_IP}" "ln -sfn ${RELEASE_PATH} ${SYMLINK_PATH}" || {
echo "❌ 版本切换失败"
exit 1
}
# 6. 权限修正
ssh "${USERNAME}@${SERVER_IP}" "chmod -R 755 ${RELEASE_PATH}" ssh "${USERNAME}@${SERVER_IP}" "chmod -R 755 ${RELEASE_PATH}"
# 7. 清理旧版本 (保留最近5个) # 4. 原子切换软链接
echo "🧹 清理旧版本..." log_info "切换服务版本..."
ssh "${USERNAME}@${SERVER_IP}" "cd ${DEPLOY_ROOT} && ls -t | tail -n +6 | xargs -I {} rm -rf {}" # 检查目标路径是否为普通目录(非软链接),如果是则备份并移除,防止ln失败
ssh "${USERNAME}@${SERVER_IP}" "
if [ -d '${LINK_PATH}' ] && [ ! -L '${LINK_PATH}' ]; then
echo '检测到目标路径为普通目录,进行备份...'
mv '${LINK_PATH}' '${LINK_PATH}_backup_$(date +%s)'
fi
ln -snf '${RELEASE_PATH}' '${LINK_PATH}'
"
echo "部署完成!" log_info "部署完成!当前版本指向: ${RELEASE_PATH}"
echo "🌍 访问地址: http://${SERVER_IP}/${APP_NAME}/"
# 5. 清理旧版本
clean_old_releases
} }
# 清理旧版本,只保留最近的N个
function clean_old_releases() {
log_info "清理旧版本(保留最近${MAX_RELEASES}个)..."
ssh "${USERNAME}@${SERVER_IP}" "
cd ${RELEASES_DIR} && ls -t | tail -n +$((${MAX_RELEASES} + 1)) | xargs -I {} rm -rf {}
"
}
# 回滚到上一个版本
function rollback() { function rollback() {
echo "Reverting to previous version..." log_info "开始回滚操作..."
# 获取倒数第二个版本目录 # 获取当前指向的版本
PREV_VERSION=$(ssh "${USERNAME}@${SERVER_IP}" "cd ${DEPLOY_ROOT} && ls -t | head -n 2 | tail -n 1") CURRENT_LINK=$(ssh "${USERNAME}@${SERVER_IP}" "readlink ${LINK_PATH}")
log_info "当前版本: ${CURRENT_LINK}"
# 获取上一个版本目录
PREV_VERSION=$(ssh "${USERNAME}@${SERVER_IP}" "ls -dt ${RELEASES_DIR}/* | grep -v '${CURRENT_LINK}' | head -n 1")
if [ -z "$PREV_VERSION" ]; then if [ -z "$PREV_VERSION" ]; then
echo "❌ 没有可回滚的版本" log_error "没有找到可回滚的历史版本"
exit 1 exit 1
fi fi
echo "🔄 回滚到版本: ${PREV_VERSION}" log_info "回滚目标版本: ${PREV_VERSION}"
ssh "${USERNAME}@${SERVER_IP}" "ln -sfn ${DEPLOY_ROOT}/${PREV_VERSION} ${SYMLINK_PATH}" && \ ssh "${USERNAME}@${SERVER_IP}" "ln -snf ${PREV_VERSION} ${LINK_PATH}"
echo "回滚成功" || echo "❌ 回滚失败" log_info "回滚成功"
} }
# 主逻辑 # 主流程
case "$1" in case "$1" in
rollback) "rollback")
rollback rollback
;; ;;
*) *)
check_env
build_project
deploy deploy
;; ;;
esac esac