1 前言
在前端开发工作流中,文件打包后上传服务器往往是一个繁琐且容易出错的环节。传统前端部署流程涉及 npm run build 构建、手动压缩文件、FTP 工具上传、服务器解压替换等重复性操作,这些操作不仅容易出错,还十分耗时耗力,完整流程平均耗时 5 - 10 分钟。这归根结底还是因为我嫌麻烦,所以为了实现解放双手(简化步骤),在网上查阅相关方案后,比较适合中小项目的主要有以下几种:
- 使用 scp 命令将本地文件夹上传到服务器指定目录,配合 package.json 配置脚本,操作简单,但功能较为单一。
- 服务器配置 Git 和 Webhook,本地将文件夹提交到 Git 仓库,服务器初始化仓库自动拉取,版本回溯方便,但前期配置较复杂易出错,不推荐。
- 利用三方部署命令行工具,如 deploy-cli-service,利用 npm 命令安装,再进行简单配置后就可使用,功能强大全面,自动化程度高,比较推荐。
- 基于 scp 命令自己编写 shell 或 bat 脚本,根据需要自定义增减功能,兼容性足够好,重要的是特别适合部分网络受限的单位。
以上方法各有优缺,任选其一都可以简化部署流程,而我选择的则是最后一种,即使用以 scp 为核心的一系列命令来编写一个 BAT 脚本,每次仅需要双击执行这个脚本就可以快速完成部署。
2 知识科普
在开始之前,有必要先来了解一下最基本的知识。
2.1 SCP 命令
SCP(Secure Copy Protocol)是基于SSH协议的安全文件传输命令,本质上是 rcp 命令的安全升级版,主要用于在本地主机与远程主机之间加密传输文件和目录。
cp 命令在传输上大多是 本地 → 本地 的方向,而 scp 命令则可以做到 本地 → 远程、远程 → 本地 或 远程 → 远程 三种传输方向。
# 本地 → 远程
scp /path/to/local/file user@remote_ip:/remote/path
# 远程 → 本地
scp user@remote_ip:/remote/path/file /local/path
# 远程 → 远程(借助本地中转)
scp user1@host1:/path/file user2@host2:/path/常用参数
-r:递归复制整个目录。-P:指定远程主机的 SSH 端口号(默认是 22)。-p:保留文件的修改时间、访问时间和权限。-v:显示详细的调试信息,有助于排查问题。-C:启用压缩,可以加快传输速度。
2.2 BAT 脚本
批处理脚本(BAT)是一系列你给计算机的指令,文件通常以 .bat 或 .cmd 作为后缀拓展名,可以在 Windows 系统上运行。
基本命令
@echo off
关闭命令提示符窗口中命令的回显,使脚本执行时只显示命令执行结果,而不显示具体命令内容,增强脚本执行的简洁性。
@echo off
echo 这行内容会显示,但此 echo 命令本身不会显示- 注释
注释可以帮助理解脚本功能、逻辑和用途等,在执行时会被忽略。:: 的效率高于 rem,但不能在括号内使用。
rem 这是注释
:: 这也是注释(更推荐)变量操作
- 定义变量
set name=张三- 使用变量
echo %name%- 输入变量
set /p input=请输入内容:流程控制
- 条件判断
if "%input%"=="y" (
echo 你选择了是
) else (
echo 你选择了否
)- 检查文件存在
if exist "test.txt" echo 文件存在- 简单循环
:loop
echo 循环中...
timeout /t 1 >nul
goto loop文件操作
- 创建目录
mkdir new_folder- 删除文件
del old.txt- 切换目录
cd ./folder
cd ..实用技巧
- 暂停脚本
pause- 显示当前路径
echo 当前目录:%cd%常用符号
>输出到文件(覆盖)
echo 内容 > log.txt>>追加到文件
echo 新内容 >> log.txt|管道符
dir | find "txt" :: 查找包含"txt"的目录项3 脚本编写
脚本编写过程中我会按照功能需求优先级来分布实现。
3.1 核心功能实现
首先创建一个脚本文件 upload.bat,然后使用任意文本编辑工具去打开它。
先来编写整个脚本最核心也是最基本的内容,打开一个命令行然后将你指定的文件夹上传到服务器指定目录。
@echo off
set REMOTE_USER=your_username(远程服务器用户名)
set REMOTE_HOST=your_server_ip(远程服务器IP)
set REMOTE_DIR=/path/to/remote/directory(要上传到的远程服务器目录)
set LOCAL_DIR=.\dist(本地要上传的文件夹)
scp -r "%LOCAL_DIR%" %REMOTE_USER%@%REMOTE_HOST%:%REMOTE_DIR%
endlocal@echo off:关闭命令行的回显功能,避免在执行过程中显示每条命令。- 设置远程服务器信息,需按照提示分别修改
REMOTE_USER、REMOTE_HOST、REMOTE_DIR和LOCAL_DIR的值。 scp -r:scp是用于安全复制文件和文件夹的命令,-r选项表示递归复制,即复制整个文件夹及其子文件夹。endlocal:结束本地环境变量的设置。

