小Hub领读:

脚本代码这么多,不是运维可能会真不会写哈哈。普通人用jenkins全量挺好的,但是代码过多时候就比较麻烦,而且jenkins一般也要配合脚本使用更加符合业务。

应用部署是开发、测试、上线必须面对的一个过程,尤其是微服务架构的出现,运维部署从单体的部署逐渐脱离出,并且越显复杂。

然而,抛开多语言,多环境,集群,分布式的部署之外。就单单讨论增量部署和全量部署

1.增量和全量部署

部署,除却项目初始化部署,最理想的情况即为:新版本更改哪些内容则更新哪些内容

1.1 增量部署

1.1.1 增量部署简介

增量部署一般指在每次部署过程中首先提取当前版本和即将部署版本之间的增量(包括代码、可执行文件或者配置等),并在部署过程中仅更新增量部分。

1.1.2 常见部署流程

利用代码管理工具(SVN、GIT 等)提取两个版本之间的增量,并结合其他方面的增量变化。

按照增量部分制定具体的部署方式,编写部署脚本,并准备增量部署包(包括混淆代码等)。

分发和部署增量部署包到已经运行上一版本的目标环境,完成系统的版本升级。

1.1.3 增量部署优点

部署速度快。每次只对增量部分进行更新,缩短部署时间

减少变化量。减少对整个系统的变化幅度,有些配置内容是不需要每次都更新迭代的

提高安全性。由于每次支队增量进行更新,避免全部代码的泄露

1.1.4 增量部署缺点

增量部署 若存在其他外在部署环境依赖,则降低部署效率

增量部署不像

部署环境多的情况下,对可重复性要求高

增量部署对回滚操作变得不友好

1.2 如何选择增量还是全量

现有的自动化部署,大多数都 全量部署,但全量部署也有一些弊端。但可以通过一些策略进行筛选:

提前准全量部署的所有配置和材料(部署包,外在配置文件等)在进行部署,可以提高效率和速度

使用灰度发布或负载均衡等方法降低全量部署对应用可用性的影响

对于现代系统中绝大部分状态无关的部署单元(应用、模块,微服务等),全量部署一般应是最优的选择。而状态相关的部署单元(数据库等)则依然适合增量部署逻辑。

2.进入主题

前面讲述了一些关于增量和全量部署的情况。接下来讲述如何通过 shell 脚本结合 Git Log 进行增量部署

2.1 前提环境

Java 项目

Maven 进行管理

Git 作为代码仓库

2.2 shell 脚本

shell 新手,写得不够完美,轻喷。

2.2.1 整个 shell 脚本的模块

Git 环境准备

Maven 对欲构建项目进行编译

创建增量部署文件夹

检索项目 target 目录

通过 git diff 检索两次 commit 之间的差异,再通过检索将对应文件拷贝到 “增量文件夹” 中

2.2.2 Git 环境准备

# git环境

if [[ ! -d ".git" ]]; then

ECHO error: please init Git Repository

exit 1;

fi

if [[ ! -z ${branch} ]]; then

git checkout ${branch}

fi

# 获取默认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

# 是否当前最新commit

if [[ $(git log --pretty=oneline -1) == *${begin_hash}* ]]; then

is_begin_has=true

fi

# 非当前最新分支commit,回滚到原始版本,可能当时maven原始配置不支持compile或会出现构建失败(如:使用本地仓/私有仓库等)

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 校验是否 git 仓库代码

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 是否需要设置默认构建的 commit 值

若执行构建时,没给添加 --begin_hash= 和 --end_hash= 进行赋值,则默认使用最新的两次 commit 来进行增量部署。

通过 git log --pretty=oneline -2 获取最近两次 commit 的 hash

# 获取默认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

复制代码

2.2.2.4 校验传参的 begin_hash 值是否为当前分支最新 commit hash

若非当前分支最新 commit hash,则需要回滚到对应 commit,进行项目构建编译

if [[ $(git log --pretty=oneline -1) == *${begin_hash}* ]]; then

