「Jenkins+Git+Maven+Shell+Tomcat持续集成」经典教程

Jenkins 是一个开源软件项目,旨在提供一个开放易用的软件平台,使软件的持续集成变得可能。现在软件开发追求的是效率以及质量,Jenkins使得自动化成为可能!

亮点

  • 采用shell自定义脚本,控制集成部署环境更加方便灵活
  • 精简war包中的lib包,常驻tomcat里,减少war包传输时间
  • Jenkins 用户权限管理
  • 构建失败发邮件通知相关人员解决
  • 自动按天备份war包,Jenkins配置备份以及版本控制化

环境

Ubuntu 14.10 (GNU/Linux 3.16.0-33-generic x86_64)

准备工作

  • Git版本控制服务器
  • Tomcat发布服务器
  • Jenkins服务器(提前安装好Maven,Git,Jdk)

实验时可以在同一台机器配置,但是生产不建议,一台机器电源断掉了,所有服务器都挂了

步骤

安装Jenkins

下载Jenkins War包,Jenkins官网 。

启动Jenkins ,将War包放入Tomcat容器里,启动Tomcat。

提示:
此时Jenkins在初始化配置目录,其默认配置目录路径为当前用户下的.jenkins目录,用户也可以自定义目录,Jenkins默认是把配置文件中的数据读到内存中,如果你替换了之前的配置文件,此时需要点击「Jenkins的读取设置」或者「重启Tomcat」,如果此时Jenkins页面无响应,则应该查看Tomcat的Catalina.out,多半是由于内存溢出造成(解决方法增大Tomcat调用Java虚拟机时内存大小,本文不做重点),运行Jenkins的服务器配置最好内存1G以上,因为后续会加入一些Jenkins插件,有一些会比较占用内存,导致Jenkins启动不了。

安装Jenkins插件

  • Email Extension Plugin (邮件通知)
  • GIT plugin (可能已经默认安装了)
  • Publish Over SSH (远程Shell)

安装方法:
首页->系统管理->管理插件->可选插件->过滤(搜索插件名)->勾选->点击最下面直接安装即可(需要等待一段时间,详情可以看catalina.out日志变化)

配置Jenkins

配置基本信息

每个选项后都有个问号解释当前含义,(此步新手可以略过,默认不填即可)
配置方法:首页->系统管理->系统设置

配置邮件

管理员邮件地址就是邮件的发件人地址(必须和后面邮件配置发件人邮箱一致,否则发不成功邮件)

配置Jdk

JAVA_HOME为Jdk路径 其中Jdk也可以从这里下载安装解压

配置 Maven

配置 Maven Configuration

路径为maven的setting.xml路径(Maven安装略)

配置Maven项目

配置Maven安装目录

配置 Git

其中Path to Git executable为你git执行的路径 一般默认是/usr/bin/git ,如有差异,可以whereis git

配置邮件

邮件模板配置

配置好邮件的模板(可自定义html编写) User Name为用户名 Password为密码 SMTP不同邮箱不同,请自行google(另外gmail邮件如无代理翻墙,请勿用,推荐163比较好配置)

未翻墙

翻墙后

模板效果图

Default Subject 代码:

构建通知:$PROJECT_NAME - Build # $BUILD_NUMBER - $BUILD_STATUS!

模板Default Content分享:

(本邮件是程序自动下发的,请勿回复,<span style="color:red">请相关人员fix it,重新提交到git 构建</span>)<br/><hr/>项目名称:$PROJECT_NAME<br/><hr/>构建编号:$BUILD_NUMBER<br/><hr/>GIT版本号:${GIT_REVISION}<br/><hr/>构建状态:$BUILD_STATUS<br/><hr/>触发原因:${CAUSE}<br/><hr/>构建日志地址:<a href="${BUILD_URL}console">${BUILD_URL}console</a><br/><hr/>构建地址:<a href="$BUILD_URL">$BUILD_URL</a><br/><hr/>变更集:${JELLY_SCRIPT,template="html"}<br/><hr/>

