• 作者:老汪软件技巧
  • 发表时间:2024-10-02 07:01
  • 浏览量:

前言

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

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

思路与流程

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

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

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

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

脚本实现

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

1. 打包前端项目

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

npm run build
tar -cvf dist.tar dist

2. 上传前端项目

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

scp dist.tar root@服务器IP:/usr/frontend

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

3. 远程执行换包操作

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

ssh "root@服务器IP" "bash -s" <<EOF
$REMOTE_SCRIPT
EOF

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

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. 传递密码

前端打包后怎么部署_前端打包上线流程_

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

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

brew install sshpass   # Mac 安装
apt-get install sshpass   # Ubuntu/Debian 安装

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

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. 代码优化

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

提取常量

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

# 获取脚本所在目录  
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 命令不在控制台展示日志输出,同时封装一个检查命令报错的函数。

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

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

检查是否有 sshpass 命令工具

sshpass 是需要单独安装的命令行工具,所以为了照顾到没有安装或者不想安装的同事,我们可以判断当前环境是否安装了 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  

完整脚本

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

#!/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 "脚本执行完毕!"

命令行使用方式:

sh publish-beta.sh your-password

结语

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