is_begin_has=true

fi

复制代码

2.2.2.5 若 begin_hash 非当前最新 commit hash

若传参 begin_hash 的值非当前最新 commit hash。则需要回滚到对应 commit 进行构建编译。

将现有项目进行拷贝到新的目录环境

到新目录环境对项目进行 reset,用于构建项目

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.3 Maven 对欲构建项目进行编译

对项目进行编译,生成对应 class 文件以及相关配置文件

mvn clean compile -q -DskipTest

复制代码

若历史版本中存在使用本地仓库,而 maven 中没有配置好的情况可以重新配置, 通过 scope 以及 systemPath 进行引入,如:

cn.catalpaflat

core

1.0.0

system

${project.basedir}/lib/core-1.0.jar

复制代码

2.2.4 创建增量部署文件夹

为了防止增量文件夹被删除或者被 commit 到 git 仓库,可以统一化到一个目录中,并通过 .gitignore 对其进行忽略。可以比对每次增量部署的差异

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

复制代码

2.2.5 检索项目 target 目录

若项目为 Maven 项目,并且是 Java 项目,由于存在 Maven 多模块情况,需要检索每个模块下的编译后的代码路径,用于后续进行 class 等文件的拷贝。

default_target_paths=()

default_java_file=java

module_index=0

# 检索当前项目是否maven多模块开发,递归检索,并设置其编译后的代码位置(暂只提供了java类型)

