🌈 一条命令部署前端代码
👋 开场白
要将前端工程部署到服务器有很多途径, 最次的是手动打包, 传包部署到NGINX;其次用jekins, jekins部署前端工程确实是挺强的;对于github开源项目,用action流程,写个yaml文件; 最好用最近在捣鼓docker,用dockerfile,也可以做到CI/CD;看了那么多的脚本一样的代码,但是我突发奇想, 能不能就写个shell脚本, 能让我就在vscode里面就一条命令就实现了部署?我咨询了Kimi,它告诉我是可以的,下面我就详细介绍我咋做的。
✌环境要求
本地开发环境windows, 部署环境Linux, Linux登陆的用户名和密码,不属于这种环境的可以划走了
🌟 环境准备
下载安装Msys2
-
下载Msys2 : 首先要安装这个环境,因为我本地开发是windows, 不支持Linux里面的命令,先到镜像站,找到'msys2-x86_64-20240727.exe'把插件下载下来Index of /msys2/distrib/x86_64/ | 清华大学开源软件镜像站,点击安装,可以装到D盘,不然后面装插件会越来越大。
-
更新 MSYS2:
-
打开 MSYS2 终端并运行以下命令来更新系统:
bashpacman -Syu
-
可能需要多次运行
pacman -Syu
并关闭终端重新打开,直到所有更新完成。
-
-
安装
sshpass
:-
在 MSYS2 终端中运行以下命令来安装
sshpass
(这个插件用于通过用户名+密码登陆Linux的)bashpacman -S sshpass
-
-
验证安装:
-
运行以下命令来验证
sshpass
是否安装成功:bashsshpass -V
-
-
环境配置:
- 由于MSYS2的环境独立于windows,你在里面输入npm -v或者node -v,会发现都用不了,这时需要共享一下环境,在系统变量里面添加:
MSYS2_PATH_TYPE=inherit
,共享主机的
- 由于MSYS2的环境独立于windows,你在里面输入npm -v或者node -v,会发现都用不了,这时需要共享一下环境,在系统变量里面添加:
vscode添加终端
为了方便在vscode中打开目录下的终端,在setting.json中添加如下代码,path填自己安装时的位置,然后就会发现终端有了个bash-MSYS2
,这个名字可以自己随便定义。
json
"terminal.integrated.profiles.windows": {
"bash-MSYS2": {
"path": "d:\\msys64\\usr\\bin\\bash.exe",
"args": ["--login", "-i"],
"env": { "CHERE_INVOKING": "1" }
}
},
🔑 脚本准备
-
先来个简单的 :
- 先测试能不能通到服务器,好排查是不是账号密码等因素影响了, 这里先打个下面命令,把ip先添加到knownhost,不然后面会拒绝连接
bashssh root@192.168.0.250 -p 22
- 小小测一把,下面文件能查看服务器/root下面的文件列表
bashsshpass -p "远程服务器密码" ssh -o StrictHostKeyChecking=no 用户名@远程服务器IP "ls"
- 传个文件试试,**替换成自己的密码,在执行目录下,自己建个example.txt,执行完毕后,到服务器、tmp下查看是不是已经有了文件
bashsshpass -p "****" scp example.txt root@192.168.0.254:/tmp
-
开整 :
- 如果上面都没有问题,那么我们已经实现了大部分功能了,剩下的就是编排流程,下面是豆包根据代码生成的流程图,代码说明下,我npm run build 里面是下面这样子也就是打包出来就是tar包,解压出来的就是文件夹名和REMOTE_DISTNAME里面定义的一样,不然后面还要重命名麻烦,然后把最后的脚步命名为deploy.sh,用前面装的msys2终端,运行命令
npm run deploy
, 最后就会看到我们的代码已经部署到位置上了, 原来的文件加上了时间戳进行备份。
json"scripts": { "build": "vue-cli-service build --dest mobilevue && npm run tar", "tar": "tar -czf mobilevue.tar.gz mobilevue", "deploy": "sh deploy.sh" }
- 如果上面都没有问题,那么我们已经实现了大部分功能了,剩下的就是编排流程,下面是豆包根据代码生成的流程图,代码说明下,我npm run build 里面是下面这样子也就是打包出来就是tar包,解压出来的就是文件夹名和REMOTE_DISTNAME里面定义的一样,不然后面还要重命名麻烦,然后把最后的脚步命名为deploy.sh,用前面装的msys2终端,运行命令
-
脚本全部代码 :
bash#!/bin/bash # 测试环境自动发布脚本 # 本地 tar 文件名称 LOCAL_TAR_FILE="mobilevue.tar.gz" # 远程服务器信息 REMOTE_USER="root" # 远程服务器用户 REMOTE_HOST="192.168.0.250" # 远程服务器 IP REMOTE_PORT="22" # 远程服务器 ssh 端口 REMOTE_PASSWORD="xxxxxx" # 远程服务器密码 REMOTE_DIR="/usr/local/nginx/html/" # 远程服务器文件传输目录 REMOTE_DISTNAME="mobilevue" # 打包前端项目 echo "开始打包前端项目..." npm run build echo "打包完成!" # 检查打包命令是否成功的函数 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 "正在将文件传输到服务器..." 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 文件传输失败" # 获取当前时间戳 CURRENT_TIMESTAMP=$(date +%Y%m%d%H%M%S) echo "当前时间戳: $CURRENT_TIMESTAMP" # 定义在远程服务器上执行的脚本内容 REMOTE_SCRIPT=$(cat << EOF #!/bin/bash set -x # 开启调试模式,输出所有命令 cd $REMOTE_DIR || { echo "目录 $REMOTE_DIR 不存在"; exit 1; } # 检查文件是否存在 if [ ! -e "$LOCAL_TAR_FILE" ]; then echo "错误: $LOCAL_TAR_FILE 不存在" exit 1 fi # 重命名旧目录 if [ -e "$REMOTE_DISTNAME" ]; then mv "$REMOTE_DISTNAME" "${REMOTE_DISTNAME}_${CURRENT_TIMESTAMP}" || { echo "重命名失败"; exit 1; } echo "旧目录已重命名为 ${REMOTE_DISTNAME}_${CURRENT_TIMESTAMP}" fi # 解压新文件 tar -xvf "$LOCAL_TAR_FILE" || { echo "解压失败"; exit 1; } echo "解压成功" 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 "远程脚本执行失败" echo "脚本执行完毕!"
最后的话
感觉shell脚本是真的很强大,如果可以还可以写爬虫,也可以调用服务器里面的sh,执行更加复杂的操作!如果有什么疑问和更好的建议,欢迎留言讨论,大家共同进度!