小Hub領(lǐng)讀:腳本代碼這么多,,不是運(yùn)維可能會(huì)真不會(huì)寫哈哈。普通人用jenkins全量挺好的,,但是代碼過(guò)多時(shí)候就比較麻煩,,而且jenkins一般也要配合腳本使用更加符合業(yè)務(wù)。
作者:CatalpaFlat https:///post/5cf0ed996fb9a07eab68674f
應(yīng)用部署是開(kāi)發(fā),、測(cè)試,、上線必須面對(duì)的一個(gè)過(guò)程,尤其是微服務(wù)架構(gòu)的出現(xiàn),,運(yùn)維部署從單體的部署逐漸脫離出,,并且越顯復(fù)雜。 然而,,拋開(kāi)多語(yǔ)言,,多環(huán)境,集群,分布式的部署之外,。就單單討論增量部署和全量部署 1.增量和全量部署部署,,除卻項(xiàng)目初始化部署,最理想的情況即為:新版本更改哪些內(nèi)容則更新哪些內(nèi)容 1.1 增量部署1.1.1 增量部署簡(jiǎn)介增量部署一般指在每次部署過(guò)程中首先提取當(dāng)前版本和即將部署版本之間的增量(包括代碼,、可執(zhí)行文件或者配置等),,并在部署過(guò)程中僅更新增量部分。 1.1.2 常見(jiàn)部署流程利用代碼管理工具(SVN,、GIT 等)提取兩個(gè)版本之間的增量,,并結(jié)合其他方面的增量變化。 按照增量部分制定具體的部署方式,,編寫部署腳本,,并準(zhǔn)備增量部署包(包括混淆代碼等)。 分發(fā)和部署增量部署包到已經(jīng)運(yùn)行上一版本的目標(biāo)環(huán)境,,完成系統(tǒng)的版本升級(jí),。
1.1.3 增量部署優(yōu)點(diǎn)部署速度快。每次只對(duì)增量部分進(jìn)行更新,,縮短部署時(shí)間 減少變化量,。減少對(duì)整個(gè)系統(tǒng)的變化幅度,有些配置內(nèi)容是不需要每次都更新迭代的 提高安全性,。由于每次支隊(duì)增量進(jìn)行更新,,避免全部代碼的泄露
1.1.4 增量部署缺點(diǎn)增量部署 若存在其他外在部署環(huán)境依賴,則降低部署效率 增量部署不像 部署環(huán)境多的情況下,,對(duì)可重復(fù)性要求高 增量部署對(duì)回滾操作變得不友好
1.2 如何選擇增量還是全量現(xiàn)有的自動(dòng)化部署,,大多數(shù)都 全量部署,但全量部署也有一些弊端,。但可以通過(guò)一些策略進(jìn)行篩選:搜索公眾號(hào):MarkerHub,,關(guān)注回復(fù)[vue]獲取前后端入門教程! 提前準(zhǔn)全量部署的所有配置和材料(部署包,,外在配置文件等)在進(jìn)行部署,,可以提高效率和速度 使用灰度發(fā)布或負(fù)載均衡等方法降低全量部署對(duì)應(yīng)用可用性的影響
對(duì)于現(xiàn)代系統(tǒng)中絕大部分狀態(tài)無(wú)關(guān)的部署單元(應(yīng)用、模塊,,微服務(wù)等),全量部署一般應(yīng)是最優(yōu)的選擇,。而狀態(tài)相關(guān)的部署單元(數(shù)據(jù)庫(kù)等)則依然適合增量部署邏輯,。 2.進(jìn)入主題前面講述了一些關(guān)于增量和全量部署的情況。接下來(lái)講述如何通過(guò) shell 腳本結(jié)合 Git Log 進(jìn)行增量部署 2.1 前提環(huán)境Java 項(xiàng)目 Maven 進(jìn)行管理 Git 作為代碼倉(cāng)庫(kù)
2.2 shell 腳本shell 新手,,寫得不夠完美,,輕噴。 2.2.1 整個(gè) shell 腳本的模塊2.2.2 Git 環(huán)境準(zhǔn)備# git環(huán)境
if [[ ! -d ".git" ]]; then ECHO error: please init Git Repository exit 1; fi
if [[ ! -z ${branch} ]]; then git checkout ${branch} fi
# 獲取默認(rèn)commit-hash if [[ -z "$begin_hash" ]] && [[ -z "$end_hash" ]] ; then for p in $(git log --pretty=oneline -2) ; do if [[ ${#p} -eq 40 ]]; then if [[ -z ${begin_hash} ]]; then begin_hash=${p} else end_hash=${p} break fi fi done fi
is_begin_has=false
# 是否當(dāng)前最新commit if [[ $(git log --pretty=oneline -1) == *${begin_hash}* ]]; then is_begin_has=true fi
# 非當(dāng)前最新分支commit,,回滾到原始版本,,可能當(dāng)時(shí)maven原始配置不支持compile或會(huì)出現(xiàn)構(gòu)建失敗(如:使用本地倉(cāng)/私有倉(cāng)庫(kù)等) if [[ ${is_begin_has} = false ]]; then project_path=$(pwd) project_name=${project_path##*/} cd .. build_project_name=${project_name}_build_temp_project if [[ ! -d ${build_project_name} ]]; then mkdir ${build_project_name} fi \cp -rf ${project_name}/. ${build_project_name} cd ${build_project_name} git reset --hard ${begin_hash} fi
2.2.2.1 校驗(yàn)是否 git 倉(cāng)庫(kù)代碼if [[ ! -d ".git" ]]; then ECHO error: please init Git Repository exit 1; fi
2.2.2.2 檢查是否需要切換分支if [[ ! -z ${branch} ]]; then git checkout ${branch} fi
2.2.2.3 是否需要設(shè)置默認(rèn)構(gòu)建的 commit 值若執(zhí)行構(gòu)建時(shí),,沒(méi)給添加 --begin_hash= 和 --end_hash= 進(jìn)行賦值,,則默認(rèn)使用最新的兩次 commit 來(lái)進(jìn)行增量部署。 通過(guò) git log --pretty=oneline -2 獲取最近兩次 commit 的 hash # 獲取默認(rèn)commit-hash if [[ -z "$begin_hash" ]] && [[ -z "$end_hash" ]] ; then for p in $(git log --pretty=oneline -2) ; do if [[ ${#p} -eq 40 ]]; then if [[ -z ${begin_hash} ]]; then begin_hash=${p} else end_hash=${p} break fi fi done fi 復(fù)制代碼
2.2.2.4 校驗(yàn)傳參的 begin_hash 值是否為當(dāng)前分支最新 commit hash若非當(dāng)前分支最新 commit hash,,則需要回滾到對(duì)應(yīng) commit,,進(jìn)行項(xiàng)目構(gòu)建編譯 if [[ $(git log --pretty=oneline -1) == *${begin_hash}* ]]; then is_begin_has=true fi 復(fù)制代碼
2.2.2.5 若 begin_hash 非當(dāng)前最新 commit hash若傳參 begin_hash 的值非當(dāng)前最新 commit hash。則需要回滾到對(duì)應(yīng) commit 進(jìn)行構(gòu)建編譯,。搜索公眾號(hào):MarkerHub,,關(guān)注回復(fù)[vue]獲取前后端入門教程! 將現(xiàn)有項(xiàng)目進(jìn)行拷貝到新的目錄環(huán)境 到新目錄環(huán)境對(duì)項(xiàng)目進(jìn)行 reset,,用于構(gòu)建項(xiàng)目
if [[ ${is_begin_has} = false ]]; then project_path=$(pwd) project_name=${project_path##*/} cd .. build_project_name=${project_name}_build_temp_project if [[ ! -d ${build_project_name} ]]; then mkdir ${build_project_name} fi \cp -rf ${project_name}/. ${build_project_name} cd ${build_project_name} git reset --hard ${begin_hash} fi 復(fù)制代碼
2.2.3 Maven 對(duì)欲構(gòu)建項(xiàng)目進(jìn)行編譯對(duì)項(xiàng)目進(jìn)行編譯,,生成對(duì)應(yīng) class 文件以及相關(guān)配置文件 mvn clean compile -q -DskipTest 復(fù)制代碼
若歷史版本中存在使用本地倉(cāng)庫(kù),而 maven 中沒(méi)有配置好的情況可以重新配置, 通過(guò) scope 以及 systemPath 進(jìn)行引入,,如: <dependency> <groupId>cn.catalpaflat</groupId> <artifactId>core</artifactId> <version>1.0.0</version> <scope>system</scope> <systemPath>${project.basedir}/lib/core-1.0.jar</systemPath> </dependency> 復(fù)制代碼
2.2.4 創(chuàng)建增量部署文件夾為了防止增量文件夾被刪除或者被 commit 到 git 倉(cāng)庫(kù),,可以統(tǒng)一化到一個(gè)目錄中,并通過(guò) .gitignore 對(duì)其進(jìn)行忽略,??梢员葘?duì)每次增量部署的差異 build_path=build-path/ current_date=`date +%Y%m%d%H%m%s`
if [[ ! -d "$build_path$current_date" ]]; then mkdir -p ${build_path}${current_date} else rm -rf ${build_path}${current_date} mkdir -p ${build_path}${current_date} fi 復(fù)制代碼
2.2.5 檢索項(xiàng)目 target 目錄若項(xiàng)目為 Maven 項(xiàng)目,并且是 Java 項(xiàng)目,,由于存在 Maven 多模塊情況,,需要檢索每個(gè)模塊下的編譯后的代碼路徑,用于后續(xù)進(jìn)行 class 等文件的拷貝,。 default_target_paths=() default_java_file=java
module_index=0 # 檢索當(dāng)前項(xiàng)目是否maven多模塊開(kāi)發(fā),,遞歸檢索,并設(shè)置其編譯后的代碼位置(暫只提供了java類型) obtain_module(){ for module in ` cat ./pom.xml | grep '<module>' | awk -F '>' '{print $2}' | awk -F '<' '{print $1}' ` do cd ${module}
if [[ ! -d "/pom.xml" ]]; then module_exist=`cat ./pom.xml | grep '<module>' | awk -F '>' '{print $2}' | awk -F '<' '{print $1}'` if [[ -z ${module_exist} ]]; then if [[ ! -d "/target" ]]; then if [[ -z $1 ]]; then default_target_paths[module_index]=${module}/target/classes else default_target_paths[module_index]=$1/${module}/target/classes fi ((module_index++)) fi else if [[ -z $1 ]]; then obtain_module ${module} else obtain_module $1/${module} fi fi fi cd .. done }
obtain_module 復(fù)制代碼
2.2.6 檢索并拷貝變更文件到增量文件夾git diff --name-only 排查兩次 commit 之間文件差異 并將 begin_hash 的 commit 編譯后的代碼拷貝到增量文件夾中,,以備后續(xù)打包進(jìn)行部署
# 通過(guò)git diff --name-only實(shí)現(xiàn)兩次commit之間文件差異,,并且將begin_hash的代碼進(jìn)行編譯后,將差異的文件拷貝到“增量文件夾”中,,以備后續(xù)進(jìn)行增量部署
for file_path in $(git diff --name-only ${begin_hash} ${end_hash}) ; do package_path=${file_path%/*} file_name=${file_path##*/} file_type=${file_name##*.} # 文件所在校驗(yàn)文件夾是否創(chuàng)建 if [[ ${package_path} != *.* ]]; then if [[ ! -d "./${build_path}${current_date}/$package_path" ]] ; then mkdir -p ./${build_path}${current_date}/${package_path} fi fi # 是否java if [[ ${file_type} = ${default_java_file} ]]; then module_path=${package_path##*java} file_class_name=${file_name%.*} module_type=${package_path%%/*} # 排查在哪個(gè)maven模塊路徑下 for default_target_path in ${default_target_paths[@]}; do target_module_path=$(echo ${default_target_path} | awk -F '/target/' '{print $1}') file_target_module_path=$(echo ${package_path} | awk -F '/src/' '{print $1}') file_target_package_path=$(echo ${package_path} | awk -F '/src/main/java/' '{print $2}') default_module_type=${default_target_path%%/*} if [[ ${target_module_path} = ${file_target_module_path} ]]; then # 排查到對(duì)應(yīng)maven模塊的target目錄,,進(jìn)行cp操作 cp -afx ${default_target_path}/${file_target_package_path}/${file_class_name}* ./${build_path}${current_date}/${package_path} fi done
else # 非java文件,直接拷貝文件到對(duì)應(yīng)目錄下 if [[ ${package_path} != *.* ]]; then if [[ ! -d "./${build_path}${current_date}/$package_path" ]] ; then mkdir -p ./${build_path}${current_date}/${package_path} fi else package_path=${package_path%/*} fi
cp -afx ${file_path} ./${build_path}${current_date}/${package_path}
fi done
源碼直通車?。,。?https://github.com/CatalpaFlat/build-maven-project-shell 到此為止,,1.0 版本的簡(jiǎn)陋版本初步完成,,目測(cè)可以使用,,哈哈哈哈
(完) MarkerHub文章索引:(點(diǎn)擊閱讀原文直達(dá)) https://github.com/MarkerHub/JavaIndex
|