背景 之前为了学习windows的bat脚本,我在AI的帮助下写了一个将前端包上传到服务器的部署脚本,使用起来还算方便,相比于 GitHub Actions 在代码推送时强制触发的自动化流程,我这套“半自动”方案可以自由控制什么时候发新版本,具有更高的灵活性。
由于最近在脚本中集成了刷新cdn的js脚本,考虑到前端开发者的技术栈偏好与代码的可维护性,于是想着把整套部署流程全部用nodejs脚本实现,毕竟作为一个前端开发者,js是我更熟悉的语言,具有更好的可读性。本文的目的只是在这里将现有的bat脚本存个档,或许它在未来的某一天会发挥它的价值也说不定。
代码 deploy.bat 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 @echo off setlocal enabledelayedexpansion:: ========================================== :: 前端部署脚本 (交互模式版) :: ========================================== cd /d "%~dp0"echo ==========================================echo 开始执行前端部署...echo ==========================================echo [提示] 如果出现 "Store key in cache?" 询问,请输 y 并回车。echo ==========================================:: --- 1 . 环境检查 --- where tar >nul 2 >nul if %errorlevel% neq 0 ( echo [错误] 未找到 tar 命令。 pause exit /b 1 ) :: --- 2 . 读取配置 --- set "configFile=config.ini"if not exist "%configFile% " ( echo [错误] 找不到配置文件: %configFile% pause exit /b 1 ) :: 初始化变量 set "server_ip="set "username="set "local_dir="set "remote_dir="set "private_key=":: 解析 INI 文件 for /f "usebackq tokens=1 ,* delims==" %%a in ("%configFile% ") do ( set "key=%%a " set "val=%%b " for /f "tokens=* delims= " %%k in ("!key! ") do set "key=%%k " if /i "!key! "=="server_ip" set "server_ip=!val! " if /i "!key! "=="username" set "username=!val! " if /i "!key! "=="local_dir" set "local_dir=!val! " if /i "!key! "=="remote_dir" set "remote_dir=!val! " if /i "!key! "=="private_key" set "private_key=!val! " if /i "!key! "=="cdn_secret_id" set "cdn_secret_id=!val! " if /i "!key! "=="cdn_secret_key" set "cdn_secret_key=!val! " ) :: 清洗变量 (去引号、去斜杠) call :CleanVar server_ipcall :CleanVar usernamecall :CleanVar local_dircall :CleanVar remote_dircall :CleanVar private_key:: --- 3 . 验证配置 --- if "%server_ip% "=="" goto ConfigErrorif "%username% "=="" goto ConfigErrorif "%local_dir% "=="" goto ConfigErrorif "%remote_dir% "=="" goto ConfigErrorif "%private_key% "=="" goto ConfigErrorecho ------------------------------------------echo 服务器IP : %server_ip% echo 本地源码 : %local_dir% echo 远程路径 : %remote_dir% echo ------------------------------------------echo 按下 Enter 键开始部署...pause >nul :: --- 4 . 打包 --- echo .echo [1 /4 ] 正在压缩文件...if not exist "%local_dir% " ( echo [错误] 本地目录不存在: %local_dir% pause exit /b 1 ) set "distFile=%~dp0dist.tar.gz"if exist "%distFile% " del "%distFile% "tar -czf "%distFile% " -C "%local_dir% " . if %errorlevel% neq 0 ( echo [错误] 压缩失败! pause exit /b 1 ) echo OK.:: --- 5 . 清理远程目录 (交互式) --- echo .echo [2 /4 ] 清理远程目录...if "%remote_dir% "=="/" ( echo [错误] 禁止删除根目录 pause exit /b 1 ) plink -i "%private_key% " %username% @%server_ip% "mkdir -p %remote_dir% && rm -rf %remote_dir% /*" if %errorlevel% neq 0 ( echo [错误] 清理失败! pause exit /b 1 ) echo OK.:: --- 6 . 上传 (交互式) --- echo .echo [3 /4 ] 上传文件...pscp -i "%private_key% " "%distFile% " %username% @%server_ip% :%remote_dir% /dist.tar.gz if %errorlevel% neq 0 ( echo [错误] 上传失败! pause exit /b 1 ) echo OK.:: --- 7 . 解压 (交互式) --- echo .echo [4 /4 ] 远程解压...plink -i "%private_key% " %username% @%server_ip% "cd %remote_dir% && tar -xzf dist.tar.gz && rm -f dist.tar.gz" if %errorlevel% neq 0 ( echo [错误] 解压失败! pause exit /b 1 ) echo OK.:: 完成 :: --- 8 . 刷新CDN缓存 --- echo .echo [5 /5 ] 刷新CDN缓存...:: 检查密钥是否存在 if "%cdn_secret_id% "=="" ( echo [警告] 未配置 secret_id,跳过 CDN 刷新。 goto :SkipCDN ) if "%cdn_secret_key% "=="" ( echo [警告] 未配置 secret_key,跳过 CDN 刷新。 goto :SkipCDN ) :: 设置临时环境变量 (仅对当前 session 有效,不会污染系统变量) :: 注意:变量名必须与 refreshCDN.js 中 process.env.后使用的名称一致 set "TENCENTCLOUD_SECRET_ID=%cdn_secret_id% "set "TENCENTCLOUD_SECRET_KEY=%cdn_secret_key% "call node "%~dp0refreshCDN.js"if %errorlevel% neq 0 ( echo [错误] CDN刷新失败! pause exit /b 1 ) echo OK.:: 完成 if exist "%distFile% " del "%distFile% "echo .echo ==========================================echo 部署成功!echo ==========================================pause exit /b 0 :: --- 子程序 --- :CleanVar set "tmpVal=!%1! "if "!tmpVal! "=="" goto :eofset "tmpVal=!tmpVal:"=! "if "!tmpVal:~-1! "=="\" set "tmpVal=!tmpVal:~0,-1! "if "!tmpVal:~-1! "=="/" set "tmpVal=!tmpVal:~0,-1! "set "tmpVal=!tmpVal: =!"set "%1 =!tmpVal! "goto :eof:ConfigError echo [错误] 配置文件变量缺失。pause exit /b 1
refreshCDN.js 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 const tencentcloud = require ("tencentcloud-sdk-nodejs-cdn" )const CdnClient = tencentcloud.cdn .v20180606 .Client const clientConfig = { credential : { secretId : process.env .TENCENTCLOUD_SECRET_ID , secretKey : process.env .TENCENTCLOUD_SECRET_KEY , }, region : "ap-chengdu" , profile : { httpProfile : { endpoint : "cdn.tencentcloudapi.com" , }, }, } const client = new CdnClient (clientConfig)const params = { Paths : ["https://cyanfish.site/" ], FlushType : "flush" , } client.PurgePathCache (params).then ( (data ) => { console .log (data) }, (err ) => { console .error ("error" , err) } )
js代码来自腾讯云sdk官方文档: https://console.cloud.tencent.com/api/explorer?Product=cdn&Version=2018-06-06&Action=PurgePathCache