Jenkins+Maven+Sonar系统持续集成环境部署以及配置

修改默认镜像源

vim /var/lib/jenkins/hudson.model.UpdateCenter.xml

<?xml version='1.1' encoding='UTF-8'?>
<sites>
<site>
<id>default</id>
<url>https://jenkins-zh.gitee.io/update-center-mirror/tsinghua/update-center.json</url>
</site>
</sites>

或者:

jenkins ==>系统管理 ==> 插件管理 ==> 高级 ==> 升级站点

-------------------------------------------------------------------------------------------------------------

想要“不自动构建下级项目”,需要在下级项目中配置

Build whenever a SNAPSHOT dependency is built    把这个选项取消掉就可以了

--------------------------------------------------------------------------------------------------------------

更改Jenkins启动的用户时的步骤:

1、# vim /etc/sysconfig/jenkins

JENKINS_USER="wjoyxt"

2、# chown -R wjoyxt.wjoyxt /var/log/jenkins /var/lib/jenkins /var/cache/jenkins  这三个目录

--------------------------------------------------------------------------------------------------------------

忘记密码时的处理办法:

打开忘记密码的用户文件夹,默认 /var/lib/jenkins/users ,里面就一个文件config.xml。打开config.xml,找到<passwordHash>项,

把其中的hash值先改成   "#jbcrypt:$2a$10$DdaWzN64JgUtLdvxWIflcuQu2fgrrMSAMabF5TSrGK5nXitqK9ZMS"

保存并重启jenkins,此时被修改用户的密码变为 "",进入jenkins后再通过用户管理重新设置自己的密码即可。

另:Jenkins中复制job的方法:复制/var/lib/jenkins/jobs中的项目目录,并改成要新建的项目名称即可。

--------------------------------------------------------------------------------------------------------------

一、Jenkins介绍以及安装

什么是持续集成?   
随着软件开发复杂度的不断提高,团队开发成员间如何更好地协同工作以确保软件开发的质量已经慢慢成为开发过程中不可回避的问题。尤其是近些年来,敏捷(Agile) 在软件工程领域越来越红火,如何能再不断变化的需求中快速适应和保证软件的质量也显得尤其的重要。 
持续集成正是针对这一类问题的一种软件开发实践,对于提高软件开发效率并保障软件开发质量提供了理论基础。它倡导团队开发成员必须经常集成他们的工作,甚至每天都可能发生多次集成。而每次的集成都是通过自动化的构建来验证,包括自动编译、发布和测试,从而尽快地发现集成错误,让团队能够更快的开发内聚的软件。 
持续集成最早由Martin Fowler 于10年前已经提出,希望通过持续集成能够实现以下过程:

 任何人在任何地点,任何时间可以构建整个项目。

 在持续集成构建过程中,每一个单元测试都必须被执行。

 在持续集成构建过程中,每一个单元测试都必须通过。

 持续集成构建的结果是可以发布的软件包。

 当以上任何一点不能满足时,整个团队的主要任务就是去解决这个问题

持续集成的核心价值

持续集成中的任何一个环节都是自动完成的,无需太多的人工干预,有利于减少重复过程以节省时间、费用和工作量;

持续集成保障了每个时间点上团队成员提交的代码是能成功集成的。换言之,任何时间点都能第一时间发现软件的集成问题,使任意时间发布可部署的软件成为了可能;

持续集成还能利于软件本身的发展趋势,这点在需求不明确或是频繁性变更的情景中尤其重要,持续集成的质量能帮助团队进行有效决策,同时建立团队对开发产品的信心。

本文此处采用yum安装方式

除了直接java -jar jenkins.war方式,还可以用yum安装,这种方式下提供了更多的可配置选项,更适合生产环境控制jenkins的行为。

1
2
3
sudo wget -O /etc/yum.repos.d/jenkins.repo http://pkg.jenkins-ci.org/redhat/jenkins.repo
sudo rpm --import http://pkg.jenkins-ci.org/redhat/jenkins-ci.org.key
sudo yum install jenkins

安装完成后,可用

1
sudo service jenkins start/stop/restart

不过,我在centos 7环境上测试下来,/etc/rc.d/init.d/jenkins这个脚本写得有点小问题,如果java不在默认目录下,会导致启动失败

1
sudo vim /etc/rc.d/init.d/jenkins +67

定位到67行,会发现该脚本会从以下位置找java可执行文件

