zoukankan      html  css  js  c++  java
  • 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,此时被修改用户的密码变为 "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"
     
     
    安装完成后,在结合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分就是不稳定的。
     
     
    二、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: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

    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-8

    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-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

    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
     
     
     
    2、系统管理---系统设置
     
     
    此处的token值取自Sonar的web界面的"我的账号----安全"
     
    3、在新建项目时或修改已有项目的配置, 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项目时,需修改
    1、修改新建项目的类型
     
    2、修改构建项目时的设置
     
    # 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
     
     
     
  • 相关阅读:
    [LeetCode] 493. Reverse Pairs 翻转对
    [LeetCode] Super Washing Machines 超级洗衣机
    [LeetCode] Perfect Number 完美数字
    [LeetCode] 483. Smallest Good Base 最小的好基数
    [LeetCode] Sliding Window Median 滑动窗口中位数
    [LeetCode] Diameter of Binary Tree 二叉树的直径
    [LeetCode] 01 Matrix 零一矩阵
    [LeetCode] Convert BST to Greater Tree 将二叉搜索树BST转为较大树
    [LeetCode] Reverse String II 翻转字符串之二
    [LeetCode] Minimum Time Difference 最短时间差
  • 原文地址:https://www.cnblogs.com/wjoyxt/p/5702406.html
Copyright © 2011-2022 走看看