Jenkins+Maven+Sonar系统持续集成环境部署以及配置
忘记密码时的处理办法:
打开忘记密码的用户文件夹,默认 /var/lib/jenkins/users ,里面就一个文件config.xml。打开config.xml,找到<passwordHash>项,
把其中的hash值先改成 "#jbcrypt:$2a$10$DdaWzN64JgUtLdvxWIflcuQu2fgrrMSAMabF5TSrGK5nXitqK9ZMS"
保存并重启jenkins,此时被修改用户的密码变为 "111111",进入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"
构建的状态:下图中分级符号概述了一个Job新近一次构建会产生的四种可能的状态:
Successful:完成构建,且被认为是稳定的。
Unstable:完成构建,但被认为不稳定。
Failed:构建失败。
Disabled:构建已禁用。
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 重启服务
- 安装中文补丁包可以通过访问http:\\localhost:9000,打开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语言分析插件, "配置--系统--更新中心"
sonar.host.url=http://10.0.30.180:9000 sonar.sourceEncoding=UTF-8
3、配置环境变量/etc/profile,此处一并加上SONARQUBE_HOME的变量
export SONARQUBE_HOME=/usr/local/sonarqube
export SONAR_RUNNER_HOME=/usr/local/sonar-scanner/
sonar.projectKey=prepare-agent sonar.projectName=prepare-agent sonar.projectVersion=1.0 sonar.sources=. sonar.language=java sonar.sourceEncoding=UTF-8
工程的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
Sonar官方已经提供了非常全的代码样例便于新手入门用。
下载地址:https://github.com/SonarSource/sonar-examples/archive/master.zip
下载后使用unzip解压。进入执行sonar-scanner命令即可。执行完成后查看SonarQube的Web界面,正常的话应该就可以看到分析的结果啦。
Build whenever a SNAPSHOT dependency is built:当此项目所依赖的项目在jenkins中被构建时触发开始进行构建
Build after other projects are built:在某个项目被构建后,构建此项目
Build periodically:按照指定的时间间隔进行自动构建,不管代码有没有变更。
Poll SCM:按照指定的时间间隔对SCM进行检测,如果代码库有更新则拉取后进行构建。
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(预发布环境)
#!/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 $0|awk '{print $2}'` if [ "$pidlist" = "" ] then echo "no $appname pid alive!" else echo "$appname Id list :$pidlist" kill -9 $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
#!/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