3.2 优化逻辑判断
使用两个 if 判断分别检查本地目录存在性和 SCP 执行结果,能够避免尝试上传不存在的目录和明确反馈操作结果,两次使用 pause 命令可以更有效地查看错误信息。
@echo off
set REMOTE_USER=your_username(远程服务器用户名)
set REMOTE_HOST=your_server_ip(远程服务器IP)
set REMOTE_DIR=/path/to/remote/directory(要上传到的远程服务器目录)
set LOCAL_DIR=.\dist(本地要上传的文件夹)
:: 检查本地目录是否存在
if not exist "%LOCAL_DIR%" (
echo 错误:本地目录 "%LOCAL_DIR%" 不存在
pause
exit /b 1
)
scp -r "%LOCAL_DIR%" %REMOTE_USER%@%REMOTE_HOST%:%REMOTE_DIR%
:: 检查上传结果
if %ERRORLEVEL% equ 0 (
echo 文件上传成功
) else (
echo 文件上传失败
)
pause
endlocal
3.3 实现多项目功能
假设我们有多个项目需要上传文件夹部署,可以通过预设和手动输入来实现。预设用来配置经常需要上传的项目,而手动输入可以上传临时项目或文件夹。
echo 请选择要执行的操作:
echo 1. 上传项目 1
echo 2. 上传项目 2
echo 3. 手动输入配置
:CHOICE
set /p CHOICE=请输入数字 (1, 2, 3):
if "%CHOICE%"=="1" (
set REMOTE_USER=your_username1
set REMOTE_HOST=your_server_ip1
set REMOTE_DIR=/path/to/remote/directory1
set LOCAL_DIR=.\dist1
) else if "%CHOICE%"=="2" (
set REMOTE_USER=your_username2
set REMOTE_HOST=your_server_ip2
set REMOTE_DIR=/path/to/remote/directory2
set LOCAL_DIR=.\dist2
) else if "%CHOICE%"=="3" (
set /p REMOTE_USER=请输入远程服务器用户名:
set /p REMOTE_HOST=请输入远程服务器 IP:
set /p REMOTE_DIR=请输入要上传到的远程服务器目录:
set /p LOCAL_DIR=请输入本地要上传的文件夹:
) else (
echo 无效的选择,请重新输入。
goto CHOICE
)输入数字 1 或 2 时,分别上传项目 1 或项目 2 的预设配置,输入数字 3 手动输入配置,需要输入服务器用户名、IP、目录以及本地文件夹等信息,若选择非 1-3 则需要重新输入。