1
2
3
4
5
6
7
8
9
10
candidates="
/etc/alternatives/java
/usr/lib/jvm/java-1.6.0/bin/java
/usr/lib/jvm/jre-1.6.0/bin/java
/usr/lib/jvm/java-1.7.0/bin/java
/usr/lib/jvm/jre-1.7.0/bin/java
/usr/lib/jvm/java-1.8.0/bin/java
/usr/lib/jvm/jre-1.8.0/bin/java
/usr/bin/java
"

如果java没安装在这些目录下,启动就会失败,解决办法:把java所在的正确位置加入其中即可,比如:

1
2
3
candidates="
/usr/local/java/jdk-1.8.51/bin/java
"

注:这样处理后,还要执行一下sudo systemctl daemon-reload,然后就可以service jenkins start了,如果还出错,尝试 cd /etc/rc.d/init.d,然后sudo ./jenkins start 进一步排查。建议同学们把这个启动脚本仔细阅读一下,可以发现很多有用的信息,比如:

1
2
3
4
5
JENKINS_WAR="/usr/lib/jenkins/jenkins.war"
JENKINS_CONFIG=/etc/sysconfig/jenkins
JENKINS_PID_FILE="/var/run/jenkins.pid" 
PARAMS="--logfile=/var/log/jenkins/jenkins.log --webroot=/var/cache/jenkins/war --daemon"
--simpleAccessLogger.file=/var/log/jenkins/access_log

上面这些参数定义了配置文件、war包、pid文件、日志的位置,出问题时,我们可以直接到这些位置去查看详情。

比如:端口8080被占用了,需要更改启动端口,直接查看/etc/sysconfig/jenkins这个文件,找到

1
JENKINS_PORT="8080"

修改一下即可。

/etc/sysconfig/jenkins这个文件为jenkins的参数配置文件,比如:

JENKINS_USER="jenkins"
JENKINS_HOME="/var/lib/jenkins"
JENKINS_AJP_PORT="8009"
JENKINS_DEBUG_LEVEL="5"
JENKINS_ENABLE_ACCESS_LOG="no"
 
 
安装完成后,在结合Maven和Sonar时需要事先安装SonarQube Plugin和Maven Integration plugin这两个插件。
或者从http://ftp.tsukuba.wide.ad.jp/software/jenkins/plugins/直接下载相应的hpi文件,然后进入到"插件管理--高级--上传插件" 进行手动导入安装。
 

构建的状态:下图中分级符号概述了一个Job新近一次构建会产生的四种可能的状态:

Successful:完成构建,且被认为是稳定的。

Unstable:完成构建,但被认为不稳定。

Failed:构建失败。

Disabled:构建已禁用。

Jenkins+Maven+Sonar系统持续集成环境部署以及配置

 
 构建的稳定性:
Jenkins会基于一些后处理器任务为构建发布一个稳健指数 (从0-100 ),这些任务一般以插件的方式实现。它们可能包括单元测试(JUnit)、覆盖率(Cobertura )和静态代码分析
(FindBugs)。分数越高,表明构建越稳定。下图中分级符号概述了稳定性的评分范围。任何构建作业的状态(总分100)低于80分就是不稳定的。
 
Jenkins+Maven+Sonar系统持续集成环境部署以及配置
 
二、Sonarqube安装配置
 
1、从Sonar官网 http://www.sonarqube.org/downloads/ 下载,解压下载好的zip包
2、配置 /usr/local/sonarqube/conf/sonar.properties
sonar.jdbc.username=sonar
sonar.jdbc.password=sonar
sonar.jdbc.url=jdbc:mysql://localhost:3306/sonar?useUnicode=true&characterEncoding=utf8&rewriteBatchedStatements=true&useConfigs=maxPerformance

3、mysql数据库配置

根据官网提供的文档,http://docs.sonarqube.org/display/SONAR/Requirements 可以得到该版本所需求的基础环境(JDK和数据库版本等),所以这里先创建好所需的mysql数据库

mysql> CREATE DATABASE sonar CHARACTER SET utf8 COLLATE utf8_general_ci; 
mysql> CREATE USER 'sonar' IDENTIFIED BY 'sonar';
mysql> GRANT ALL ON sonar.* TO 'sonar'@'%' IDENTIFIED BY 'sonar';
mysql> GRANT ALL ON sonar.* TO 'sonar'@'localhost' IDENTIFIED BY 'sonar';
mysql> FLUSH PRIVILEGES;

4、启动Sonar服务,默认9000端口

目录切换至sonar的<install_directory>/bin/linux-x86-64/目录,启动服务
#./sonar.sh start   启动服务
#./sonar.sh stop    停止服务
#./sonar.sh restart 重启服务