配置邮件触发器
当失败的时候,会触发邮件通知,这个功能比较实用。

配置 Publish over SSH

远程执行shell脚本 采用公钥私钥连接 其中Key里贴的是私钥 远程被管理的主机里贴的是公钥,这2台主机就是相互信任,这样scp等操作就不需要输入用户名和密码

公钥私钥生成方法:

1.管理主机linux 上 ssh-keygen -t rsa -C "mousycoder@foxmail.com 一路回车 会在/root/.ssh下生成id_rsa(私钥) id_rsa.pub(公钥)。

2.copy 公钥的内容到远程需要通信(被管理)的主机 /root/.ssh/authorized_keys 如无此目录文件则手动创建。

配置完之后可以Test Configuration

配置 Job

步骤:首页->新建->构建一个maven项目(输入item名称)->进入该项目->配置

JOB基本信息

项目源码管理
Repository UR 项目地址 Credentials授权可以是SSH也可以是用户名密码(SSH方法同上)

选择需要构建的分支,我们项目采用git工作流 默认master和develop 平时开发构建develop分支,正式上线构建master并且打标签(前公司git提交标准化相当复杂,分支相当多,这里大家可以根据实际情况来)。

构建触发器

这里我们选择poll轮询每隔1分钟去检测git仓库代码库版本,如果有更改则立刻构建,这里大家可以根据自己团队实际情况去制定,当然还有另外一个插件gitlab-hook可以主动去通知jenkins构建,不过插件所占内存比较大,需要增大tomcat虚拟机内存配置,不然会内存溢出。

构建命令

我们采用最简单的clean install 当然这里可以根据各自需求
例如 部署后的产物上传到nexus等,详情参考 Maven命令

clean install deploy:deploy-file -DgroupId=com.weitoo -DartifactId=common -Dversion=0.1-SNAPSHOT -Dpackaging=jar -Dfile=D:\workspace\server-aggregator\common\target\common-0.1-SNAPSHOT.jar -Durl=http://192.168.0.200:8081/nexus/content/repositories/thirdparty/ -DrepositoryId=thirdparty

Add post-build step

构建成功后执行shell命令

该shell的目的是取出war包lib中其他所有lib包 只留下common-0.1-SNAPSHOT.jar 大大减少war包大小(完整war包30M 传包到阿里云服务器需要2分多,精简后2M,10秒多,大大提高构建速度)。

分享我的Shell