3.4 改进交互体验
使用视觉分隔区分不同信息类型,优化错误处理,结合提示语增强交互。
@echo off
title 前端项目自动化上传工具
echo.
echo ╔══════════════════════════════════════════════╗
echo ║ 前端项目自动化上传工具 v1.0 ║
echo ╚══════════════════════════════════════════════╝
echo.
echo 请选择要执行的操作:
echo 1. 上传项目 1
echo 2. 上传项目 2
echo 3. 手动输入配置
:CHOICE
set /p CHOICE=请输入数字 (1, 2, 3):
if "%CHOICE%"=="1" (
set REMOTE_USER=your_username1
set REMOTE_HOST=your_server_ip1
set REMOTE_DIR=/path/to/remote/directory1
set LOCAL_DIR=.\dist1
) else if "%CHOICE%"=="2" (
set REMOTE_USER=your_username2
set REMOTE_HOST=your_server_ip2
set REMOTE_DIR=/path/to/remote/directory2
set LOCAL_DIR=.\dist2
) else if "%CHOICE%"=="3" (
set /p REMOTE_USER=请输入远程服务器用户名:
set /p REMOTE_HOST=请输入远程服务器 IP:
set /p REMOTE_DIR=请输入要上传到的远程服务器目录:
set /p LOCAL_DIR=请输入本地要上传的文件夹:
) else (
echo 无效的选择,请重新输入。
goto CHOICE
)
if not exist "%LOCAL_DIR%" (
echo ████████████████████████████████████████████
echo 错误:本地目录 "%LOCAL_DIR%" 不存在
echo 请检查以下可能原因:
echo 1. 项目未正确构建
echo 2. 目录路径配置错误
echo 3. 脚本运行位置不正确
echo.
echo 当前工作目录:%cd%
echo ████████████████████████████████████████████
pause
exit /b 1
)
for /f "delims=" %%a in ('wmic os get localdatetime ^| find "."') do set start=%%a
echo ■ 准备上传目录: %LOCAL_DIR%
echo ■ 目标服务器: %REMOTE_USER%@%REMOTE_HOST%
echo ■ 远程路径: %REMOTE_DIR%
echo.
echo ※ 正在上传文件,请稍候...(首次连接需要确认指纹)
scp -r "%LOCAL_DIR%" %REMOTE_USER%@%REMOTE_HOST%:%REMOTE_DIR%
for /f "delims=" %%a in ('wmic os get localdatetime ^| find "."') do set end=%%a
set /a "duration=(1%end:~8,2%-100)*3600 + (1%end:~10,2%-100)*60 + (1%end:~12,2%-100)"
set /a "duration=duration - ((1%start:~8,2%-100)*3600 + (1%start:~10,2%-100)*60 + (1%start:~12,2%-100))"
if %duration% lss 0 set /a duration+=86400
echo.
if %ERRORLEVEL% equ 0 (
echo ████████████████████████████████████████████
echo ■ 上传成功!耗时 %duration% 秒
echo ■ 传输完成时间: %date% %time%
echo ████████████████████████████████████████████
) else (
echo ████████████████████████████████████████████
echo ■ 上传失败!错误代码: %ERRORLEVEL%
echo.
echo 可能原因:
echo 1. 服务器连接失败
echo 2. 认证失败(检查用户名/密码/密钥)
echo 3. 远程目录不可写
echo 4. 磁盘空间不足
echo.
echo 建议操作:
echo 1. 检查网络连接
echo 2. 验证服务器配置参数
echo 3. 手动尝试SCP命令排错
echo ████████████████████████████████████████████
)
echo.
echo 操作已完成,按任意键退出...
pause >nul
endlocal
3.5 额外功能:解压缩
为减少数据传输量、提高传输稳定性,建议增加解压缩功能,还便于版本管理。
:: 生成时间戳和压缩包名称
for /f "tokens=2 delims==" %%a in ('wmic os get localdatetime /value') do set datetime=%%a
set TIMESTAMP=%datetime:~0,4%-%datetime:~4,2%-%datetime:~6,2%_%datetime:~8,2%-%datetime:~10,2%-%datetime:~12,2%
set ZIP_NAME=deploy_%TIMESTAMP%.zip
set TEMP_ZIP=.\temp\%ZIP_NAME%
:: 第一步:本地压缩
echo ※ 正在压缩本地文件...
powershell -command "Add-Type -Assembly 'System.IO.Compression.FileSystem'; [System.IO.Compression.ZipFile]::CreateFromDirectory('%LOCAL_DIR%', '%TEMP_ZIP%')"
if not exist "%TEMP_ZIP%" (
pause
exit /b 1
)
echo √ 压缩完成,压缩包大小:
for %%F in ("%TEMP_ZIP%") do echo %%~zF 字节
echo.
:: 第二步:上传压缩包
echo ※ 正在上传压缩包,请稍候...(首次连接需要确认指纹)
scp "%TEMP_ZIP%" %REMOTE_USER%@%REMOTE_HOST%:%REMOTE_DIR%/
if not %ERRORLEVEL% equ 0 (
del "%TEMP_ZIP%" >nul 2>&1
pause
exit /b 1
)
:: 第三步:服务器端解压
echo ※ 正在远程解压文件...
ssh %REMOTE_USER%@%REMOTE_HOST% "cd %REMOTE_DIR% && unzip -oq %ZIP_NAME%"
if not %ERRORLEVEL% equ 0 (
del "%TEMP_ZIP%" >nul 2>&1
pause
exit /b 1
)
:: 清理临时文件
del "%TEMP_ZIP%" >nul 2>&13.6 进一步功能增强
接下来,我们可以结合 npm 构建命令,增强脚本自动化,从构建到部署一次性完成,还可以新增退出选项和循环执行,让脚本使用体验更流畅易用。
当然,可以整合的功能远不止此,但做到目前实现的功能对于个人来说完全够用,下面就展示一下完整的文件。
4 完整文件
:: upload.bat
@echo off
title 前端项目自动化上传工具
:MAIN_LOOP
cls
echo.
echo ╔══════════════════════════════════════════════╗
echo ║ 前端项目自动化上传工具 v1.0 ║
echo ╚══════════════════════════════════════════════╝
echo.
echo 请选择要执行的操作:
echo 1. 上传项目 1
echo 2. 上传项目 2
echo 3. 手动输入配置
echo 4. 退出程序
echo.
:CHOICE
set /p CHOICE=请输入数字 (1, 2, 3, 4):
if "%CHOICE%"=="1" (
set REMOTE_USER=your_username1(远程服务器用户名)
set REMOTE_HOST=your_server_ip1(远程服务器IP)
set REMOTE_DIR=/path/to/remote/directory1(要上传到的远程服务器目录)
set PROJECT_DIR=.\project1(本地项目地址,该处执行npm构建命令)
set NPM_COMMAND=npm run build(本地要执行的npm构建命令)
set LOCAL_DIR=.\dist(本地要上传的文件夹,注意为项目地址的相对路径)
) else if "%CHOICE%"=="2" (
set REMOTE_USER=your_username2
set REMOTE_HOST=your_server_ip2
set REMOTE_DIR=/path/to/remote/directory2
set PROJECT_DIR=.\project1
set NPM_COMMAND=npm run build
set LOCAL_DIR=.\dist2
) else if "%CHOICE%"=="3" (
set /p REMOTE_USER=请输入远程服务器用户名:
set /p REMOTE_HOST=请输入远程服务器 IP:
set /p REMOTE_DIR=请输入要上传到的远程服务器目录:
set /p PROJECT_DIR=请输入项目所在目录:
set /p NPM_COMMAND=请输入 npm 构建命令:
set /p LOCAL_DIR=请输入本地要上传的文件夹:
) else if "%CHOICE%"=="4" (
echo 正在退出程序...
timeout /t 1 >nul
exit /b 0
) else (
echo 无效的选择,请重新输入。
goto CHOICE
)
for /f "delims=" %%a in ('wmic os get localdatetime ^| find "."') do set start=%%a
if not exist "%PROJECT_DIR%" (
echo ████████████████████████████████████████████
echo 错误:本地目录 "%PROJECT_DIR%" 不存在
echo 请检查以下可能原因:
echo 1. 项目未正确构建
echo 2. 目录路径配置错误
echo 3. 脚本运行位置不正确
echo.
echo 当前工作目录:%cd%
echo ████████████████████████████████████████████
echo 按任意键返回主菜单...
pause >nul
cd /d %~dp0
goto MAIN_LOOP
)
echo ■ 正在执行 npm 构建命令: %NPM_COMMAND%
echo ■ 请耐心等待
cd /d %PROJECT_DIR%
call %NPM_COMMAND% >nul 2>&1
if %ERRORLEVEL% neq 0 (
echo ████████████████████████████████████████████
echo ■ npm 构建失败!错误代码: %ERRORLEVEL%
echo.
echo 请检查以下可能原因:
echo 1. 项目依赖未正确安装
echo 2. 构建脚本配置错误
echo.
echo 建议操作:
echo 1. 执行 npm install 安装依赖
echo 2. 检查项目的 package.json 文件中的脚本配置
echo ████████████████████████████████████████████
echo 按任意键返回主菜单...
pause >nul
cd /d %~dp0
goto MAIN_LOOP
)
for /f "tokens=2 delims==" %%a in ('wmic os get localdatetime /value') do set datetime=%%a
set TIMESTAMP=%datetime:~0,4%-%datetime:~4,2%-%datetime:~6,2%_%datetime:~8,2%-%datetime:~10,2%-%datetime:~12,2%
set ZIP_NAME=deploy_%TIMESTAMP%.zip
set TEMP_ZIP=.\temp\%ZIP_NAME%
if not exist ".\temp" (
mkdir ".\temp"
if %ERRORLEVEL% neq 0 (
echo ████████████████████████████████████████████
echo 错误:无法创建临时目录 ".\temp"
echo 可能原因:
echo 1. 磁盘空间不足
echo 2. 文件权限问题
echo ████████████████████████████████████████████
echo 按任意键返回主菜单...
pause >nul
cd /d %~dp0
goto MAIN_LOOP
)
)
echo ■ 准备压缩: %LOCAL_DIR%
echo.
echo ※ 正在压缩本地文件...
powershell -command "Add-Type -Assembly 'System.IO.Compression.FileSystem'; [System.IO.Compression.ZipFile]::CreateFromDirectory('%LOCAL_DIR%', '%TEMP_ZIP%')"
if not exist "%TEMP_ZIP%" (
echo ████████████████████████████████████████████
echo 错误:压缩文件创建失败
echo 可能原因:
echo 1. 磁盘空间不足
echo 2. 文件权限问题
echo 3. PowerShell 执行失败
echo ████████████████████████████████████████████
echo 按任意键返回主菜单...
pause >nul
cd /d %~dp0
goto MAIN_LOOP
)
echo √ 压缩完成,压缩包大小:
for %%F in ("%TEMP_ZIP%") do echo %%~zF 字节
echo.
echo ※ 正在上传压缩包,请稍候...(首次连接需要确认指纹)
echo ■ 准备上传压缩包: %TEMP_ZIP%
echo ■ 目标服务器: %REMOTE_USER%@%REMOTE_HOST%
echo ■ 远程路径: %REMOTE_DIR%
scp "%TEMP_ZIP%" %REMOTE_USER%@%REMOTE_HOST%:%REMOTE_DIR%/
if not %ERRORLEVEL% equ 0 (
echo ████████████████████████████████████████████
echo ■ 上传失败!错误代码: %ERRORLEVEL%
echo.
echo 可能原因:
echo 1. 服务器连接失败
echo 2. 认证失败(检查用户名/密码/密钥)
echo 3. 远程目录不可写
echo 4. 磁盘空间不足
echo.
echo 建议操作:
echo 1. 检查网络连接
echo 2. 验证服务器配置参数
echo 3. 手动尝试SCP命令排错
echo ████████████████████████████████████████████
del "%TEMP_ZIP%" >nul 2>&1
echo 按任意键返回主菜单...
pause >nul
cd /d %~dp0
goto MAIN_LOOP
)
echo ※ 正在远程解压文件...
ssh %REMOTE_USER%@%REMOTE_HOST% "cd %REMOTE_DIR% && unzip -oq %ZIP_NAME%"
for /f "delims=" %%a in ('wmic os get localdatetime ^| find "."') do set end=%%a
set /a "duration=(1%end:~8,2%-100)*3600 + (1%end:~10,2%-100)*60 + (1%end:~12,2%-100)"
set /a "duration=duration - ((1%start:~8,2%-100)*3600 + (1%start:~10,2%-100)*60 + (1%start:~12,2%-100))"
if %duration% lss 0 set /a duration+=86400
del "%TEMP_ZIP%" >nul 2>&1
echo.
echo ████████████████████████████████████████████
echo √ 操作成功完成!耗时 %duration% 秒
echo ■ 传输完成时间: %date% %time%
echo ■ 已执行步骤:
echo 1. 本地执行 %NPM_COMMAND% 命令
echo 2. 本地压缩: %LOCAL_DIR% → %ZIP_NAME%
echo 3. 上传压缩包到: %REMOTE_DIR%/
echo 4. 服务器解压
echo ████████████████████████████████████████████
echo.
echo 按任意键返回主菜单...
pause >nul
cd /d %~dp0
goto MAIN_LOOP5 解决免密登录
想要解决每次执行 scp 命令都要输入密码很简单,只需要设置 SSH 公钥认证,就可以使后续连接无需密码登录。它的实现方法流程为:本地生成 SSH 密钥对 > 将公钥上传到服务器 /root/.ssh/ 下 > 重命名为 authorized_keys。
为了简化这一流程,我们也可以用一个 bat 文件来实现:
@echo off
setlocal enabledelayedexpansion
:: 1. 生成 SSH 密钥对(如果不存在)
if not exist "%USERPROFILE%\.ssh\id_rsa" (
echo 正在生成 SSH RSA 密钥对...
ssh-keygen -t rsa -f "%USERPROFILE%\.ssh\id_rsa" -q -N ""
) else (
echo 检测到已存在的 SSH 密钥,跳过生成步骤...
)
:: 2. 获取服务器信息
set /p server_ip=请输入服务器IP地址:
set /p server_username=请输入服务器用户名(默认为root):
if "!server_username!"=="" set server_username=root
:: 3. 创建远程.ssh目录(如果不存在)并上传公钥
echo 正在上传公钥到服务器...
type "%USERPROFILE%\.ssh\id_rsa.pub" | ssh !server_username!@!server_ip! "mkdir -p ~/.ssh && chmod 700 ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys"
echo 公钥上传完成
pause
6 写在最后
通过以上步骤,我们成功打造了一个功能强大且实用的前端项目自动化上传工具。这个工具不仅能显著提升前端部署的效率,还极大地减少了人为操作可能带来的错误。无论是中小项目,还是在网络受限的环境中,它都能发挥出出色的作用。在实际使用过程中,你可以根据自身的需求对脚本进行进一步的定制和扩展。
在最后的完整文件展示中,主要以功能实现为主,很多细节并未处理或者处理的并不妥善,比如依赖环境说明、安全性提示和代码复用性等等,所以在细节方面还有不少的提升空间,但只是个人使用的话基本没什么问题。
如果你对这个工具感兴趣,可以在 talen8/automation-deploy: 前端自动化部署 关注更新,后续我会不断去完善这个脚本功能。
评论
暂无评论,快来发表第一条评论吧!