Jenkins+Maven+Sonar系統持續集成環境部署以及配置

想要「不自動構建下級項目」,須要在下級項目中配置php

Build whenever a SNAPSHOT dependency is built    把這個選項取消掉就能夠了java

--------------------------------------------------------------------------------------------------------------mysql

更改Jenkins啓動的用戶時的步驟:linux

一、# vim /etc/sysconfig/jenkinsgit

JENKINS_USER="wjoyxt"github

二、# chown -R wjoyxt.wjoyxt /var/log/jenkins /var/lib/jenkins /var/cache/jenkins  這三個目錄web

--------------------------------------------------------------------------------------------------------------sql

忘記密碼時的處理辦法:shell

打開忘記密碼的用戶文件夾,默認 /var/lib/jenkins/users ,裏面就一個文件config.xml。打開config.xml,找到<passwordHash>項,數據庫

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

保存並重啓jenkins,此時被修改用戶的密碼變爲 "111111",進入jenkins後再經過用戶管理從新設置本身的密碼便可。

 

另:Jenkins中複製job的方法:複製/var/lib/jenkins/jobs中的項目目錄,並改爲要新建的項目名稱便可。

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

1、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 PluginMaven Integration plugin這兩個插件。
或者從http://ftp.tsukuba.wide.ad.jp/software/jenkins/plugins/直接下載相應的hpi文件,而後進入到"插件管理--高級--上傳插件" 進行手動導入安裝。
 

構建的狀態:下圖中分級符號概述了一個Job新近一次構建會產生的四種可能的狀態: 

Successful:完成構建,且被認爲是穩定的。

Unstable:完成構建,但被認爲不穩定。

Failed:構建失敗。

Disabled:構建已禁用。

 
 構建的穩定性:
Jenkins會基於一些後處理器任務爲構建發佈一個穩健指數 (從0-100 ),這些任務通常以插件的方式實現。它們可能包括單元測試(JUnit)、覆蓋率(Cobertura )和靜態代碼分析
(FindBugs)。分數越高,代表構建越穩定。下圖中分級符號概述了穩定性的評分範圍。任何構建做業的狀態(總分100)低於80分就是不穩定的。
 
 
2、Sonarqube安裝配置
 
一、從Sonar官網 http://www.sonarqube.org/downloads/ 下載,解壓下載好的zip包
二、配置 /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

三、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;

四、啓動Sonar服務,默認9000端口

目錄切換至sonar的<install_directory>/bin/linux-x86-64/目錄,啓動服務
#./sonar.sh start   啓動服務
#./sonar.sh stop    中止服務
#./sonar.sh restart 重啓服務

五、中文語言包安裝的兩種方式
  •   安裝中文補丁包能夠經過訪問http:\\localhost:9000,用戶名和密碼都是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

六、安裝須要進行代碼分析的Java、PHP語言分析插件, "配置--系統--更新中心"

3、SonarQube Scanners安裝配置
 
官方文檔也介紹的挺清楚:http://docs.sonarqube.org/display/SCAN/Analyzing+with+SonarQube+Scanner 
 
一、一樣從http://www.sonarqube.org/downloads/進行下載後解壓到/usr/local/
二、修改/usr/local/sonar-scanner/conf/sonar-scanner.properties
sonar.host.url=http://10.0.30.180:9000
sonar.sourceEncoding=UTF-8

三、配置環境變量/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
 
4、以命令行方式使用SonarQube Runner對源碼進行分析
 
參考官方資料 http://docs.sonarqube.org/display/SCAN/Analyzing+with+SonarQube+Scanner
一、在項目源碼的根目錄下建立 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-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界面,正常的話應該就能夠看到分析的結果啦。

例如進入解壓後的 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打包也是一樣的道理。
 
5、在Jenkins中進行Sonar集成時的相關設置
 
一、系統管理---Global Tool Configuration
 
 
 
二、系統管理---系統設置
 
 
此處的token值取自Sonar的web界面的"個人帳號----安全"
 
三、在新建項目時或修改已有項目的配置, Repository URL根據本身要構建的項目的不一樣svn地址而進行修改。
 
構建觸發器:
 
 
 

Build whenever a SNAPSHOT dependency is built:當此項目所依賴的項目在jenkins中被構建時觸發開始進行構建
Build after other projects are built:在某個項目被構建後,構建此項目 
Build periodically:按照指定的時間間隔進行自動構建,無論代碼有沒有變動。 
Poll SCM:按照指定的時間間隔對SCM進行檢測,若是代碼庫有更新則拉取後進行構建。

 
 
 
這一步呢,多說兩句。我這邊採用的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 $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

 

# cat  /home/sunyl/jenkins/startup.sh   爲dubbo的啓動文件
#!/bin/bash
#
# Usage: start.sh [debug]
#


cd `dirname $0`
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 2>&1
if [ $? -ne 0 ]; then
  echo "ERROR: Not Found java installed!"
  exit 1
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 1
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 2>&1 | grep -i 64-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 2>&1 & 


echo "OK!"
View Code

  

在"構建設置"裏開啓設置接收郵件的郵箱時,服務器端須要啓動 postfix 服務。
 
 
 
 --------------------------------------------------
以上爲構建java項目,在構建PHP項目時,需修改
一、修改新建項目的類型
 
二、修改構建項目時的設置
 
# 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
相關文章
相關標籤/搜索