#!/bin/bash # course-web 部署脚本 # 功能:项目构建、文件传输、原子切换、历史版本管理、回滚支持 SERVER_IP="101.200.208.45" USERNAME="root" APP_NAME="course-web" DEPLOY_BASE="/data/www/course-web-deploy" RELEASES_DIR="${DEPLOY_BASE}/releases" LINK_PATH="/data/www/course-of-life" MAX_RELEASES=5 # 打印带颜色的信息 function log_info() { echo -e "\033[32m[INFO] $1\033[0m" } function log_error() { echo -e "\033[31m[ERROR] $1\033[0m" } # 检查环境 function check_env() { log_info "检查本地环境..." if ! command -v npm &> /dev/null; then log_error "未找到npm命令,请先安装Node.js" exit 1 fi if ! command -v scp &> /dev/null; then log_error "未找到scp命令" exit 1 fi } # 构建项目 function build_project() { log_info "开始构建项目..." # 清理旧构建 rm -rf dist # 安装依赖并构建 # npm install # 视情况开启,为了速度暂时注释,假设依赖已安装 if npm run build; then log_info "项目构建成功" else log_error "项目构建失败" exit 1 fi if [ ! -d "dist" ]; then log_error "dist目录不存在" exit 1 fi } # 部署到服务器 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 log_info "文件上传成功" else log_error "文件上传失败" exit 1 fi # 3. 设置权限 ssh "${USERNAME}@${SERVER_IP}" "chmod -R 755 ${RELEASE_PATH}" # 4. 原子切换软链接 log_info "切换服务版本..." # 检查目标路径是否为普通目录(非软链接),如果是则备份并移除,防止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}' " log_info "部署完成!当前版本指向: ${RELEASE_PATH}" # 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() { log_info "开始回滚操作..." # 获取当前指向的版本 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 log_error "没有找到可回滚的历史版本" exit 1 fi log_info "回滚目标版本: ${PREV_VERSION}" ssh "${USERNAME}@${SERVER_IP}" "ln -snf ${PREV_VERSION} ${LINK_PATH}" log_info "回滚成功!" } # 主流程 case "$1" in "rollback") rollback ;; *) check_env build_project deploy ;; esac