5、中文语言包安装的两种方式
  • 安装中文补丁包可以通过访问http:\\localhost:,用户名和密码都是admin。打开sonar后,进入更新中心Available安装 "Chines Pack"
  • 或者从下载地址:https://github.com/SonarQubeCommunity/sonar-l10n-zh下载对应版本的中文补丁包后,放到SONARQUBE_HOME/extensions/plugins目录,然后重启SonarQube服务

各版本相对应的语言包:https://github.com/SonarQubeCommunity/sonar-l10n-zh/releases

6、安装需要进行代码分析的Java、PHP语言分析插件, "配置--系统--更新中心"

三、SonarQube Scanners安装配置
 
官方文档也介绍的挺清楚:http://docs.sonarqube.org/display/SCAN/Analyzing+with+SonarQube+Scanner 
 
1、同样从http://www.sonarqube.org/downloads/进行下载后解压到/usr/local/
2、修改/usr/local/sonar-scanner/conf/sonar-scanner.properties
sonar.host.url=http://10.0.30.180:9000
sonar.sourceEncoding=UTF-

3、配置环境变量/etc/profile,此处一并加上SONARQUBE_HOME的变量

export SONARQUBE_HOME=/usr/local/sonarqube

export SONAR_RUNNER_HOME=/usr/local/sonar-scanner/

export PATH=$SONAR_RUNNER_HOME/bin:$PATH
 
四、以命令行方式使用SonarQube Runner对源码进行分析
 
参考官方资料 http://docs.sonarqube.org/display/SCAN/Analyzing+with+SonarQube+Scanner
1、在项目源码的根目录下创建sonar-project.properties配置文件,然后直接执行sonar-scanner
sonar.projectKey=prepare-agent
sonar.projectName=prepare-agent
sonar.projectVersion=1.0
sonar.sources=.
sonar.language=java
sonar.sourceEncoding=UTF-
参数介绍如下:

工程的key和name维护成一样即可

  sonar.projectKey=weike_open
  sonar.projectName=weike_open

  #当前工程的版本
  sonar.projectVersion=1.7.1.0
  #进行扫描分析的代码*目录

  sonar.sources=src

  # 分析的语言
  sonar.language=java
  # 源码编码格式
  sonar.sourceEncoding=UTF-8

2、官网实例测试,查看是否出图以及出图结果,以此来验证部署是否成功。

Sonar官方已经提供了非常全的代码样例便于新手入门用。

下载地址:https://github.com/SonarSource/sonar-examples/archive/master.zip

下载后使用unzip解压。进入执行sonar-scanner命令即可。执行完成后查看SonarQube的Web界面,正常的话应该就可以看到分析的结果啦。

例如进入解压后的 sonar-examples-master/projects/languages/java/sonar-runner/java-sonar-runner-simple 目录,直接运行sonar-scanner即可验证Sonarqube以及Sonar-scanner是否已安装部署正确。
在进行对不同语言的源码进行分析前,要确认是否已经在Sonar安装了相应的语言支持插件,例如访问http:\\localhost:9000更新中心添加Android、PHP插件,使其可以分析Android和PHP规则
 
注:抛开Jenkins不谈,直接用Sonnar就可以对源代码进行质量分析。所以,你需要在系统下先把Sonnar跑通,让它能在命令行下分析源代码。确定这一步没有问题啦,再跟Jenkins做持续集成。当然了Maven打包也是同样的道理。
 
五、在Jenkins中进行Sonar集成时的相关设置
 
1、系统管理---Global Tool Configuration
Jenkins+Maven+Sonar系统持续集成环境部署以及配置
 
Jenkins+Maven+Sonar系统持续集成环境部署以及配置
Jenkins+Maven+Sonar系统持续集成环境部署以及配置
 
 
2、系统管理---系统设置
 
Jenkins+Maven+Sonar系统持续集成环境部署以及配置
 
此处的token值取自Sonar的web界面的"我的账号----安全"
 
3、在新建项目时或修改已有项目的配置, Repository URL根据自己要构建的项目的不同svn地址而进行修改。
Jenkins+Maven+Sonar系统持续集成环境部署以及配置
 
构建触发器:
 
Jenkins+Maven+Sonar系统持续集成环境部署以及配置 
 

Build whenever a SNAPSHOT dependency is built:当此项目所依赖的项目在jenkins中被构建时触发开始进行构建
Build after other projects are built:在某个项目被构建后,构建此项目 
Build periodically:按照指定的时间间隔进行自动构建,不管代码有没有变更。 
Poll SCM:按照指定的时间间隔对SCM进行检测,如果代码库有更新则拉取后进行构建。

 
 