mv ~/.jenkins/jobs/server/workspace/server/target/server/WEB-INF/lib/common-0.1-SNAPSHOT.jar ~/.jenkins/jobs/server/workspace/server/target/
rm -rf ~/.jenkins/jobs/server/workspace/server/target/server/WEB-INF/lib/*
rm -rf ~/.jenkins/jobs/server/workspace/server/target/server.war 
mv ~/.jenkins/jobs/server/workspace/server/target/common-0.1-SNAPSHOT.jar ~/.jenkins/jobs/server/workspace/server/target/server/WEB-INF/lib/
cd ~/.jenkins/jobs/server/workspace/server/target/server/
zip -r ~/.jenkins/jobs/server/workspace/server/target/server.war * -r
scp /root/.jenkins/jobs/server/workspace/server/target/server.war root@123.56.xxx.xx:/opt/war/

构建成功远程执行shell脚本

exec command 是远程sh的路径

分享我的publish.sh文件

作用是备份每次上传的war包 重启Tomcat。


export JAVA_HOME=/opt/software/jdk1.7.0_25
TOMCAT_HOME="/opt/software/apache-tomcat-7.0.59"
TOMCAT_PORT=80
PROJECT="server"
BAK_DIR=/opt/war/bak/$PROJECT/`date +%Y%m%d`mkdir -p "${BAK_DIR}"
cp /opt/war/"${PROJECT}".war "${BAK_DIR}"/"${PROJECT}"_`date +%Y%m%d%H%M%S`.war#shutdown tomcat
/opt/sh/kill-tomcat-force.sh#publish project 
rm -rf "${TOMCAT_HOME}"/webapps/${PROJECT}
cp /opt/war/"${PROJECT}".war "${TOMCAT_HOME}"/webapps/${PROJECT}.war
q
#remove tmp
rm -rf /opt/war/${PROJECT}.war#unzip war
unzip "${TOMCAT_HOME}"/webapps/${PROJECT}.war -d "${TOMCAT_HOME}"/webapps/${PROJECT}rm -rf "${TOMCAT_HOME}"/webapps/${PROJECT}.war##copy lib
cp /opt/lib/* "${TOMCAT_HOME}"/webapps/${PROJECT}/WEB-INF/lib/## start tomcatsleep 3#start tomcat
/opt/software/apache-tomcat-7.0.59/bin/startup.sh
echo "tomcat is starting!"

分享我的kill-tomcat-force.sh文件

作用是强制关闭tomcat进程


set fileformat=unixpath=/opt/software/apache-tomcat-7.0.59/binps -ef|grep $path|grep tomcat|awk '{print $2}'echo "exec $path/shutdown.sh"
$path/shutdown.shsleep 3s#kill -9 pid
ps -ef|grep $path|grep tomcat|awk '{print $2}'|xargs kill -9#success msg
echo "shutdown success"ps -ef|grep $path|grep java|awk '{print $2}'

分享我的Tomcat精简方法

  • 在tomcat_home/lib下新建自定义jar包文件,导入项目所需其他jar包(以后有新增的话,单独再导一次)
  • 修改tomcat_home/conf/catalina.properties 搜索=shared.loader加上路径
shared.loader=${catalina.base}/lib/server,${catalina.base}/lib/server/*.jar,${catalina.home}/lib/server,${catalina.home}/lib/server/*.jar

此时Tomcat运行前会加载server下的lib包,如果是多个项目公用一个tomcat的时候,就需要这里放公共的lib包,避免tomcat加载多余的jar包,消耗内存。

构建后邮件设置

邮件主题收件人配置

邮件触发器

局部配置会覆盖掉全局配置,我们之前在全局配置里配置了构建失败邮件触发器,这里是更加精细的配置,

我们选择构建失败Failure-1st触发器,失败以后发邮件给开发者,(这里可以根据实际需要,配置,可以配置多个触发器)开发者的邮件在Recipient List里配置。

Jenkins用户权限管理

步骤:首页-> 系统管理-> Configure Global Security
基本配置:
只有注册的用户才能操作,当然如果是大企业的话,可以采用项目矩阵授权策略,详情可以Google。

Jenkins配置的备份和版本控制

很多情况下稍不注意改变了Jenkins的配置,把平台弄坏了,又想去恢复,这个时候就得把Jenkins的配置文件进行配置或者版本化,只需要把/root/.jenkins/加入git版本库里即可,该目录下包含Jenkins所有信息,包括每次构建历史信息和历史jar包
进行全备份然后覆盖掉该文件夹的时候,重新构建JOB会出现文件夹已经存在等exception,只需要手动删掉这些目录即可,不会丢失数据。(这是Jenkins的一个bug,参考 JENKINS-21330)

参考资料

  • Jenkins权威指南
  • jdkleo

感谢您的耐心阅读,如果您发现文章中有一些没表述清楚的,或者是不对的地方,请给我留言,你的鼓励是作者写作最大的动力,
如果您认为本文质量不错,读后觉得收获很大,不妨小额赞助我一下,让我更有动力继续写出高质量的文章。

  • 支付宝

  • 微信


作 者 : @mousycoder

原文出处 : http://mousycoder.com/2015/10...

创作时间:2015-6-11

更新时间:2015-12-2

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/400192.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

使用Altium Designer进行DDR2的PCB设计(转比较不错)

转载于&#xff1a;http://blog.csdn.net/snaking616/article/details/53981973 本文首先列出了DDR2布线中面临的困难&#xff0c;接着系统的讲述了DDR2电路板设计的具体方法&#xff0c;最后给出个人对本次电路设计的一些思考。本次设计中CPU的封装为BGA844-SOC-Y&#xff0c;…

【机器视觉学习笔记】OpenCV C++ 与 HSV颜色模型

目录HSV颜色模型Opencv中的HSV获取颜色值的小工具平台&#xff1a;Windows 10 20H2 Visual Studio 2015 opencv_contrib-3.4.12 HSV颜色模型 本节内容摘自HSV模型及opencv应用 —— ponponon 这个模型中颜色的参数分别是&#xff1a;色调&#xff08;H&#xff09;&#xff…

win10 解决升级 WordPress 时提示”另一更新正在进行”

1. 确定 wordpress 目录的 users 权限为 完全控制。 2. https://www.wpdaxue.com/wordpress-update-problem.html 本文目录 [隐藏] 1情景再现2解决办法 WordPress 4.5 下载安装量已经超过 600 万&#xff0c;而第一个维护版本 WordPress 4.5.1 已发布&#xff0c;修复了 Wo…

清除Linux终端命令的历史记录

在Linux终端下1、运行history&#xff0c;可以得到一个整洁的Linux终端命令历史记录的列表2、运行history -c&#xff0c;可以清除杂乱的历史记录&#xff08;需要重启&#xff09;3、运行history -r /home/yajiu/history.txt&#xff0c;可以将history.txt文件存储的常用命令读…

暑假集训D19总结

考试 日常爆炸 T1 辣么简单&#xff0c;淼到极致的DP&#xff0c;我竟然打挂了 &#xff0c;打挂了 &#xff0c;只拿了75分啊&#xff0c;不能接受啊 T2 随便找找规律&#xff0c;瞎XX模拟一下就能A的鬼东西&#xff0c;我竟然打了个暴力Floyed判环&#xff08;是叫这个鬼…

【STC15库函数上手笔记】7、PCA与PWM

目录硬知识硬件知识CCP/PWM/PCA模块的结构软件知识PCA初始化函数PWM更新占空比函数测试程序PWM模式产生PWM信号main.c实验现象16位软件定时器模式模式产生PWM信号main.c实验现象捕获模式测量周期长度main.c实验现象STC实验箱4 IAP15W4K58S4 Keil uVision V5.29.0.0 PK51 Prof…

单元测试概述

盖种测试 1.语句覆盖&#xff1a;语句覆盖是几个测试用例的设计&#xff0c;通过测试程序运行。使每一个可以运行的语句至少运行一次。 2.判定覆盖&#xff08;也叫分支覆盖&#xff09;&#xff1a;设计若干个測试用例。运行所測程序&#xff0c;使程序中每一个…

JQuery官方学习资料(译):遍历JQuery对象和非JQuery对象

JQuery提供了一个对象遍历的Utility方法$.each()和一个JQuery集合遍历方法.each()。$.each()$.each()是一个通用的方法用来遍历对象和数组&#xff0c;Plain对象是通过其命名属性进行遍历的。$.each()可以用来替换传统的for和for-in循环。var sum 0;var arr [ 1, 2, 3, 4, 5 …

【STC15库函数上手笔记】8、比较器

目录库函数compare.ccompare.hSTC15Fxxxx.H测试程序main.cSTC实验箱4 IAP15W4K58S4 Keil uVision V5.29.0.0 PK51 Prof.Developers Kit Version:9.60.0.0 库函数 比较器的库函数仅在官方例程中发现&#xff0c;未与其他库函数放在一起&#xff0c;笔者也未对其进行测试&…

WIN10 下 PHP7 中文乱码的解决办法

在数据提交前&#xff0c;插入语句 mysqli_set_charset($conn,utf8);

不会几个框架,都不好意思说搞过前端: Vue.js - 60分钟快速入门

Vue.js——60分钟快速入门 Vue.js是当下很火的一个JavaScript MVVM库&#xff0c;它是以数据驱动和组件化的思想构建的。相比于Angular.js&#xff0c;Vue.js提供了更加简洁、更易于理解的API&#xff0c;使得我们能够快速地上手并使用Vue.js。 本文摘自&#xff1a;http://www…

指针以及内存分配

原文&#xff1a;http://blog.csdn.net/bizhu12/article/details/6532235 1. 指针很灵活,这使得指针很难管理,在定义指针时,将在栈中开辟一块内存存放指针的地址(栈内的内存由系统分配和释放),指针的地址内存只是存放指针的地址,不存放指针指向的数据,值得注意的是,定义指针时指…

建议11: 区别对待==和Equals

建议11&#xff1a; 区别对待和Equals在开始本建议之前&#xff0c;首先要明确概念“相等性”。CLR中将“相等性”分为两类&#xff1a;“值相等性”和“引用相等性”。如果用来比较的两个变量所包含的数值相等&#xff0c;那么将其定义为“值相等性”&#xff1b;如果比较的两…

mysql如何修改开启允许远程连接

关于mysql远程连接的问题&#xff0c;大家在公司工作中&#xff0c;经常会遇到mysql数据库存储于某个人的电脑上&#xff0c;大家要想连接mysql服务&#xff0c;装有mysql服务的电脑就必须开启远程连接 第一步&#xff0c;用dos连接上你的数据库&#xff0c;&#xff08;我这里…

Objective-C马路成魔【14-关键C语言功能】

郝萌主倾心贡献&#xff0c;尊重作者的劳动成果&#xff0c;请勿转载。 假设文章对您有所帮助&#xff0c;欢迎给作者捐赠&#xff0c;支持郝萌主。捐赠数额任意&#xff0c;重在心意^_^ 我要捐赠: 点击捐赠 Cocos2d-X源代码下载&#xff1a;点我传送 这里介绍一些特性&#x…

Solidworks如何自动打开和关闭特征识别FeatureWorks

如果直接对已有的零件识别特征&#xff0c;可能会报错 删除多余的特征&#xff0c;先只保留一个输入&#xff08;注意没有必要连草图也删掉&#xff0c;草图不会影响识别特征&#xff0c;你识别完了之后草图再接着该拉伸拉伸&#xff0c;该切除切除&#xff09;&#xff0c;然后…

SPI驱动0.96/1.3寸 OLED屏幕,易修改为DMA控制

目录OLED SPI 端口定义七针OLED引脚定义六针OLED引脚定义驱动程序oled.coled.holedfont.h使用main.c实验现象STC实验箱4 IAP15W4K58S4 Keil uVision V5.29.0.0 PK51 Prof.Developers Kit Version:9.60.0.0 DMA控制见【0.96寸 OLED屏实现1500Fps的帧率】STM32 软件、硬件SPI、…

分享网页到微信朋友圈的官方接口

看到 JiaThis 增加了微信分享的按钮&#xff0c;查看了下网络请求&#xff0c;是官方提供的接口&#xff0c;不过官方文档还没有这方面的信息。这个接口应该是合作测试中的&#xff0c;不排除以后会更改或者停用。 目前分享到微信朋友圈不同于通常的分享&#xff0c;需要先向微…

WordPress PHP Fatal Error “Maximum execution time of 30 seconds exceeded” 的解决办法

修改Wp-config.php 在wp-config.php中增加一行&#xff0c;注意在/* That’s all, stop editing! Happy blogging. */”这一行之前加入&#xff1a; set_time_limit(60); https://blog.csdn.net/cnpinpai/article/details/84575015

上传图片在页面上显示

看了别人写的 自己照着写了一下 <% page language"java" import"java.util.*" pageEncoding"UTF-8"%> <% String path request.getContextPath(); String basePath request.getScheme()"://"request.getServerName()"…