自动化部署脚本教程:前端项目的自动打包、上传与部署

前言

在实际项目开发中,并不是所有项目都会配置 CI/CD 流程,特别是在中小型团队或者公司内部测试环境中,很多时候我们仍然需要手动打包、上传和部署项目。这个过程虽然简单,但往往是重复性强且浪费时间还容易出错,尤其是当项目规模较大时,整个流程会变得非常耗时和繁琐。

为了解决这些问题,我们可以编写一个自动化脚本,将项目的打包、上传及部署等一系列步骤自动化,这样可以减少重复性工作,节省时间,提高效率。接下来,我将详细介绍如何通过 Shell 脚本来实现这一流程的自动化。


思路与流程

手动部署一个前端项目的典型步骤包括:

  1. 执行 npm run build 打包前端项目。
  2. 将打好的项目打成压缩包(如 .tar 包)。
  3. 使用 scp 命令将压缩包上传到服务器。
  4. 登录到服务器,解压并替换掉当前的前端项目包。
  5. 执行一些后续清理操作,必要时重启服务。

这些步骤虽然不复杂,但手动执行时耗时且容易出错,尤其是等待项目打包和文件上传时,可能会耗费大量时间。

通过编写一个自动化脚本,我们可以将上述步骤脚本化,并利用工具如 sshpass 实现免交互式的密码输入,进一步简化流程。


脚本实现

由于我使用的是 Mac 操作系统,且 Shell 脚本能很好地满足需求,因此这里选用 Shell 来实现自动化。

1. 打包前端项目

打包前端项目的命令很简单,直接通过 npm run build 即可。考虑到有些服务器上可能没有安装压缩工具,我们使用通用的 tar 命令来打包生成的 dist 文件夹。

bash 复制代码
npm run build
tar -cvf dist.tar dist

2. 上传前端项目

打包完成后,我们我们使用 scp 命令上传项目到远程服务器,scp 命令用于在本地和远程服务器之间传输文件。

bash 复制代码
scp dist.tar root@服务器IP:/usr/frontend

这行代码会将打包后的 dist.tar 文件传输到服务器的 /usr/frontend 目录。

3. 远程执行换包操作

在文件上传成功后,我们需要登录到服务器,解压并替换当前的前端项目包。通过 ssh 命令,我们可以远程执行这些操作。为了传递多行命令,我们使用 EOF 标记符号将脚本内容传递到服务器。

bash 复制代码
ssh "root@服务器IP" "bash -s" <<EOF
$REMOTE_SCRIPT
EOF

在服务器上执行的具体脚本如下:

bash 复制代码
REMOTE_SCRIPT=$(cat << EOF
#!/bin/bash

# 进入前端项目部署目录
cd /usr/frontend

# 解压 tar 包
tar -xvf dist.tar
if [ $? -ne 0 ]; then
  echo "错误: dist.tar 解压失败"
  exit 1
fi

# 替换掉前端项目包
rm -rf html
mv dist html

# 如果使用了 Docker,需要重启前端服务
docker restart frontend_web
EOF
)

这个脚本解压上传的 dist.tar 包,删除旧的 html 目录并将新的 dist 目录替换为 html,然后重启 Docker 中的前端服务。

4. 传递密码

通常每次执行 sshscp 命令时都需要输入密码,为了避免每次手动输入密码,我们可以使用 sshpass 工具。sshpass 可以通过命令行传递密码,免去交互式输入的麻烦。

[!NOTE] sshpass 是一个独立的命令行工具,需要手动安装。可以通过包管理器(如 apt, brew)来安装:

bash 复制代码
brew install sshpass   # Mac 安装
apt-get install sshpass   # Ubuntu/Debian 安装

安装好 sshpass 后,我们只需在 scpssh 命令前加上 sshpass 命令即可:

bash 复制代码
sshpass -p "your_password" scp dist.tar root@服务器IP:/usr/frontend
sshpass -p "your_password" ssh "root@服务器IP" "bash -s" <<EOF
$REMOTE_SCRIPT
EOF

