基于bat腳本的前端發(fā)布流程設(shè)計(jì)與實(shí)現(xiàn)
寫(xiě)在前面
本文大致向讀者介紹了樓下幾點(diǎn)知識(shí),希望在編寫(xiě)bat腳本時(shí)候能夠幫到讀者,如果能夠有所啟迪,那就更好了。
bat腳本的相關(guān)知識(shí)和案例編寫(xiě) 用windows自帶的命令壓縮文件 windows和linux文件傳輸 如何免密碼登錄Linux 前端發(fā)布流程的優(yōu)化
背景介紹
筆者目前所在的開(kāi)發(fā)團(tuán)隊(duì),由于一些限制,沒(méi)有相關(guān)的devOps實(shí)踐,所以也就沒(méi)持續(xù)集成、自動(dòng)部署什么事了。很多時(shí)候,還是依靠人力手動(dòng)擋操控,先運(yùn)行諸如yarn build或者npm run build之類(lèi)的npm script去構(gòu)建相關(guān)的前端項(xiàng)目,然后選中dist文件夾,進(jìn)行相關(guān)的壓縮,差一點(diǎn)的就直接命名dist.zip好一點(diǎn)的就帶上個(gè)時(shí)間方便回溯,比如app-202206012002.zip這種,然后打開(kāi)相關(guān)的ftp工具,把壓縮好的包傳到遠(yuǎn)程服務(wù)器上,最后在服務(wù)器上解壓,放到nginx指定的html目錄下,這一趟發(fā)版就算是齊活了。
這種模式比如就一個(gè)項(xiàng)目,那你要是能夠接受,時(shí)間也夠充裕那就這么搞吧,也無(wú)可厚非的。但是要是有好多個(gè)這種項(xiàng)目這么搞,真讓人嘔吐??啊,好tm惡心啊,程序員本身在做的一件事情,應(yīng)該是把一件繁瑣的或者說(shuō)是復(fù)雜的事情簡(jiǎn)單化,而不是隨波逐流,任由事情變得越來(lái)越復(fù)雜、以致到了最后不可控,那就太雞肋了。
Larry Wall(拉里 · 沃爾)曾經(jīng)說(shuō)過(guò)程序員的三大美德:懶惰,急切,傲慢(laziness, impatience, hubris)。樓上的做法顯然不是很尊重(懶惰)美德啊,于是我開(kāi)始蠢蠢欲動(dòng)地構(gòu)思顛覆樓上的發(fā)布模式。
我物色到了好幾位選手,一位是bat選手,一位是cmd選手,還有js選手,py選手等等,經(jīng)過(guò)相關(guān)的權(quán)衡,我最終選擇編寫(xiě)bat(批處理)來(lái)解決樓上的問(wèn)題。
我為什么相中bat選手來(lái)解決樓上的問(wèn)題?
第一個(gè)就是,我們?cè)诮鉀Q當(dāng)前問(wèn)題的時(shí)候,盡量不要引入一些新事物去增加問(wèn)題本身的復(fù)雜度,基于樓上這件事本身就是敲敲命令行(包括你說(shuō)壓縮、上傳,本質(zhì)上不就是一條命令嘛),所以js選手、py選手pass。第二個(gè)就是,我們盡量要做的兼容性足夠好,bat和cmd用起來(lái)其實(shí)都差不多的,但你一定要深究它們,我理了下它們的區(qū)別大致是這樣子的
bat(ms dos批處理腳本)基于dos設(shè)計(jì),更通用一點(diǎn) cmd(windows nt命令腳本)只能在windows2000以上系統(tǒng)運(yùn)行,但是命令豐富
所以綜上所述,我最后選擇編寫(xiě)一個(gè)dos批處理腳本來(lái)解決樓上的問(wèn)題。
有哪些人機(jī)交互的方案可以實(shí)現(xiàn)?
方案一:當(dāng)用戶(hù)運(yùn)行相關(guān)bat腳本的時(shí)候,可以讓用戶(hù)輸入對(duì)應(yīng)的項(xiàng)目名稱(chēng),然后去匹配對(duì)應(yīng)的項(xiàng)目,再執(zhí)行構(gòu)建命令,然后執(zhí)行壓縮命令,再上傳到linux服務(wù)器 方案二:考慮到項(xiàng)目有可能很長(zhǎng),為了優(yōu)化用戶(hù)體驗(yàn),現(xiàn)在統(tǒng)一讓用戶(hù)輸入數(shù)字,執(zhí)行相關(guān)的邏輯,比如1、執(zhí)行app項(xiàng)目構(gòu)建,2、執(zhí)行biz項(xiàng)目構(gòu)建,3、執(zhí)行app和biz項(xiàng)目構(gòu)建,然后在進(jìn)行相關(guān)的壓縮上傳操作。 把項(xiàng)目的粒度放到子項(xiàng)目中去,比如NoteWeb下面有app,biz,fin三個(gè)子項(xiàng)目,每個(gè)子項(xiàng)目寫(xiě)一個(gè)構(gòu)建腳本,在父項(xiàng)目中,寫(xiě)的著急一點(diǎn)就無(wú)腦構(gòu)建,每個(gè)項(xiàng)目都run一把,當(dāng)然你也可以參考樓上的方案一、二做相應(yīng)的優(yōu)化
bat腳本知識(shí)科普
@echo off關(guān)閉回顯setlocal enabledelayedexpansion設(shè)置延遲變量@REM 用來(lái)寫(xiě)注釋的chcp 65001使用utf-8編碼,這樣中文就不會(huì)亂碼了,cls清屏cd /D %~dp0進(jìn)入當(dāng)前目錄echo 這個(gè)是用來(lái)輸出的color 0A設(shè)置文字顯示的顏色是 一抹“原諒色”set /p input_source=?講輸入的值賦值給變量input_source
以上列舉的是常用的bat腳本知識(shí),具體的建議讀者閱讀幫助文檔來(lái)進(jìn)行了解相關(guān)的命令,這里就不再贅述。
deploy.bat腳本的編寫(xiě)
如何實(shí)現(xiàn)數(shù)字菜單?
這里的思路是讓用戶(hù)輸入對(duì)應(yīng)的數(shù)字,然后講參數(shù)傳給execBuild方法執(zhí)行相關(guān)的邏輯(構(gòu)建打包,壓縮,上傳)
@echo?off
setlocal?enabledelayedexpansion?
color?0A
@REM?中電匯融項(xiàng)目構(gòu)建腳本,Zheng?JiangTao([email protected])
chcp?65001
cls
cd?/D?%~dp0
echo?==========(∩??ω??)?-*?中電匯融項(xiàng)目構(gòu)建腳本?*-?(??ω??∩)==========
:start
echo?中電匯融項(xiàng)目數(shù)字菜單:
echo?【1】app,?【2】biz,?【3】fin
echo.
echo?【4】app、biz,?【5】app、fin
echo.
echo?【6】biz、fin,【7】app、biz、fin,
echo.
echo?【0】退出
echo.
echo?請(qǐng)按提示輸入相應(yīng)的數(shù)字進(jìn)行相關(guān)的項(xiàng)目構(gòu)建操作:
set?/p?input_source=
if?!input_source!==?0?(?echo?退出成功?)
if?!input_source!==?1?(?call?:execBuild?app?)
if?!input_source!==?2?(?call?:execBuild?biz?)
if?!input_source!==?3?(?call?:execBuild?fin?)
if?!input_source!==?4?(?call?:execBuild?app,biz?)
if?!input_source!==?5?(?call?:execBuild?app,fin?)
if?!input_source!==?6?(?call?:execBuild?biz,fin?)
if?!input_source!==?7?(?call?:execBuild?app,biz,fin?)
echo?========*:??(?′?`)??:*中電匯融項(xiàng)目構(gòu)建腳本*:??(?′?`)??:*========
:finish
exit?/b
如何實(shí)現(xiàn)打包文件壓縮?
市面上常見(jiàn)的壓縮軟件有winRar、7-Zip等等,一個(gè)思路是設(shè)置對(duì)應(yīng)安裝的軟件的bin目錄到環(huán)境變量,然后去查閱對(duì)應(yīng)的API,執(zhí)行相關(guān)的打包壓縮命令,但是問(wèn)題就來(lái)了,你哪能知道用戶(hù)裝的是winRar還是7-Zip,還是360壓縮呢,所以你就需要寫(xiě)一個(gè)兼容的方法來(lái)抹平這個(gè)問(wèn)題,先去查找有沒(méi)有對(duì)應(yīng)的文件目錄,有的話(huà)添加到環(huán)境變量,然后執(zhí)行對(duì)應(yīng)的壓縮命令,這樣子很繁瑣,萬(wàn)一它一個(gè)也沒(méi)有裝呢?而且也違背了上面說(shuō)的(懶惰)美德。
所以在這里,我們?cè)噲D通過(guò)windows自身的一些方法去壓縮文件,皇天不負(fù)趕路人,我在csdn上看到一篇帖子https://blog.csdn.net/d_r_l_t/article/details/100584748,于是我摸著這位大哥的文件壓縮過(guò)河,具體的讀者可以點(diǎn)開(kāi)閱讀下,我這里就不再贅述了。
創(chuàng)建一個(gè)zip.vbs腳本
Set?objArgs?=?WScript.Arguments
ZipFile?=?objArgs(0)
?
'?Create?empty?ZIP?file?and?open?for?adding
CreateObject("Scripting.FileSystemObject").CreateTextFile(ZipFile,?True).Write?"PK"?&?Chr(5)?&?Chr(6)?&?String(18,?vbNullChar)
Set?zip?=?CreateObject("Shell.Application").NameSpace(ZipFile)
?
'?Add?all?files/directories?to?the?.zip?file
For?i?=?1?To?objArgs.count-1
??zip.CopyHere(objArgs(i))
??WScript.Sleep?10000?'REQUIRED!!?(Depending?on?file/dir?size)
Next
那么壓縮就簡(jiǎn)單到執(zhí)行一條命令就好了,例如:cscript ../zip.vbs dest.zip src
如何上傳到linux服務(wù)器?
scp命令可以進(jìn)行計(jì)算機(jī)間的文件傳輸,具體的例如 scp app-202206012112.zip [root@1](mailto:[email protected])22.51.52.169:/root/nginx/html-auxre/zdhr/app就是把a(bǔ)pp-202206012112.zip傳到服務(wù)器122.51.52.169的/root/nginx/html-auxre/zdhr/app目錄下,當(dāng)然這里會(huì)讓你輸入密碼。
如何解決每次執(zhí)行scp命令都要輸入密碼(解決免密登錄)?
其實(shí)這里寫(xiě)一個(gè)auth.bat腳本就好了,代碼如下:
@echo?off
ssh-keygen?-t?rsa
cd?C:\Users\%USERNAME%\.ssh
type?id_rsa.pub?>>?authorized_keys
xcopy?/Q/Y/F/S?"C:\Users\%USERNAME%\.ssh\id_rsa.pub"?".\authorized_keys"
xcopy?/Q/Y/F/S?"C:\Users\%USERNAME%\.ssh\id_rsa.pub"?".\id_rsa.pub"
scp?id_rsa.pub?authorized_keys?root@122.51.52.169:/root/.ssh
最后完整的代碼是這樣子的,圖中ip為了保密已經(jīng)做了瞎寫(xiě)處理,讀者可以拿去參考應(yīng)用到自己或者公司的項(xiàng)目中(這里,如果是在一些國(guó)企、銀行單位,那批處理就很有用了,畢竟沒(méi)網(wǎng).jpg)
@echo?off
setlocal?enabledelayedexpansion?
color?0A
@REM?中電匯融項(xiàng)目構(gòu)建腳本,Zheng?JiangTao([email protected])
chcp?65001
cls
cd?/D?%~dp0
echo?==========(∩??ω??)?-*?中電匯融項(xiàng)目構(gòu)建腳本?*-?(??ω??∩)==========
:start
echo?中電匯融項(xiàng)目數(shù)字菜單:
echo?【1】app,?【2】biz,?【3】fin
echo.
echo?【4】app、biz,?【5】app、fin
echo.
echo?【6】biz、fin,【7】app、biz、fin,
echo.
echo?【0】退出
echo.
echo?請(qǐng)按提示輸入相應(yīng)的數(shù)字進(jìn)行相關(guān)的項(xiàng)目構(gòu)建操作:
set?/p?input_source=
if?!input_source!==?0?(?echo?退出成功?)
if?!input_source!==?1?(?call?:execBuild?app?)
if?!input_source!==?2?(?call?:execBuild?biz?)
if?!input_source!==?3?(?call?:execBuild?fin?)
if?!input_source!==?4?(?call?:execBuild?app,biz?)
if?!input_source!==?5?(?call?:execBuild?app,fin?)
if?!input_source!==?6?(?call?:execBuild?biz,fin?)
if?!input_source!==?7?(?call?:execBuild?app,biz,fin?)
echo?========*:??(?′?`)??:*中電匯融項(xiàng)目構(gòu)建腳本*:??(?′?`)??:*========
:finish
exit?/b?
:execBuild
setlocal
set?exec_a=%~1
set?exec_b=%~2
set?exec_c=%~3
set?prefix=NotePBL
set?exec_a_src="%~dp0%prefix%-%exec_a%\dist"
set?exec_b_src="%~dp0%prefix%-%exec_b%\dist"
set?exec_c_src="%~dp0%prefix%-%exec_c%\dist"
set?cur_date=%date:~3,4%%date:~8,2%%date:~11,2%%time:~0,2%%time:~3,2%%time:~6,2%
set?exec_a_dist="%~dp0%prefix%-%exec_a%\%exec_a%-%cur_date%.zip"
set?exec_b_dist="%~dp0%prefix%-%exec_b%\%exec_b%-%cur_date%.zip"
set?exec_c_dist="%~dp0%prefix%-%exec_c%\%exec_a%-%cur_date%.zip"
if?"%exec_a%"?==?""?(
??@REM?Do?Nothing
)?else?(?
??echo?"*:??(?′?`)??:*構(gòu)建%prefix%-%exec_a%開(kāi)始*:??(?′?`)??:*"
??cd?/D?%~dp0\%prefix%-%exec_a%
??call?npm?run?build
??echo?"*:??(?′?`)??:*構(gòu)建%prefix%-%exec_a%結(jié)束*:??(?′?`)??:*"
??echo?"*:??(?′?`)??:*%exec_a%-%cur_date%.zip開(kāi)始打包*:??(?′?`)??:*"
??call?cscript?../zip.vbs?%exec_a_dist%?%exec_a_src%
??echo?"*:??(?′?`)??:*%exec_a%-%cur_date%.zip打包完成*:??(?′?`)??:*"
??echo?"*:??(?′?`)??:*上傳%prefix%-%exec_a%開(kāi)始*:??(?′?`)??:*"
??scp?%exec_a%-%cur_date%[email protected]:/root/nginx/html-auxre/zdhr/%exec_a%
??echo?"*:??(?′?`)??:*上傳%prefix%-%exec_a%結(jié)束*:??(?′?`)??:*"
)
if?"%exec_b%"?==?""?(?
??@REM?Do?Nothing
)?else?(?
??echo?"*:??(?′?`)??:*構(gòu)建%prefix%-%exec_b%開(kāi)始*:??(?′?`)??:*"
??cd?/D?%~dp0\%prefix%-%exec_b%
??call?npm?run?build
??echo?"*:??(?′?`)??:*構(gòu)建%prefix%-%exec_b%結(jié)束*:??(?′?`)??:*"
??echo?"*:??(?′?`)??:*%exec_b%-%cur_date%.zip開(kāi)始打包*:??(?′?`)??:*"
??call?cscript?../zip.vbs?%exec_b_dist%?%exec_b_src%
??echo?"*:??(?′?`)??:*%exec_b%-%cur_date%.zip打包完成*:??(?′?`)??:*"
??echo?"*:??(?′?`)??:*上傳%prefix%-%exec_b%開(kāi)始*:??(?′?`)??:*"
??scp?%exec_b%-%cur_date%[email protected]:/root/nginx/html-auxre/zdhr/%exec_b%
??echo?"*:??(?′?`)??:*上傳%prefix%-%exec_b%結(jié)束*:??(?′?`)??:*"
)
if?"%exec_c%"?==?""?(?
??@REM?Do?Nothing
)?else?(?
??echo?"*:??(?′?`)??:*構(gòu)建%prefix%-%exec_c%開(kāi)始*:??(?′?`)??:*"
??cd?/D?%~dp0\%prefix%-%exec_c%
??call?npm?run?build
??echo?"*:??(?′?`)??:*構(gòu)建%prefix%-%exec_c%結(jié)束*:??(?′?`)??:*"
??echo?"*:??(?′?`)??:*%exec_c%-%cur_date%.zip開(kāi)始打包*:??(?′?`)??:*"
??call?cscript?../zip.vbs?%exec_c_dist%?%exec_c_src%
??echo?"*:??(?′?`)??:*%exec_c%-%cur_date%.zip打包完成*:??(?′?`)??:*"
??echo?"*:??(?′?`)??:*上傳%prefix%-%exec_c%開(kāi)始*:??(?′?`)??:*"
??scp?%exec_c%-%cur_date%[email protected]:/root/nginx/html-auxre/zdhr/%exec_c%
??echo?"*:??(?′?`)??:*上傳%prefix%-%exec_c%結(jié)束*:??(?′?`)??:*"
)
goto:eof
實(shí)現(xiàn)效果
可能細(xì)心的讀者會(huì)發(fā)現(xiàn),怎么沒(méi)有構(gòu)建這一步啊,這里為了更直觀的讓大家看到效果,我在運(yùn)行的時(shí)候把npm run build 注釋掉了因?yàn)樗虺鰜?lái)的日志太多了,刷屏了,就把它去掉,展示下整體的效果,圖中應(yīng)該是壓縮到上傳到Linux服務(wù)器的效果

最后
樓上的腳本就作為拋磚引玉,希望能夠在前端發(fā)包方面幫助到讀者,解放勞動(dòng)力。其實(shí)我們還是可以繼續(xù)優(yōu)化的,比如說(shuō),在CPU和內(nèi)存理想的狀態(tài)下,我能不能開(kāi)三個(gè)小窗口去分別并行執(zhí)行三個(gè)項(xiàng)目的構(gòu)建,然后把項(xiàng)目的構(gòu)建和上傳解耦,這樣子設(shè)計(jì)會(huì)更符合軟件設(shè)計(jì)的思想,更加魯棒。