Jenkins+Maven+Sonar系统持续集成环境部署以及配置
Jenkins+Maven+Sonar系统持续集成环境部署以及配置
 
Jenkins+Maven+Sonar系统持续集成环境部署以及配置
这一步呢,多说两句。我这边采用的shell+ansible进行的自动化执行版本发布和更新以及回滚。
# cat /home/sunyl/jenkins/openrc  环境定义文件   env其实就是在jenkins中的项目名称

workspace=/data/workspace/online-ucenter-front
appname=resin  此处的appname代表的是tomcat或resin的文件夹名称,例如:dubbo  resin  tomcat-web  tomcat-manager  tomcat-zhibo
env=online-ucenter-front(生产环境)   或 prepare-ucenter-fromt(预发布环境)

 
# cat /home/sunyl/jenkins/prepare 相当于host文件
[online-ucenter-front]
10.0.30.155
 
# cat /home/sunyl/jenkins/java.sh
#!/bin/bash
#添加环境相关变量
source /home/sunyl/jenkins/openrc #以时间命名目录名称
time=`date +"%Y%m%d-%H%M%S"` #使用的hosts文件
hosts=`echo $env|awk -F '-' '{print $1}'` #目标应用启动路径
if [[ "$appname" =~ "dubbo" ]];
then
work_dir=/data/ifengsite/java/dubbo/$appname
package=$workspace/target/dubbo.zip
else
work_dir=/data/ifengsite/java/$appname/webapps
package=$workspace/target/ROOT.war
fi #目标应用保留目录
releases_dir=/data/ifengsite/releases/$appname #建立软连接源目录
work2_dir=$releases_dir/$time ansible -i /home/sunyl/jenkins/$hosts $env -m copy -a "src=/home/sunyl/jenkins/openrc dest=/home/www/openrc" -u www
ansible -i /home/sunyl/jenkins/$hosts $env -m shell -a "mkdir -p $work2_dir" -u www if [[ "$appname" =~ "dubbo" ]];
then
cd $workspace/target/
rm -rf dubbo.zip
zip -r dubbo.zip *.jar lib resources
ansible -i /home/sunyl/jenkins/$hosts $env -m copy -a "src=/home/sunyl/jenkins/startup.sh dest=$work2_dir" -u www
ansible -i /home/sunyl/jenkins/$hosts $env -m copy -a "src=$package dest=$work2_dir" -u www
ansible -i /home/sunyl/jenkins/$hosts $env -m shell -a "cd $work2_dir && unzip dubbo.zip && rm -rf dubbo.zip" -u www
#ansible -i /home/sunyl/jenkins/$hosts $env -m unarchive -a "src=$package dest=$work2_dir " -u www
else
ansible -i /home/sunyl/jenkins/$hosts $env -m copy -a "src=$package dest=$work2_dir" -u www
fi ansible -i /home/sunyl/jenkins/$hosts $env -m shell -a "ln -sfn $work2_dir $work_dir" -u www
ansible -i /home/sunyl/jenkins/$hosts $env -m script -a "/home/sunyl/jenkins/restart_app.sh" -u www

# cat /home/sunyl/jenkins/restart_app.sh

