053-Jenkins

Jenkins

Jenkins,之前叫做Hudson,是基于Java开发的一种持续集成工具,用于监控秩序重复的工作,包括:

1)、持续的软件版本发布/测试项目。

2)、监控外部调用执行的工作。

下面是官网的简单介绍图:


持续集成

持续集成是一个开发的实践,需要开发人员定期集成代码到共享存储库(比如说svn或git等)。这个概念是为了消除发现的问题,后来出现在构建生命周期的问题。持续集成要求开发人员有频繁的构建。最常见的做法是,每当一个代码提交时,构建应该被触发。


Jenkins安装

Jenkins可以使用最简单的war包安装,命令是java -jar,下载地址:https://jenkins.io/download,或者可以使用docker安装:

docker run -dit --name jenkins -p 8080:8080 jenkins

其它安装方式参见教程或者官网。




SpringBoot项目持续集成

首先创建一个简单的web项目,地址:https://gitee.com/blueses/spring-boot-web.git。


我们平时部署项目的顺序是,开发编译测试通过以后,打一个jar包,放到服务器上,然后直接java -jar启动项目即可,这也是SpringBoot项目的优点,部署简单。


Jenkins很好的继承了这个顺序,并且使过程更加连贯。假设Jenkins所有的配置都是ok的,首先在Jenkins上创建一个maven类型的项目:


接下来配置代码来源,一般代码来源于版本控制系统,此处配置git:

注意上面的分支别错了,如果是私服系统,可以还需要用户名密码,需要在Credentials中配置:

配置好代码以后,就可以处理代码了,一般是利用maven编译和打包:

-U,该参数能强制让Maven检查所有SNAPSHOT依赖更新,确保集成基于最新的状态。


主要的工作完成了,现在运行可以成功执行到打包状态,大部分使用者在这一步之前都不觉得困难,困难的是后面,动态的停止jar包,启动项目,接下来写一些shell脚本:

shell脚本的功能很简单,先判断服务器有没有相同的服务器在运行,有就先杀死,然后将新打包的传输到远程服务器,最后启动。

这里分两种情况,第一种是Jenkins与服务部署在一个服务器上,服务名为app-demo.jar:

# 解决Jenkins自动杀掉衍生进程

OLD_BUILD_ID=$BUILD_ID

BUILD_ID=DONTKILLME


# 智能停止旧服务

pid=`ps -ef|grep app-demo.jar|grep -v grep|awk '{print $2}'`

echo "old id:$pid"

if [ -n "$pid" ]

then

kill -9 $pid 

else 

echo "not running"

fi


# 清理旧的文件

rm -rf /packages/app_demo/*


# 上传并启动新的服务

cp ~/.jenkins/workspace/app-demo/target/app-demo.jar /packages/app_demo/

nohup java -jar /packages/app_demo/app-demo.jar >> /packages/app_demo/nohup.out &


# 解决Jenkins自动杀掉衍生进程

BUILD_ID=$OLD_BUILD_ID



另一种情况是服务单独部署在一个服务器上,这个时候需要做一个ssh免密登录,然后使用远程执行命令的方式:

ssh  user@ip  "命令内容"


假如服务要部署的ip为192.168.1.111,具体Jenkins脚本如下:

#解决Jenkins自动杀掉衍生进程

OLD_BUILD_ID=$BUILD_ID

BUILD_ID=DONTKILLME


# 智能停止服务

pid=`ssh [email protected] "ps -ef|grep app-demo.jar|grep -v grep"|awk '{print $2}'`

echo "old pid=$pid"

if [ -n "$pid" ]

then 

ssh [email protected] "kill -9 $pid"

else

echo "not running"

fi


# 清理旧文件

ssh [email protected] "rm -rf /packages/app_demo/*"


#上传并启动

scp ~/.jenkins/workspace/app-demo/target/app-demo.jar [email protected]:/packages/app_demo/

ssh [email protected] "source /etc/profile;nohup java -jar /packages/app_demo/app-demo.jar >> /packages/app_demo/nohup.out &"


# 解决Jenkins自动杀掉衍生进程

BUILD_ID=$OLD_BUILD_ID



上面的shell脚本中,开头和结尾是必须的,因为Jenkins会杀掉衍生进程。清理旧文件部分和上传并启动服务的命令对开发人员并没有什么难度,但是智能停止服务命令部分人员可能不太明白,简单介绍一下。


给pid赋值,就能打印出出来,这个不用说:


下面介绍pid的赋值语句,比如一个服务jar包为 spring-boot-web-0.0.1-SNAPSHOT.jar,那么下面的命令大家可能有些熟悉:

ps -ef|grep spring-boot-web-0.0.1-SNAPSHOT.jar

结果为:

ps命令将某个进程显示出来,

grep命令是查找,

中间的|是管道命令 是指ps命令与grep同时执行,

PS是LINUX下最常用的也是非常强大的进程查看命令,

grep命令是查找,是一种强大的文本搜索工具,它能使用正则表达式搜索文本,并把匹配的行打印出来。

grep全称是Global Regular Expression Print,表示全局正则表达式版本,它的使用权限是所有用户。

以下这条命令是检查java 进程是否存在:ps -ef |grep java

字段含义如下:

UID      :程序被该 UID 所拥有

PID      :就是这个程序的 ID 

PPID    :则是其上级父程序的ID

C          :CPU使用的资源百分比

STIME :系统启动时间

TTY     :登入者的终端机位置

TIME   :使用掉的CPU时间。

CMD   :所下达的是什么指令


所以ps -ef|grep spring-boot-web-0.0.1-SNAPSHOT.jar就是检查对应的服务,再看下一步,加上 grep  -v  grep  效果:

可以看到,出现的多条结果只剩下一条了,原来的命令为什么会有两条呢?因为一条结果属于当前命令本身,另一条才是要的Java结果,后面加上grep -v是反向过滤的意思,grep -v grep 就是把本条命令的结果去掉,如果要去掉java本身的结果,可以执行grep  -v  java:

看最后一部分  awk {print $2},先看一下执行结果:

awk是行处理命令,简单说,就是会把前面得到的结果一行一行进行处理,比如不进行反向过滤,那结果肯定有两条:

再看一下后面的处理,单引号中是大括号,大括号中可以看出是个print打印语句,$2表示第二列的值,这个和Java不同,不是从0开始的,如果写$0会打印整行:

因为项目是jar包启动的,最有效的停止方法就是kill命令,所以需要获取进程id,可以看到$2位置的值就是我们要的进程id,所以这条命令应该好理解了:

就是获取运行中对应java进程的id,并赋值给pid,注意pid=后面要加飘号``。在Java代码中用不到这个,但是shell中会用到,位置就在~键上。


前面的获取pid的脚本可以看明白了,结果就是有对应Java项目在运行,pid就有值,没有就是空的。最后再来看一下if语句,这个在shell中以if开头,fi结尾,判断条件放在中括号内,尤其要注意的一点,也是我犯了很多次错的一点,左右中括号的左右两端都要加空格,这个是必须的!!!



对开发人员来说,脚本有难点的大概介绍完了,总结一下流程,Jenkins持续集成就是从版本库拉代码到Jenkins所在的服务器,然后用maven编译打包,用脚本部署,这样能达到提交代码后构建,就能看到最新效果,有需要还可以查查如果用Jenkins定期构建。除了脚本,还可以使用pipeline流水线的方式(推荐Blue Ocean版本),还可以集成docker或者k8s进行容器化部署。上面的方案简单有效,适合程序员在测试环境使用,至于正式环境,要看自己公司的运维大神的身手了!

你可能感兴趣的:(053-Jenkins)