这样就可以避免每次输入密码的麻烦,脚本会自动使用提供的密码登录远程服务器。

5. 代码优化

上面只是脚本中主要的运行命令,为了运行脚本时有更好的容错和错误提示,我们对脚本做一些优化

提取常量

我们将服务器的信息,还有打包的名称全部提取成常量,方便脚本复用时更换信息,同时通过执行脚本时传入参数的方式接收服务器密码,避免明文保存密码的问题。

shell 复制代码
# 获取脚本所在目录  
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"  
  
# 获取脚本所在目录的上一级目录  
PARENT_DIR="$(dirname "$SCRIPT_DIR")"  
  
# 本地 tar 文件名称  
LOCAL_TAR_FILE="dist.tar"  
  
# 远程服务器信息  
REMOTE_USER="root"                  # 远程服务器用户  
REMOTE_HOST=""                      # 远程服务器 IP
REMOTE_PORT="22"                    # 远程服务器 ssh 端口  
REMOTE_PASSWORD="$1"                # 远程服务器密码  
REMOTE_DIR="/usr/frontend/"         # 远程服务器文件传输目录  

错误提示

为了避免执行命令时输出一些没什么用的信息,比如打包信息、解压信息等,我们可以通过 > /dev/null 2>&1 命令不在控制台展示日志输出,同时封装一个检查命令报错的函数。

shell 复制代码
check_success() {  
  if [ $? -ne 0 ]; then  
    echo "错误: $1"  
    exit 1  
  fi  
}  

当执行完一个命令时,我们可以通过 check_success "xxx命令执行失败" 调用这个函数来判断上一个命令是否执行成功,没有成功则退出。

检查是否有 sshpass 命令工具

sshpass 是需要单独安装的命令行工具,所以为了照顾到没有安装或者不想安装的同事,我们可以判断当前环境是否安装了 sshpass, 如果没有安装,或者安装了,在执行时没有传入密码,我们将通过交互式命令行进行上传和执行脚本。

shell 复制代码
USE_SSHPASS=false  
if command -v sshpass > /dev/null 2>&1; then  
  if [ -z "$REMOTE_PASSWORD" ]; then  
    echo "警告: 检测到 sshpass,但未提供密码。将使用常规方式登录。"  
  else  
    USE_SSHPASS=true  
  fi  
else  
  echo "未检测到 sshpass,使用常规的密码提示方式。"  
fi  

完整脚本

下面是完整的自动化部署脚本,包含打包、上传和部署的所有步骤:

bash 复制代码
#!/bin/bash  
###  
 # @Author: 子洋  
 # @Date: 2024-09-30 12:11:05
 # @LastEditors: 子洋  
 # @LastEditTime: 2024-09-30 12:39:33  
 # @Description: 测试环境自动发布脚本  
 # @FilePath: /web/publish/publish-beta.sh  
###  
  
# 获取脚本所在目录  
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"  
  
# 获取脚本所在目录的上一级目录  
PARENT_DIR="$(dirname "$SCRIPT_DIR")"  
  
# 本地 tar 文件名称  
LOCAL_TAR_FILE="dist.tar"  
  
# 远程服务器信息  
REMOTE_USER="root"                  # 远程服务器用户  
REMOTE_HOST=""                      # 远程服务器 IP
REMOTE_PORT="22"                    # 远程服务器 ssh 端口  
REMOTE_PASSWORD="$1"                # 远程服务器密码  
REMOTE_DIR="/usr/frontend/"         # 远程服务器文件传输目录  
  
# 检查打包命令是否成功的函数  
check_success() {  
  if [ $? -ne 0 ]; then  
    echo "错误: $1"  
    exit 1  
  fi  
}  
  
# 检查 sshpass 是否存在  
USE_SSHPASS=false  
if command -v sshpass > /dev/null 2>&1; then  
  if [ -z "$REMOTE_PASSWORD" ]; then  
    echo "警告: 检测到 sshpass,但未提供密码。将使用常规方式登录。"  
  else  
    USE_SSHPASS=true  
  fi  
else  
  echo "未检测到 sshpass,使用常规的密码提示方式。"  