#!/bin/sh
source /home/www/openrc
#kill tomcat pid
if [[ "$appname" =~ "dubbo" ]];
then
appname=`ls /data/ifengsite/java/dubbo/$appname|grep jar`
fi pidlist=`ps -ef|grep $appname|grep -v "grep"|grep -v $|awk '{print $2}'`
if [ "$pidlist" = "" ]
then
echo "no $appname pid alive!"
else
echo "$appname Id list :$pidlist"
kill - $pidlist
echo "KILL $pidlist:"
echo "service stop success"
fi source /home/www/openrc
echo "start $appname" if [[ "$appname" =~ "dubbo" ]];
then
cd /data/ifengsite/java/dubbo/$appname/
sh startup.sh
else
cd /data/ifengsite/java/$appname/bin
sh startup.sh
fi
# cat  /home/sunyl/jenkins/startup.sh   为dubbo的启动文件
#!/bin/bash
#
# Usage: start.sh [debug]
# cd `dirname $`
BIN_DIR=`pwd`
#cd ..
DEPLOY_DIR=`pwd`
APPNAME=`ls $DEPLOY_DIR | grep jar`
LOGS_DIR=log
STDOUT_FILE='log/console.log' if test -n "${JAVA_HOME}"; then
if test -z "${JAVA_EXE}"; then
JAVA_EXE=$JAVA_HOME/bin/java
fi
fi if test -z "${JAVA_EXE}"; then
JAVA_EXE=java
fi ${JAVA_EXE} -version >/dev/null >&
if [ $? -ne ]; then
echo "ERROR: Not Found java installed!"
exit
fi if [ -z "$LOGS_DIR" ]; then
LOGS_DIR=$DEPLOY_DIR/log
fi
if [ ! -d $LOGS_DIR ]; then
mkdir $LOGS_DIR
fi
if [ ! -d $LOGS_DIR ]; then
echo "ERROR: Please check LOGS_DIR=$LOGS_DIR is ok?"
exit
fi
STDOUT_FILE=$LOGS_DIR/console.log echo "Logs_dir: ${STDOUT_FILE}" JAVA_OPTS=" -Djava.awt.headless=true -Djava.net.preferIPv4Stack=true "
JAVA_DEBUG_OPTS=""
if [ "$1" = "debug" ]; then
JAVA_DEBUG_OPTS=" -Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,address=8000,server=y,suspend=n "
fi
JAVA_JMX_OPTS=""
if [ "$1" = "jmx" ]; then
JAVA_JMX_OPTS=" -Dcom.sun.management.jmxremote.port=1099 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false "
fi JAVA_MEM_OPTS=""
BITS=`${JAVA_EXE} -version >& | grep -i -bit`
if [ -n "$BITS" ]; then
JAVA_MEM_OPTS=" -server -Xmx2048m -Xms2048m -Xmn256m -XX:PermSize=128m -Xss256k -XX:+DisableExplicitGC -XX:+UseConcMarkSweepGC -XX:+CMSParallelRemarkEnabled -XX:+UseCMSCompactAtFullCollection -XX:LargePageSizeInBytes=128m -XX:+UseFastAccessorMethods -XX:+UseCMSInitiatingOccupancyOnly -XX:CMSInitiatingOccupancyFraction=70 "
else
JAVA_MEM_OPTS=" -server -Xms1024m -Xmx1024m -XX:PermSize=128m -XX:SurvivorRatio=2 -XX:+UseParallelGC "
fi echo "Starting the $SERVER_NAME ..."
nohup ${JAVA_EXE} $JAVA_SPRING_OPTS $JAVA_OPTS $JAVA_MEM_OPTS $JAVA_DEBUG_OPTS $JAVA_JMX_OPTS -jar $APPNAME > $STDOUT_FILE >& & echo "OK!"
在"构建设置"里开启设置接收邮件的邮箱时,服务器端需要启动 postfix 服务。
 
 Jenkins+Maven+Sonar系统持续集成环境部署以及配置
 
 --------------------------------------------------
以上为构建java项目,在构建PHP项目时,需修改
1、修改新建项目的类型
Jenkins+Maven+Sonar系统持续集成环境部署以及配置
 
2、修改构建项目时的设置
Jenkins+Maven+Sonar系统持续集成环境部署以及配置
 
# cat /home/sunyl/jenkins/php.sh
#!/bin/bash
#添加环境相关变量
source /home/sunyl/jenkins/openrc #使用的hosts文件
hosts=`echo $env|awk -F '-' '{print $1}'` #以时间命名目录名称
time=`date +"%Y%m%d-%H%M%S"` #目标应用启动路径
work_dir=/data/ifengsite/htdocs/$appname
package=$workspace/../$appname.tar #目标应用保留目录
releases_dir=/data/ifengsite/releases/$appname #建立软连接源目录
work2_dir=$releases_dir/$time ansible -i /home/sunyl/jenkins/$hosts $env -m shell -a "mkdir -p $work2_dir" -u www cd $workspace/../ && rm -rf $appname.tar
cd $workspace && tar cf $package *
ansible -i /home/sunyl/jenkins/$hosts $env -m copy -a "src=$package dest=$work2_dir" -u www
ansible -i /home/sunyl/jenkins/$hosts $env -m shell -a "cd $work2_dir && tar xf $appname.tar && rm -rf $appname.tar" -u www ansible -i /home/sunyl/jenkins/$hosts $env -m shell -a "ln -sfn $work2_dir $work_dir" -u www ansible -i /home/sunyl/jenkins/$hosts $env -m shell -a "/etc/init.d/php-fpm restart" -u www
 
 
 
上一篇:Event List


下一篇:Objective-C三种定时器CADisplayLink / NSTimer / GCD的使用