admin_front_deploy.sh 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807
  1. #!/bin/bash
  2. # =============================================
  3. # Vue前端应用自动部署脚本
  4. # 功能:从Git拉取最新代码 → 打包编译 → 备份当前部署 → 部署新版本到nginx
  5. # 支持多环境:dev/test/prod
  6. # =============================================
  7. # 设置颜色输出
  8. RED='\033[0;31m'
  9. GREEN='\033[0;32m'
  10. YELLOW='\033[1;33m'
  11. BLUE='\033[0;34m'
  12. PURPLE='\033[0;35m'
  13. CYAN='\033[0;36m'
  14. NC='\033[0m' # No Color
  15. # 日志函数
  16. log_info() {
  17. echo -e "${GREEN}[INFO] $1${NC}"
  18. }
  19. log_warn() {
  20. echo -e "${YELLOW}[WARN] $1${NC}"
  21. }
  22. log_error() {
  23. echo -e "${RED}[ERROR] $1${NC}"
  24. }
  25. log_step() {
  26. echo -e "${BLUE}[STEP] $1${NC}"
  27. }
  28. log_env() {
  29. echo -e "${PURPLE}[ENV] $1${NC}"
  30. }
  31. log_debug() {
  32. echo -e "${CYAN}[DEBUG] $1${NC}"
  33. }
  34. # ================= 配置区域 =================
  35. # 环境配置 (可通过命令行参数覆盖)
  36. ENVIRONMENT="dev" # 默认环境: dev/test/prod
  37. # Git配置
  38. GIT_USER="WangXuMing"
  39. GIT_PASS="123456"
  40. # 环境相关配置
  41. declare -A ENV_CONFIG
  42. # dev环境配置
  43. ENV_CONFIG["dev,branch"]="dev"
  44. ENV_CONFIG["dev,npm_build_cmd"]="build:dev"
  45. ENV_CONFIG["dev,dist_subdir"]="dist-dev"
  46. ENV_CONFIG["dev,backup_prefix"]="frontend_dev"
  47. # test环境配置
  48. ENV_CONFIG["test,branch"]="test"
  49. ENV_CONFIG["test,npm_build_cmd"]="build:test"
  50. ENV_CONFIG["test,dist_subdir"]="dist-test"
  51. ENV_CONFIG["test,backup_prefix"]="frontend_test"
  52. # prod环境配置
  53. ENV_CONFIG["prod,branch"]="master"
  54. ENV_CONFIG["prod,npm_build_cmd"]="build:prod"
  55. ENV_CONFIG["prod,dist_subdir"]="dist"
  56. ENV_CONFIG["prod,backup_prefix"]="frontend_prod"
  57. # 公共配置
  58. SOURCE_DIR="/home/lq/lq_workspace/LQAdminFrontServer/source/LQAdminFront"
  59. NGINX_HTML_DIR="/home/lq/nginx/html" # nginx部署目录
  60. BACKUP_DIR="/home/lq/lq_workspace/deploy_workspace/deploy_bak/LQAdminFrontServer" # 备份目录
  61. TEMP_DEPLOY_DIR="/home/lq/lq_workspace/LQAdminFrontServer/deploy_tmp" # 临时部署目录
  62. # Node.js环境检查
  63. NODE_VERSION=">=14.0.0"
  64. NPM_VERSION=">=6.0.0"
  65. # ================= 功能函数 =================
  66. # 显示使用帮助
  67. show_help() {
  68. echo "=================================================="
  69. echo " Vue前端应用自动部署脚本"
  70. echo "=================================================="
  71. echo ""
  72. echo "使用方法:"
  73. echo " $0 [环境参数]"
  74. echo ""
  75. echo "环境参数:"
  76. echo " dev 开发环境 (默认)"
  77. echo " test 测试环境"
  78. echo " prod 生产环境"
  79. echo " -h, --help 显示帮助信息"
  80. echo ""
  81. echo "示例:"
  82. echo " $0 # 部署开发环境"
  83. echo " $0 test # 部署测试环境"
  84. echo " $0 prod # 部署生产环境"
  85. echo ""
  86. echo "环境配置:"
  87. echo " 开发环境: 分支=dev, 构建命令=npm run build:dev"
  88. echo " 测试环境: 分支=test, 构建命令=npm run build:test"
  89. echo " 生产环境: 分支=master, 构建命令=npm run build:prod"
  90. echo ""
  91. exit 0
  92. }
  93. # 解析命令行参数
  94. parse_arguments() {
  95. if [ $# -gt 0 ]; then
  96. case "$1" in
  97. -h|--help)
  98. show_help
  99. ;;
  100. dev|test|prod)
  101. ENVIRONMENT="$1"
  102. ;;
  103. *)
  104. log_error "未知的环境参数: $1"
  105. show_help
  106. ;;
  107. esac
  108. fi
  109. }
  110. # 获取环境配置
  111. get_env_config() {
  112. local key="$1"
  113. local full_key="${ENVIRONMENT},${key}"
  114. if [ -n "${ENV_CONFIG[$full_key]}" ]; then
  115. echo "${ENV_CONFIG[$full_key]}"
  116. else
  117. log_error "未找到环境配置: $full_key"
  118. exit 1
  119. fi
  120. }
  121. # 初始化环境变量
  122. init_environment() {
  123. log_env "初始化 $ENVIRONMENT 环境配置..."
  124. # 获取环境配置
  125. GIT_BRANCH=$(get_env_config "branch")
  126. NPM_BUILD_CMD=$(get_env_config "npm_build_cmd")
  127. DIST_SUBDIR=$(get_env_config "dist_subdir")
  128. BACKUP_PREFIX=$(get_env_config "backup_prefix")
  129. # 构建输出目录
  130. DIST_DIR="$SOURCE_DIR/$DIST_SUBDIR"
  131. # 显示环境配置
  132. log_info "=================================================="
  133. log_info "环境: $ENVIRONMENT"
  134. log_info "Git分支: $GIT_BRANCH"
  135. log_info "构建命令: npm run $NPM_BUILD_CMD"
  136. log_info "打包目录: $DIST_DIR"
  137. log_info "备份前缀: $BACKUP_PREFIX"
  138. log_info "=================================================="
  139. }
  140. # 检查命令是否存在
  141. check_command() {
  142. if ! command -v "$1" &> /dev/null; then
  143. log_error "命令 $1 未安装,请先安装"
  144. return 1
  145. fi
  146. return 0
  147. }
  148. # 检查目录是否存在,不存在则创建
  149. check_and_create_dir() {
  150. if [ ! -d "$1" ]; then
  151. log_warn "目录不存在,正在创建: $1"
  152. mkdir -p "$1"
  153. if [ $? -eq 0 ]; then
  154. log_info "目录创建成功: $1"
  155. else
  156. log_error "目录创建失败: $1"
  157. exit 1
  158. fi
  159. fi
  160. }
  161. # 检查环境
  162. check_environment() {
  163. log_step "检查部署环境..."
  164. # 检查必要命令
  165. local required_commands=("git" "node" "npm" "unzip")
  166. for cmd in "${required_commands[@]}"; do
  167. if ! check_command "$cmd"; then
  168. exit 1
  169. fi
  170. done
  171. # 检查Node.js版本
  172. local node_version=$(node --version | sed 's/v//')
  173. local npm_version=$(npm --version)
  174. log_info "Node.js版本: $node_version"
  175. log_info "npm版本: $npm_version"
  176. # 检查package.json中的构建脚本
  177. if [ -f "$SOURCE_DIR/package.json" ]; then
  178. log_info "检查package.json构建脚本..."
  179. # 检查当前环境对应的构建命令是否存在
  180. if ! grep -q "\"$NPM_BUILD_CMD\"" "$SOURCE_DIR/package.json"; then
  181. log_warn "未在package.json中找到构建脚本: $NPM_BUILD_CMD"
  182. log_info "可用的构建脚本:"
  183. grep '"build' "$SOURCE_DIR/package.json" | sed 's/^/ /'
  184. # 尝试使用默认的build命令
  185. if grep -q '"build"' "$SOURCE_DIR/package.json"; then
  186. log_warn "将使用默认的 build 命令"
  187. NPM_BUILD_CMD="build"
  188. else
  189. log_error "未找到可用的构建脚本"
  190. exit 1
  191. fi
  192. fi
  193. else
  194. log_warn "未找到package.json文件,将在后续步骤中检查"
  195. fi
  196. # 检查目录
  197. check_and_create_dir "$SOURCE_DIR"
  198. check_and_create_dir "$BACKUP_DIR"
  199. check_and_create_dir "$TEMP_DEPLOY_DIR"
  200. check_and_create_dir "$NGINX_HTML_DIR"
  201. log_info "环境检查完成"
  202. }
  203. # Git拉取最新代码
  204. git_pull_latest() {
  205. log_step "步骤 1: 从Git拉取最新代码 ($GIT_BRANCH 分支)..."
  206. if [ ! -d "$SOURCE_DIR" ]; then
  207. log_error "源码目录不存在: $SOURCE_DIR"
  208. exit 1
  209. fi
  210. cd "$SOURCE_DIR" || {
  211. log_error "进入源码目录失败: $SOURCE_DIR"
  212. exit 1
  213. }
  214. # 检查是否为Git仓库
  215. if [ ! -d ".git" ]; then
  216. log_error "当前目录不是Git仓库: $SOURCE_DIR"
  217. exit 1
  218. fi
  219. # 获取当前分支
  220. local current_branch=$(git branch --show-current 2>/dev/null)
  221. log_info "当前分支: ${current_branch:-未设置}"
  222. # 检查本地修改
  223. log_info "检查本地修改..."
  224. local has_changes=$(git status --porcelain)
  225. if [ -n "$has_changes" ]; then
  226. log_warn "发现本地修改:"
  227. echo "$has_changes" | while read line; do
  228. log_info " - $line"
  229. done
  230. # 询问是否暂存修改
  231. if [ "$ENVIRONMENT" == "prod" ]; then
  232. # 生产环境必须清理修改
  233. log_info "生产环境:强制清理本地修改..."
  234. git checkout -- .
  235. git clean -fd
  236. else
  237. read -p "是否暂存这些修改?(y/N): " -n 1 -r
  238. echo
  239. if [[ $REPLY =~ ^[Yy]$ ]]; then
  240. git stash
  241. log_info "本地修改已暂存"
  242. else
  243. log_warn "跳过暂存,继续执行..."
  244. fi
  245. fi
  246. fi
  247. # 获取远程URL
  248. local origin_url=$(git remote get-url origin 2>/dev/null)
  249. if [ $? -ne 0 ]; then
  250. log_error "获取Git远程地址失败"
  251. exit 1
  252. fi
  253. # 构造认证URL
  254. local clean_url=${origin_url#*://}
  255. local auth_url="http://${GIT_USER}:${GIT_PASS}@${clean_url}"
  256. # 拉取最新代码
  257. log_info "正在切换到分支: $GIT_BRANCH"
  258. git checkout "$GIT_BRANCH" 2>/dev/null || {
  259. log_warn "分支 $GIT_BRANCH 不存在,正在创建并跟踪远程分支..."
  260. git fetch origin "$GIT_BRANCH"
  261. git checkout -b "$GIT_BRANCH" "origin/$GIT_BRANCH" || {
  262. log_error "无法切换到分支 $GIT_BRANCH"
  263. exit 1
  264. }
  265. }
  266. local max_retries=3
  267. local retry_count=0
  268. local pull_success=0
  269. while [ $retry_count -lt $max_retries ]; do
  270. log_info "尝试拉取代码 (第 $((retry_count+1)) 次)..."
  271. git pull "$auth_url" "$GIT_BRANCH" --force --allow-unrelated-histories
  272. if [ $? -eq 0 ]; then
  273. pull_success=1
  274. break
  275. fi
  276. retry_count=$((retry_count+1))
  277. log_warn "拉取失败,3秒后重试..."
  278. sleep 3
  279. done
  280. if [ $pull_success -eq 1 ]; then
  281. # 显示最新提交信息
  282. local latest_commit=$(git log -1 --format="%h - %an - %ad - %s" --date=format:"%Y-%m-%d %H:%M:%S")
  283. log_info "✓ Git拉取成功"
  284. log_info "最新提交: $latest_commit"
  285. # 显示最近3次提交
  286. log_info "最近3次提交记录:"
  287. git log -3 --format=" %h - %ad - %s" --date=format:"%m-%d %H:%M" | while read line; do
  288. log_info "$line"
  289. done
  290. # 显示分支信息
  291. log_info "当前分支状态:"
  292. git log --oneline -5 --graph --decorate
  293. else
  294. log_error "Git拉取失败,已达到最大重试次数"
  295. exit 1
  296. fi
  297. }
  298. # 安装依赖和打包
  299. build_project() {
  300. log_step "步骤 2: 安装依赖并打包项目 ($NPM_BUILD_CMD)..."
  301. cd "$SOURCE_DIR" || {
  302. log_error "进入源码目录失败"
  303. exit 1
  304. }
  305. # 检查package.json是否存在
  306. if [ ! -f "package.json" ]; then
  307. log_error "未找到package.json文件"
  308. exit 1
  309. fi
  310. # 显示当前环境变量(可选)
  311. if [ "$ENVIRONMENT" == "prod" ]; then
  312. log_info "生产环境构建,将使用生产配置"
  313. # 可以在这里设置生产环境的环境变量
  314. export NODE_ENV=production
  315. elif [ "$ENVIRONMENT" == "test" ]; then
  316. log_info "测试环境构建"
  317. export NODE_ENV=test
  318. else
  319. log_info "开发环境构建"
  320. export NODE_ENV=development
  321. fi
  322. # 显示构建配置
  323. log_info "当前NODE_ENV: ${NODE_ENV:-未设置}"
  324. # 安装依赖
  325. log_info "正在安装依赖..."
  326. # 检查是否有package-lock.json或yarn.lock
  327. if [ -f "package-lock.json" ]; then
  328. log_info "使用 package-lock.json 安装依赖"
  329. npm ci --registry=https://registry.npm.taobao.org
  330. else
  331. log_info "使用 package.json 安装依赖"
  332. npm install --registry=https://registry.npm.taobao.org
  333. fi
  334. if [ $? -ne 0 ]; then
  335. log_error "依赖安装失败"
  336. exit 1
  337. fi
  338. log_info "✓ 依赖安装成功"
  339. # 执行打包
  340. log_info "正在执行构建命令: npm run $NPM_BUILD_CMD"
  341. # 记录构建开始时间
  342. local build_start=$(date +%s)
  343. # 执行构建命令
  344. npm run "$NPM_BUILD_CMD"
  345. local build_exit_code=$?
  346. # 记录构建结束时间
  347. local build_end=$(date +%s)
  348. local build_duration=$((build_end - build_start))
  349. if [ $build_exit_code -eq 0 ]; then
  350. log_info "✓ 项目构建成功 (耗时: ${build_duration}秒)"
  351. # 检查打包结果
  352. if [ -d "$DIST_DIR" ]; then
  353. local file_count=$(find "$DIST_DIR" -type f | wc -l)
  354. local dir_size=$(du -sh "$DIST_DIR" | cut -f1)
  355. log_info "打包目录: $DIST_DIR"
  356. log_info "文件数量: $file_count 个"
  357. log_info "目录大小: $dir_size"
  358. # 显示关键文件
  359. log_info "关键文件检查:"
  360. if [ -f "$DIST_DIR/index.html" ]; then
  361. local html_size=$(du -h "$DIST_DIR/index.html" | cut -f1)
  362. log_info "✓ index.html (${html_size})"
  363. else
  364. log_error "✗ 未找到index.html"
  365. exit 1
  366. fi
  367. if [ -d "$DIST_DIR/assets" ]; then
  368. local assets_count=$(find "$DIST_DIR/assets" -type f | wc -l)
  369. local assets_size=$(du -sh "$DIST_DIR/assets" | cut -f1)
  370. log_info "✓ assets目录 (${assets_count}个文件, ${assets_size})"
  371. else
  372. log_warn "⚠ 未找到assets目录"
  373. fi
  374. # 显示主要文件类型统计
  375. log_info "文件类型统计:"
  376. local js_count=$(find "$DIST_DIR" -name "*.js" -type f | wc -l)
  377. local css_count=$(find "$DIST_DIR" -name "*.css" -type f | wc -l)
  378. local img_count=$(find "$DIST_DIR" \( -name "*.jpg" -o -name "*.png" -o -name "*.gif" -o -name "*.svg" -o -name "*.webp" \) -type f | wc -l)
  379. log_info " JS文件: $js_count 个"
  380. log_info " CSS文件: $css_count 个"
  381. log_info " 图片文件: $img_count 个"
  382. else
  383. log_error "打包目录不存在: $DIST_DIR"
  384. exit 1
  385. fi
  386. else
  387. log_error "项目构建失败 (退出码: $build_exit_code)"
  388. exit 1
  389. fi
  390. }
  391. # 备份当前部署
  392. backup_current_deployment() {
  393. log_step "步骤 3: 备份当前部署..."
  394. # 检查nginx目录是否为空
  395. if [ ! -d "$NGINX_HTML_DIR" ] || [ -z "$(ls -A $NGINX_HTML_DIR 2>/dev/null)" ]; then
  396. log_warn "nginx部署目录为空,跳过备份"
  397. return 0
  398. fi
  399. # 创建备份
  400. local current_time=$(date "+%Y%m%d_%H%M%S")
  401. local backup_filename="${BACKUP_PREFIX}_${current_time}.zip"
  402. local backup_path="$BACKUP_DIR/$backup_filename"
  403. cd "$NGINX_HTML_DIR" || {
  404. log_error "进入nginx目录失败"
  405. exit 1
  406. }
  407. # 检查是否有需要备份的文件
  408. if [ ! -f "index.html" ] && [ ! -d "assets" ]; then
  409. log_warn "未找到index.html和assets目录,跳过备份"
  410. return 0
  411. fi
  412. log_info "正在创建备份文件: $backup_filename"
  413. # 记录备份开始时间
  414. local backup_start=$(date +%s)
  415. # 创建备份压缩包(排除隐藏文件和临时文件)
  416. find . -maxdepth 1 -type f -name "*.html" -o -name "*.js" -o -name "*.css" | zip -q "$backup_path" -@
  417. if [ -d "assets" ]; then
  418. zip -qr "$backup_path" assets
  419. fi
  420. local backup_exit_code=$?
  421. # 记录备份结束时间
  422. local backup_end=$(date +%s)
  423. local backup_duration=$((backup_end - backup_start))
  424. if [ $backup_exit_code -eq 0 ]; then
  425. local backup_size=$(du -h "$backup_path" | cut -f1)
  426. log_info "✓ 备份创建成功 (耗时: ${backup_duration}秒)"
  427. log_info "备份文件: $backup_path"
  428. log_info "文件大小: $backup_size"
  429. # 显示备份目录信息
  430. local backup_files=$(ls -1 "$BACKUP_DIR/${BACKUP_PREFIX}_"*.zip 2>/dev/null | wc -l)
  431. log_info "当前环境备份文件数: $backup_files 个"
  432. # 如果备份文件超过10个,删除最旧的5个
  433. if [ $backup_files -gt 10 ]; then
  434. log_info "清理旧备份文件..."
  435. ls -1t "$BACKUP_DIR/${BACKUP_PREFIX}_"*.zip | tail -n 5 | xargs -I {} rm -f {}
  436. log_info "已清理5个旧备份"
  437. fi
  438. # 显示所有环境的备份统计
  439. log_info "所有环境备份统计:"
  440. local total_backups=$(ls -1 "$BACKUP_DIR/"*.zip 2>/dev/null | wc -l)
  441. log_info " 总备份数: $total_backups 个"
  442. for env in dev test prod; do
  443. local env_backups=$(ls -1 "$BACKUP_DIR/frontend_${env}_"*.zip 2>/dev/null | wc -l)
  444. if [ $env_backups -gt 0 ]; then
  445. log_info " ${env}: $env_backups 个"
  446. fi
  447. done
  448. else
  449. log_error "备份创建失败"
  450. exit 1
  451. fi
  452. }
  453. # 准备部署文件
  454. prepare_deployment() {
  455. log_step "步骤 4: 准备部署文件..."
  456. # 清理临时部署目录
  457. log_info "清理临时部署目录..."
  458. rm -rf "$TEMP_DEPLOY_DIR"/*
  459. # 复制打包文件到临时目录
  460. log_info "从 $DIST_DIR 复制文件到 $TEMP_DEPLOY_DIR..."
  461. cp -r "$DIST_DIR"/* "$TEMP_DEPLOY_DIR/"
  462. if [ $? -eq 0 ]; then
  463. local temp_file_count=$(find "$TEMP_DEPLOY_DIR" -type f | wc -l)
  464. local temp_dir_size=$(du -sh "$TEMP_DEPLOY_DIR" | cut -f1)
  465. log_info "✓ 部署文件准备完成"
  466. log_info "临时目录文件数量: $temp_file_count 个"
  467. log_info "临时目录大小: $temp_dir_size"
  468. log_info "临时目录: $TEMP_DEPLOY_DIR"
  469. # 显示临时目录结构
  470. if [ "$ENVIRONMENT" == "dev" ]; then
  471. log_debug "临时目录结构:"
  472. ls -la "$TEMP_DEPLOY_DIR" | head -20
  473. fi
  474. else
  475. log_error "部署文件准备失败"
  476. exit 1
  477. fi
  478. }
  479. # 部署到Nginx
  480. deploy_to_nginx() {
  481. log_step "步骤 5: 部署到Nginx ($ENVIRONMENT 环境)..."
  482. # 检查Nginx目录权限
  483. if [ ! -w "$NGINX_HTML_DIR" ]; then
  484. log_error "Nginx目录无写权限: $NGINX_HTML_DIR"
  485. exit 1
  486. fi
  487. # 清理nginx目录(先备份到临时目录)
  488. log_info "准备部署到Nginx目录: $NGINX_HTML_DIR"
  489. # 创建临时备份目录
  490. local nginx_backup_dir="/tmp/nginx_${ENVIRONMENT}_backup_$(date +%Y%m%d_%H%M%S)"
  491. mkdir -p "$nginx_backup_dir"
  492. # 备份当前文件(如果有)
  493. if [ -n "$(ls -A $NGINX_HTML_DIR 2>/dev/null)" ]; then
  494. log_info "备份当前Nginx文件到: $nginx_backup_dir"
  495. mv "$NGINX_HTML_DIR"/* "$nginx_backup_dir/" 2>/dev/null || true
  496. fi
  497. # 复制新文件
  498. log_info "复制新版本文件到Nginx..."
  499. cp -r "$TEMP_DEPLOY_DIR"/* "$NGINX_HTML_DIR/"
  500. if [ $? -eq 0 ]; then
  501. log_info "✓ 文件复制完成"
  502. # 设置文件权限
  503. log_info "设置文件权限..."
  504. chmod -R 755 "$NGINX_HTML_DIR"
  505. chown -R lq:lq "$NGINX_HTML_DIR" 2>/dev/null || {
  506. log_warn "无法更改文件所有者,跳过此步骤"
  507. }
  508. # 验证部署
  509. log_info "验证部署结果..."
  510. local verification_passed=1
  511. if [ -f "$NGINX_HTML_DIR/index.html" ]; then
  512. local index_size=$(du -h "$NGINX_HTML_DIR/index.html" | cut -f1)
  513. log_info "✓ index.html 存在 (${index_size})"
  514. else
  515. log_error "✗ index.html 不存在"
  516. verification_passed=0
  517. fi
  518. if [ -d "$NGINX_HTML_DIR/assets" ]; then
  519. local asset_count=$(find "$NGINX_HTML_DIR/assets" -type f | wc -l)
  520. log_info "✓ assets 目录存在,包含 $asset_count 个文件"
  521. else
  522. log_warn "⚠ assets 目录不存在"
  523. fi
  524. # 检查静态文件
  525. local static_files=("favicon.ico" "manifest.json" "robots.txt")
  526. for file in "${static_files[@]}"; do
  527. if [ -f "$NGINX_HTML_DIR/$file" ]; then
  528. log_info "✓ $file 存在"
  529. fi
  530. done
  531. if [ $verification_passed -eq 0 ]; then
  532. log_error "部署验证失败"
  533. # 恢复备份
  534. log_info "正在恢复备份..."
  535. rm -rf "$NGINX_HTML_DIR"/*
  536. if [ -n "$(ls -A $nginx_backup_dir 2>/dev/null)" ]; then
  537. cp -r "$nginx_backup_dir"/* "$NGINX_HTML_DIR/"
  538. log_info "已恢复原文件"
  539. fi
  540. exit 1
  541. fi
  542. log_info "✓ 部署验证通过"
  543. # 清理临时备份
  544. rm -rf "$nginx_backup_dir"
  545. log_info "临时备份已清理"
  546. else
  547. log_error "文件复制失败"
  548. # 恢复备份
  549. log_info "正在恢复备份..."
  550. if [ -n "$(ls -A $nginx_backup_dir 2>/dev/null)" ]; then
  551. rm -rf "$NGINX_HTML_DIR"/*
  552. cp -r "$nginx_backup_dir"/* "$NGINX_HTML_DIR/"
  553. log_info "已恢复原文件"
  554. fi
  555. exit 1
  556. fi
  557. }
  558. # 清理临时文件
  559. cleanup_temp_files() {
  560. log_step "步骤 6: 清理临时文件..."
  561. # 清理临时部署目录
  562. log_info "清理临时部署目录..."
  563. rm -rf "$TEMP_DEPLOY_DIR"/*
  564. log_info "临时部署目录已清理"
  565. # 可选:清理node_modules缓存(谨慎使用)
  566. if [ "$ENVIRONMENT" == "prod" ]; then
  567. log_info "生产环境:清理npm缓存..."
  568. npm cache clean --force
  569. fi
  570. log_info "✓ 清理完成"
  571. }
  572. # 部署后验证
  573. post_deployment_validation() {
  574. log_step "步骤 7: 部署后验证..."
  575. log_info "==================== 部署详情 ===================="
  576. log_info "部署环境: $ENVIRONMENT"
  577. log_info "部署时间: $(date)"
  578. log_info "Git分支: $GIT_BRANCH"
  579. log_info "构建命令: npm run $NPM_BUILD_CMD"
  580. log_info "源码目录: $SOURCE_DIR"
  581. log_info "Nginx目录: $NGINX_HTML_DIR"
  582. log_info "备份目录: $BACKUP_DIR"
  583. # 显示部署文件统计
  584. log_info "部署文件统计:"
  585. local html_count=$(find "$NGINX_HTML_DIR" -name "*.html" -type f | wc -l)
  586. local js_count=$(find "$NGINX_HTML_DIR" -name "*.js" -type f | wc -l)
  587. local css_count=$(find "$NGINX_HTML_DIR" -name "*.css" -type f | wc -l)
  588. local img_count=$(find "$NGINX_HTML_DIR" \( -name "*.jpg" -o -name "*.png" -o -name "*.gif" -o -name "*.svg" -o -name "*.webp" \) -type f | wc -l)
  589. local total_files=$(find "$NGINX_HTML_DIR" -type f | wc -l)
  590. log_info " HTML文件: $html_count 个"
  591. log_info " JS文件: $js_count 个"
  592. log_info " CSS文件: $css_count 个"
  593. log_info " 图片文件: $img_count 个"
  594. log_info " 总文件数: $total_files 个"
  595. # 显示目录大小
  596. local dir_size=$(du -sh "$NGINX_HTML_DIR" | cut -f1)
  597. log_info " 目录大小: $dir_size"
  598. # 显示关键文件信息
  599. log_info "关键文件:"
  600. for file in index.html main.js app.css; do
  601. if [ -f "$NGINX_HTML_DIR/$file" ]; then
  602. local file_size=$(du -h "$NGINX_HTML_DIR/$file" | cut -f1)
  603. log_info " ✓ $file (${file_size})"
  604. fi
  605. done
  606. log_info "=================================================="
  607. # 显示最新的Git提交
  608. cd "$SOURCE_DIR" && git log -1 --format="最新提交: %h - %an - %ad - %s" --date=format:"%Y-%m-%d %H:%M:%S"
  609. log_info "${GREEN}✅ Vue前端应用 ($ENVIRONMENT 环境) 部署完成!${NC}"
  610. # 输出环境特定的建议
  611. echo ""
  612. log_info "后续操作建议:"
  613. log_info "1. 重新加载Nginx配置: sudo nginx -s reload"
  614. case "$ENVIRONMENT" in
  615. "prod")
  616. log_info "2. 生产环境建议执行: sudo systemctl restart nginx"
  617. log_info "3. 访问地址: https://your-production-domain.com"
  618. ;;
  619. "test")
  620. log_info "2. 访问测试地址: http://test.your-domain.com"
  621. log_info "3. 测试完成后可执行: $0 prod 部署到生产环境"
  622. ;;
  623. "dev")
  624. log_info "2. 访问开发地址: http://dev.your-domain.com"
  625. log_info "3. 查看构建日志: tail -f $SOURCE_DIR/build.log"
  626. ;;
  627. esac
  628. log_info "4. 查看Nginx日志: sudo tail -f /var/log/nginx/error.log"
  629. log_info "5. 查看访问日志: sudo tail -f /var/log/nginx/access.log"
  630. }
  631. # ================= 主程序 =================
  632. main() {
  633. # 解析命令行参数
  634. parse_arguments "$@"
  635. # 显示部署信息
  636. echo "=================================================="
  637. echo " Vue前端应用自动部署脚本"
  638. echo " 环境: $ENVIRONMENT"
  639. echo "=================================================="
  640. # 记录开始时间
  641. local start_time=$(date +%s)
  642. log_info "部署开始时间: $(date)"
  643. # 初始化环境配置
  644. init_environment
  645. # 执行部署流程
  646. check_environment
  647. git_pull_latest
  648. build_project
  649. backup_current_deployment
  650. prepare_deployment
  651. deploy_to_nginx
  652. cleanup_temp_files
  653. post_deployment_validation
  654. # 计算执行时间
  655. local end_time=$(date +%s)
  656. local duration=$((end_time - start_time))
  657. local minutes=$((duration / 60))
  658. local seconds=$((duration % 60))
  659. log_info "总执行时间: ${duration}秒 (${minutes}分${seconds}秒)"
  660. echo ""
  661. log_info "${GREEN}🎉 $ENVIRONMENT 环境所有部署步骤已完成!${NC}"
  662. # 添加完成时间戳
  663. log_info "部署完成时间: $(date)"
  664. }
  665. # 脚本入口
  666. main "$@"