fi  
  
# 开始打包  
echo "开始打包..."  
npm run build > /dev/null 2>&1  
check_success "前端打包失败"
  
# 删除旧的 tar 文件  
rm -f $LOCAL_TAR_FILE > /dev/null 2>&1  
  
# 生成新的 tar 文件  
tar -cvf $LOCAL_TAR_FILE dist > /dev/null 2>&1  
check_success "打包 dist 目录失败"  
  
# 传输文件到服务器  
echo "正在将文件传输到服务器..."  
if [ "$USE_SSHPASS" = true ]; then  
  sshpass -p "$REMOTE_PASSWORD" scp -P $REMOTE_PORT $LOCAL_TAR_FILE $REMOTE_USER@$REMOTE_HOST:$REMOTE_DIR  
else  
  scp -P $REMOTE_PORT $LOCAL_TAR_FILE $REMOTE_USER@$REMOTE_HOST:$REMOTE_DIR  
fi  
check_success "SCP 文件传输失败"  
  
# 定义在远程服务器上执行的脚本内容  
REMOTE_SCRIPT=$(cat << EOF  
#!/bin/bash  
cd $REMOTE_DIR  
  
if [ ! -e "$LOCAL_TAR_FILE" ]; then  
  echo "$LOCAL_TAR_FILE 不存在"  
  exit 1  
fi  
  
tar -xvf $LOCAL_TAR_FILE > /dev/null 2>&1  
if [ $? -ne 0 ]; then  
  echo "错误: $LOCAL_TAR_FILE 解压失败"  
  exit 1  
fi  
  
rm -rf html  
mv dist html  
docker restart frontend_web  
EOF  
)  
  
# 登录服务器并执行脚本  
echo "文件传输完成,正在登录服务器并执行脚本..."  
if [ "$USE_SSHPASS" = true ]; then  
  sshpass -p "$REMOTE_PASSWORD" ssh -p "$REMOTE_PORT" "$REMOTE_USER@$REMOTE_HOST" "bash -s" <<EOF  
$REMOTE_SCRIPT  
EOF  
else  
  ssh -p "$REMOTE_PORT" "$REMOTE_USER@$REMOTE_HOST" "bash -s" <<EOF  
$REMOTE_SCRIPT  
EOF  
fi  
check_success "远程脚本执行失败"  
  
cd - > /dev/null 2>&1 || exit  
  
echo "脚本执行完毕!"

命令行使用方式:

shell 复制代码
sh publish-beta.sh your-password

结语

通过简单的 Shell 脚本,我们能够自动化地执行前端项目的打包、上传和部署操作,从而节省时间,减少人为错误。虽然这个脚本已经可以很好地工作,但在实际项目中,我们还可以进一步优化,比如添加错误处理、备份旧版本项目等功能。如果需要在生产环境中使用,建议加入更为完善的日志和异常处理机制。

相关推荐
paopaokaka_luck2 小时前
【360】基于springboot的志愿服务管理系统
java·spring boot·后端·spring·毕业设计
逐·風3 小时前
unity关于自定义渲染、内存管理、性能调优、复杂物理模拟、并行计算以及插件开发
前端·unity·c#
Devil枫3 小时前
Vue 3 单元测试与E2E测试
前端·vue.js·单元测试
码农小旋风3 小时前
详解K8S--声明式API
后端
Peter_chq3 小时前
【操作系统】基于环形队列的生产消费模型
linux·c语言·开发语言·c++·后端
Yaml44 小时前
Spring Boot 与 Vue 共筑二手书籍交易卓越平台
java·spring boot·后端·mysql·spring·vue·二手书籍
小小小妮子~4 小时前
Spring Boot详解:从入门到精通
java·spring boot·后端
hong1616884 小时前
Spring Boot中实现多数据源连接和切换的方案
java·spring boot·后端
尚梦4 小时前
uni-app 封装刘海状态栏(适用小程序, h5, 头条小程序)
前端·小程序·uni-app
GIS程序媛—椰子4 小时前
【Vue 全家桶】6、vue-router 路由(更新中)
前端·vue.js