obtain_module(){

for module in ` cat ./pom.xml | grep '' | awk -F '>' '{print $2}' | awk -F '

do

cd ${module}

if [[ ! -d "/pom.xml" ]]; then

module_exist=`cat ./pom.xml | grep '' | awk -F '>' '{print $2}' | awk -F '

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

复制代码

2.2.6 检索并拷贝变更文件到增量文件夹

git diff --name-only 排查两次 commit 之间文件差异

并将 begin_hash 的 commit 编译后的代码拷贝到增量文件夹中,以备后续打包进行部署

# 通过git diff --name-only实现两次commit之间文件差异,并且将begin_hash的代码进行编译后,将差异的文件拷贝到“增量文件夹”中,以备后续进行增量部署

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##*.}

# 文件所在校验文件夹是否创建

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%%/*}

# 排查在哪个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

# 排查到对应maven模块的target目录,进行cp操作

cp -afx ${default_target_path}/${file_target_package_path}/${file_class_name}* ./${build_path}${current_date}/${package_path}

fi

done

else

# 非java文件,直接拷贝文件到对应目录下

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

到此为止,1.0 版本的简陋版本初步完成,目测可以使用,哈哈哈哈

(完)

推荐阅读:

Java自动生成增量补丁自动部署_Shell脚本结合Git实现增量项目部署相关推荐

  1. java自动生成类_自动生成优化的Java类专业知识

    java自动生成类 如果您今年访问过JavaOne,您可能已经参加了我的演讲"如何从数据库生成定制的Java 8代码". 在那次演讲中,我展示了如何使用Speedment Open ...

  2. java怎么生成字母_java自动生成字母

    新建一个类SpringContextUtil.java: import org.springframework.beans.BeansException; import org.springframe ...

  3. 输入关键词自动生成文章-免费自动输入关键词自动生成文章器

    输入关键词自动生成文章,什么是输入关键词自动生成文章?例:你输入什么关键词 '装修'免费工具会自动生成一篇跟装修相关的文章,该免费工具还支持:自动关键词文章生成+文章自动采集+伪原创+自动发布+自动推 ...

  4. 关于webStrom-11.1配置less且自动生成.css和自动压缩为.min.css/.min.js

    网上看过很多配置思路,自己总结了以下, 就把我个人配置的顺序以及材料分享下,webstrom以下简称WB 1.配置less需要安装nodejs,自行安装.因为要用到npm.我是直接把npm解压到C盘根 ...

  5. python自动生成表格_Python自动整理 Excel 表格

    相信有不少朋友日常工作会用到 Excel 处理各式表格文件,更有甚者可能要花大把时间来做繁琐耗时的表格整理工作.最近有朋友问可否编程来减轻表格整理工作量,今儿我们就通过实例来实现 Python 对表格 ...

  6. 自动生成_一键自动生成CAD图纸目录

    好课推荐: 零基础CAD:点我CAD室内:点我 周站长CAD:点我CAD机械:点我 Bim教程:点我CAD建筑:点我CAD三维:点我全屋定制:点我 ps教程:点我苹果版CAD:点我 3dmax教程:点 ...

  7. python自动生成字幕_自动生成字幕软件?

    其实把视频上传到 Youtube 就好了,前提是视频的声音清晰,它会自动生成字幕,然后再用 Downsub 之类的网站就可以把这个字幕抓下来: 还有一个网站, gosubtitle ,我只试过一次,给 ...

  8. python自动生成表格_Python自动生成绩效考核表并发送邮件

    相信大家经常在工作中见到一些数据报告,比如周报啊,月报啊,绩效考核表之类的数据表格,这些表格每个月我们都需要发送给固定的人,比如领导,对于这些报告,有的需要手工导入数据,而有的其实都是一些固定数据,所 ...

  9. Oracle自动生成ID,自动编号,自增补零填充

    问题 在pl/sql中,需将某个查询结果插入到一个新表tableNameA中时,如何通过sql自动生成ID列,且形如:ID0001,ID0002,ID0003--. 解决方案 insert into ...

  10. php自动生成phpunit,[PHPUnit]自动生成PHPUnit测试骨架脚本

    场景 在编写PHPUnit单元测试代码时,其实很多都是对各个类的各个外部调用的函数进行测试验证,检测代码覆盖率,验证预期效果.为避免增加开发量,可以使用PHPUnit提供的phpunit-skelge ...

最新文章

  1. django搭建示例-ubantu环境
  2. Error Code: 1052. Column '列名' in where clause is ambiguous
  3. 爬虫、框架scrapy
  4. OAuth2.0在项目中的应用
  5. photoshop是用什么编程语言开发的_为什么中国开发不出流行的操作系统和编程语言?...
  6. 自定义控件三部曲之动画篇(一)——alpha、scale、translate、rotate、set的xml属性及用法...
  7. word删除分节符后之前的格式乱了_分页符分节符,你知道多少
  8. 一个关于数组中满足条件的元素选择、及再次排序得c语言函数。
  9. javascript 开发多种类型的应用(Electron 跨平台开发)
  10. html弄多个按钮_html - 一个表单中的两个提交按钮
  11. MySql+Memcached架构的问题
  12. Word技巧:快速将不同字数的姓名对齐
  13. 把握本质规律——《数学之美》作者吴军接受《程序员》采访
  14. INDEX函数与MATCH函数嵌套使用技巧
  15. HTTP接口测试工具及使用
  16. Mac下添加Chrome插件
  17. Java学习笔记-组件及处理事件(二)(ActionEvent,DocumentEvent,ItemEvent)
  18. GitCode 专属开源加速器,帮你实现开源社区运营
  19. 超声波塑料焊接发生器驱动电源设计
  20. 人脸检测算法之 S3FD

热门文章

  1. Atitit 研发体系建立 数据存储与数据知识点体系知识图谱attilax 总结
  2. Atitit.atiDataStoreService   v2 新特性
  3. Atitit..状态机与词法分析  通用分词器 分词引擎的设计与实现 attilax总结
  4. Atitit.mssql 数据库表记录数and 表体积大小统计
  5. Julia: readdlm
  6. 阿里云资深专家起底云网络平台的技术架构升级之路-洛神3.0
  7. 身份密匙~迷惑的要点——大盘点
  8. 35+大龄程序员被清退?
  9. 演过电影的无人驾驶卡车是如何炼成的?
  10. 2019中国云计算十一大趋势预测与分析