1.前言
上一章讲述了如何配置使用源代码管理工具SVN并使之与Apache集成,从而实现代码的变更可追溯,虽然在大多数团队里强调代码提交之前必须找团队中经验丰富的人来审核通过后方可提交,但这一条有时候不是所有时候都能得到满足,有没有依赖于机制而不是人来保证代码质量呢,我们知道计算机的缺点也是优点之一就是可以忠实执行指令。答案是有的,那就是SonarQube,其官方网址为:https://www.sonarqube.org/,目前最新版本为6.4。
SonarQube是一个开源平台,用于管理源代码的质量。Sonar 不只是一个质量数据报告工具,更是代码质量管理平台。支持的语言包括:Java、PHP、C#、C、Cobol、PL/SQL、Flex 等。主要特点:
代码覆盖:通过单元测试,将会显示哪行代码被选中
改善编码规则
搜寻编码规则:按照名字,插件,激活级别和类别进行查询
项目搜寻:按照项目的名字进行查询
对比数据:比较同一张表中的任何测量的趋势
本篇将讲述如何在CentOS7下配置使用SonarQube。
2.准备
2.1前置条件
安装SonarQube需要服务器上已经安装Java运行环境和数据库,SonarQube支持的数据库有Oracle、MySQL、PostgreSQL、SQL Server等,考虑这个系列下来我们已经在CentOS7上安装了Oracle JDK和MySQL5.17.8,因此我们在此基础上安装SonarQube,请大家回忆一下《开发人员学Linux(3):CentOS7中安装JDK8和Tomcat8》和《开发人员学Linux(6):CentOS7编译安装MySQL5.17.8多实例及主从复制》,对于SonarQube来说,Tomcat和MySQL主从复制是非必须的。
另外需要注意的是:
1.运行SonarQube需要较大的内存,官方建议至少2G以上,我将我的虚拟机调整为4核4G内存了;
2.运行SonarQube时官方要求如果是MySQL,要求数据库默认引擎为InnoDB而不是MyISAM,而在前面的章节中我们恰恰是配置的默认引擎为MyISAM,需要打开/usr/local/mysql-5.7.18/data/3306/my.cnf将[mysqld]节点下的“default-storage-engine=MyISAM”改为“default-storage-engine= InnoDB”。此外,还要求必须是UFT8编码,这个在之前的配置文件已经配置为UFT8,所以无需改动;
3.运行SonarQube6.4需要JDK8,我们之前安装的就是Oracke JDK8,因此可以忽略。
4.浏览SonarQube结果需要IE 11/Microsoft Edge或FireFox、Chrome的最新版本。
2.2软件准备
sonarqube-6.4.zip,下载地址:https://sonarsource.bintray.com/Distribution/sonarqube/sonarqube-6.4.zip
sonar-scanner-2.8.zip :https://sonarsource.bintray.com/Distribution/sonar-scanner-cli/sonar-scanner-2.8.zip
另外,如果需要使用SonarQube对C#进行代码质量分析,需要下载sonar-scanner-msbuild和MSBuild,其中要求MSBuild在V14.0以上,不想安装MSBuild的同学可以直接安装Microsoft Build Tools 2015。
sonar-scanner-msbuild-3.0.0.629.zip,下载地址:
https://github.com/SonarSource/sonar-scanner-msbuild/releases/download/3.0.0.629/sonar-scanner-msbuild-3.0.0.629.zip,说实在很难下载,可以去我的百度网盘下载,网址:https://pan.baidu.com/s/1pLblLMz
Microsoft Build Tools 2015,下载地址:
https://download.microsoft.com/download/E/E/D/EEDF18A8-4AED-4CE0-BEBE-70A83094FC5A/BuildTools_Full.exe
通过上面提供的软件已经满足在命令行下对代码进行分析的条件了,为了方便IDE开发人员,还提供了SonarLintwei,其网址为:http://www.sonarlint.org/,以下是其网站截图:
 wKiom1lsEbHyZIPLAAGmYgX3vq4800.png-wh_50 
3.安装
将下载的sonarqube-6.4.zip和sonar-scanner-2.8.zip上传到CentOS7的root目录下(也可通过wget下载,因为本人经常捣腾虚拟机,而有些放在国外网站上的文件下载速度极慢,所以习惯下载到本地存放)。
3.1安装SonarQube6.4
执行以下命令,将SonarQube安装到/usr/local/ sonarqube-6.4目录。
cd /root
unzip /root/sonarqube-6.4.zip –d /usr/local
启动SonarQube的文件在/usr/local/sonarqube-6.4/bin目录下,其结构如下:
wKioL1lsEcSyCbdiAADwdhGvFFE198.png-wh_50 

根据系统的不同进入不同目录下启动SonarQube,本人的CentOS7是64位的,因此在本人的虚拟机上启动SonarQube的脚本为:/usr/local/sonarqube-6.4/bin/linux-x86-64/sonar.sh。
启动:/usr/local/sonarqube-6.4/bin/linux-x86-64/sonar.sh start
重启:/usr/local/sonarqube-6.4/bin/linux-x86-64/sonar.sh restart
关闭:/usr/local/sonarqube-6.4/bin/linux-x86-64/sonar.sh stop
这是我们就可以从浏览器中打开SonarQube的结果页面了,网址是:http://192.168.60.198:9000(这个IP是我的虚拟机外部访问IP,在虚拟机内部可以通过http://localhost:9000访问,因在外部操作方便故本人习惯于是用外部地址访问,下同),默认管理员账户是:admin/admin。如下是启动后的界面:
wKiom1lsEdSh10JaAAEJoCrO78A630.png-wh_50 

3.2配置SonarQube
3.2.1修改配置文件sonar-runner.properties
由于SonarQube默认使用的H2数据库仅为演示使用,实际上登录系统之后就会看到提示,如下:
“bedded database should be used for evaluation purpose only

The embedded database will not scale, it will not support upgrading to newer versions of SonarQube, and there is no support for migrating your data out of it into a different database engine. ”
因此需要对SonarQube进行配置,这里以MySQL5.17.8为例:
通过vim /usr/local/sonarqube-6.4/conf/sonar.properties打开SonarQube的配置文件,作如下修改:
1.“sonar.jdbc.username=”改为:“sonar.jdbc.username=sonar”
2.“sonar.jdbc.password=”改为:“sonar.jdbc.password= sonar”
3.“sonar.jdbc.url=jdbc:mysql://localhost:3306/sonar?useUnicode=true&characterEncoding=utf8&rewriteBatchedStatements=true&useConfigs=maxPerformance&useSSL=false”去掉注释,即删除前面的“#”。
上面的用户名和密码是链接到SonarQube系统的所使用的数据库的账号信息,同时在数据库url中指定了SonarQue所使用的数据库为sonar,如果与实际环境中不一致需要相应修改。
3.2.2MySQL数据设置
首先启动数据库:
/usr/local/mysql-5.7.18/data/3306/mysql start
然后登录数据库:
/usr/local/mysql-5.7.18/bin/mysql -u root -p -S ./data/3306/mysql.sock
输入具有管理权限的账号和密码后,以此进行创建数据库、授权用户操作:
CREATE DATABASE sonar CHARACTER SET utf8 COLLATE utf8_general_ci;
GRANT ALL ON sonar.* TO 'sonar'@'%' IDENTIFIED BY 'sonar';  FLUSH PRIVILEGES;
经历过Java开发的开发人员肯定清楚,Java访问数据库需要JDBC驱动,在/usr/local/sonarqube-6.4/lib/jdbc目录下默认内置了h2/mssql/mysql/postgresql的JDBC驱动,如果是使用其它类型数据库作为SonarQube的数据,需要将对应的JDBC驱动下载并存放到指定目录,如Oracle的JDBC驱动存放位置:/usr/local/sonarqube-6.4/extensions/jdbc-driver/oracle。
至此已完成了SonarQube和MySQL数据库的配置工作,可以通过如下命令重启:
/usr/local/sonarqube-6.4/bin/linux-x86-64/sonar.sh restart
重启之后就不会出现要求更换数据库的提示了。配置JDBC之后第一次运行时需要较长时间,因为需要初始化数据库。
3.3安装插件
在完成SonarQube配置后,在虚拟机所在宿主机上通过http://192.168.60.198:9000并是用系统管理员账号登录后就可以安装插件了。进入安装插件的路径是:“Administration”-“System”-“Update Center”,如下图所示:
wKioL1lsEe2Bx7jEAAAgvWHNZiA757.png-wh_50 
默认已经安装了一些插件了,但是本人运行的时候提示我更新,于是本人就按照提示进行了更新,如果不习惯英文界面的朋友,可以安装中文语言包,如下图所示:
wKioL1lsEf7CdvfFAACkyHhm4GI079.png-wh_50 
注:由于未知原因有时候看不到这个插件,不过仍可以去https://github.com/SonarQubeCommunity/sonar-l10n-zh下载插件然后按照说明放到对应目录,最新插件下载地址为:https://github.com/SonarQubeCommunity/sonar-l10n-zh/releases/tag/sonar-l10n-zh-plugin-1.16,按照本文情况将其放到/usr/local/sonarqube-6.4/extensions/plugins目录下即可。
不过本人还是想尽量创造一些英文环境来巩固英语,毕竟大量的系统和框架都是英文的,连其说明文档也是英文的,因此在这里就不安装了。
3.4安装sonar-scanner-2.8
执行以下命令,将SonarQube安装到/usr/local/ sonar-scanner-2.8目录。
cd /root
unzip /root/sonar-scanner-2.8.zip –d /usr/local
启动sonar-scanner的文件在/usr/local/ sonar-scanner-2.8/bin目录下,为今后便于运行,可以将sonar-scanner的安装路径添加到/etc/profile中:
在其中增加:
export SONAR_SCANNER_HOME=/usr/local/sonar-scanner-2.8
并将sonar-scanner的bin文件夹添加到PATH变量,如下是本人机器上PATH的设置:
export PATH=$PATH:$JAVA_HOME/bin:/usr/local/apache-tomcat-8.5.15/bin:/usr/local/httpd-2.4.25/bin:/usr/local/svn/bin:/usr/local/php/bin:$SONAR_RUNNER_HOME/bin
然后执行source /etc/profile使配置生效。
3.5配置sonar-scanner-2.8
打开/usr/local/sonar-scanner-2.8/conf/sonar-scanner.properties根据实际安装情况做修改,主要改动如下:
“#sonar.host.url=http://localhost:9000”改为“sonar.host.url=http://localhost:9000”;(即去掉注释符号“#”)
“#sonar.sourceEncoding=UTF-8”改为“#sonar.sourceEncoding=UTF-8”;(即去掉注释符号“#”,如果程序源代码不是UTF-8则需要相应修改,建议程序源代码文件编码使用UTF-8)
“#sonar.jdbc.username=sonar”改为“sonar.jdbc.username=sonar”; (即去掉注释符号“#”)
“#sonar.jdbc.password=sonar”改为“sonar.jdbc.password=sonar”;(即去掉注释符号“#”)
“#sonar.jdbc.url=jdbc:mysql://localhost:3306/sonar?useUnicode=true&characterEncoding=utf8”改为“sonar.jdbc.url=jdbc:mysql://localhost:3306/sonar?useUnicode=true&characterEncoding=utf8”;(即去掉注释符号“#”)
上面配置的是SonarQube数据库的信息,对代码进行扫描之后需要将结果保存到数据库;
至此,sonar-scanner已具备对代码进行分析的条件了。
4.使用sonar-scanner
下面的截图是本人当前项目分析的几个报告:
wKioL1lsEiridwXMAAB52KUXez8137.png-wh_50 
4.1使用sonar-scanner分析代码
sonar-scanner是SonarQube默认推荐的代码分析工具,使用起来也相对简单,分以下几个步骤:
1.在要测试的项目中创建一个sonar-project.properties;
2.在sonar-project.properties文件中配置项目的相关信息,如项目的名称、版本、编程所使用的语言、程序文件所使用的编码等;
在这里就一个简单例子为例:
将本人用Java写的一个本人早年练手的Java EE项目simple-web来进行分析,将其上传到服务器/tmp/目录下;
在/tmp/ simple-web /目录下创建sonar-project.properties文件,文件内容如下:

# must be unique in a given SonarQube instance
sonar.projectKey=my:simple-web
# this is the name displayed in the SonarQube UI
sonar.projectName=simple-web
sonar.projectVersion=1.0
sonar.language=java
 
# Path is relative to the sonar-project.properties file. Replace "\" by "/" on Windows.
# Since SonarQube 4.2, this property is optional if sonar.modules is set.
# If not set, SonarQube starts looking for source code from the directory containing
# the sonar-project.properties file.
sonar.sources=src
 
# Encoding of the source code. Default is default system encoding
sonar.sourceEncoding=UTF-8


其中:
sonar.projectKey必须在整个SonarQube中全局唯一;
sonar.projectName用于在网页中显示的项目名称;
sonar.projectVersion用于标识源代码版本;
sonar.language用于标识项目源代码所使用的开发语言;
sonar.sources用于指定源代码在整个文件中的起始路径;在Java Maven项目中默认都会有个src目录存放源代码,因此这里的值为“src”,当然如果不存在类似目录结构,也可以用“.”标识当前路径。
sonar.sourceEncoding:项目中源代码文件的编码,用Visual Studio创建的项目默认都是UTF-8编码,用Eclipse作为IDE的需要在IDE中进行设置,当然如果难以转码也可以用实际编码;
3.由于已经将sonar-scanner的路径洗洗添加到CentOS7的PATH环境变量中,所以可以直接sonar-runner来运行代码分析了,如果没有添加环境变量也是可以执行分析的,命令如下:

cd /tmp/ simple-web /
/usr/local/sonar-scanner-2.8/bin/sonar-scanner


如果不出错的话,会看到如下提示:
wKioL1lsElCyPqz5AABp29bqHnk668.png-wh_50 
这时,就可以浏览器中打开SonarQube网站来观看结果了,这是simple-web的代码分析结果:
 wKiom1lsElygnsrXAACgmIgNhno401.png-wh_50
可以看到这个项目被SonarQube分析后的总体情况:项目总代码行数,单元测试覆盖率,bug数,可能会有问题的代码,代码编写风格存在问题的总数、重复的代码数。
在上述网页点击相应数据指标会看到比较明晰的数据来源。
当然,上述的分析结果只是建议,就像有人去小卖部买矿泉水被收5元,买的人跟老板论理:“这上面都说建议零售价4元的。”老板说:“我不接受建议”。我查看一下所列出的问题,比如catch了exception没有记录到日志是会被看做vulnerability。
当然,有时候你可以自信没有问题,但是被同一个组的其他人看到每次要解释又很麻烦,那么可以在原有规则上进行修改即可。
4.2分析C#代码
对于使用Visual Studio创建的.net项目是需要使用MSBuild.exe来进行分析的,因此无法在Linux系统上进行分析,可以采用sonar-scanner-msbuild-2.2.0.24.zip在命令行下分析或者安装SonarLint插件在Visual Studio中进行分析。这里演示一下如何使用sonar-scanner-msbuild来进行分析。
4.2.1sonar-scanner-msbuild安装配置
首先,将sonar-scanner-msbuild-3.0.0.629.zip下载到本地并进行解压(前文已提供下载地址),本人将它解压到C:\ sonar-scanner-msbuild-3.0.0.629,如下图所示:

wKioL1lsEm7yzlK6AAEeGtnm2LY263.png-wh_50 
编辑C:\ sonar-scanner-msbuild-3.0.0.629目录下的SonarQube.Analysis.xml文件,最终结果如下:

<?xml version="1.0" encoding="utf-8" ?><!--  This file defines properties which would be understood by the SonarQube Scanner for MSBuild, if not overridden (see below)  By default the MSBuild.SonarQube.Scanner.exe picks-up a file named SonarQube.Analysis.xml in the folder it  is located (if it exists). It is possible to use another properties file by using the /s:filePath.xml flag   The overriding strategy of property values is the following:  - A project-specific property defined in the MSBuild *.*proj file (corresponding to a SonarQube module) can override:  - A property defined in the command line (/d:propertyName=value) has which can override:  - A property defined in the SonarQube.Analysis.xml configuration file [this file] which can override:  - A property defined in the SonarQube User Interface at project level which can override:  - A property defined in the SonarQube User Interface at global level which can't override anything.   Note that the following properties cannot be set through an MSBuild project file or an SonarQube.Analysis.xml file:  sonar.projectName, sonar.projectKey, sonar.projectVersion  The following flags need to be used to set their value: /n:[SonarQube Project Name] /k:[SonarQube Project Key] /v:[SonarQube Project Version]
--><SonarQubeAnalysisProperties  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://www.sonarsource.com/msbuild/integration/2015/1">
  <Property Name="sonar.host.url">http://192.168.60.198:9000</Property>  <!--  <Property Name="sonar.login"></Property>  <Property Name="sonar.password"></Property>  -->  <Property Name="sonar.login">admin</Property>  <Property Name="sonar.password">admin</Property>    <!-- Required only for versions of SonarQube prior to 5.2 -->  <!--  <Property Name="sonar.jdbc.url">jdbc:jtds:sqlserver://mySqlServer/sonar;instance=SQLEXPRESS;SelectMethod=Cursor</Property>


由于XML实体中不允许出现"&","<",">"等特殊字符,否则XML语法检查时将出错,如果编写的XML文件必须包含这些字符,则必须分别写成"&amp;","&lt;","&gt;"再写入文件中。
  <Property Name="sonar.jdbc.url">jdbc:mysql://192.168.60.198:3306/sonar?useUnicode=true&characterEncoding=utf8&rewriteBatchedStatements=true&useConfigs=maxPerformance&useSSL=false</Property>
  -->
  <Property Name="sonar.jdbc.url">jdbc:mysql://192.168.60.198:3306/sonar?useUnicode=true&amp;characterEncoding=utf8&amp;rewriteBatchedStatements=true&amp;useConfigs=maxPerformance&amp;useSSL=false</Property>
  <Property Name="sonar.jdbc.username">sonar</Property>
  <Property Name="sonar.jdbc.password">sonar</Property>

</SonarQubeAnalysisProperties>
说明:
1.因为在宿主机上需要通过192.168.60.198来连接部署了SonarQube的虚拟机,因此需要将原来的localhost改为192.168.60.198;
2.因为在xml中"&","<",">"等特殊字符需要转义,所以需要将sonar.jdbc.url中url部分含有“&”替换为“&amp;”。
3.MSBuild.exe需要14.0以上版本,如果本地安装了Visual Studio 2015及以上版本则已经满足条件,否则需要安装Microsoft Build Tools 2015,Microsoft Build Tools 2015下载链接前文已经给出,下载到本地然后安装。
4.2.2使用sonar-scanner-msbuild分析代码
在命令下进入要到分析的项目的目录,如本人要分析的项目的目录为:C:\ITManageSolution,然后找到MSBuild.exe的路径,在本人机器上路径为:C:\Program Files (x86)\MSBuild\14.0\Bin\MSBuild.exe
首先执行如下命令:

"C:\sonar-scanner-msbuild-3.0.0.629\MSBuild.SonarQube.Runner.exe" begin /key:"my:ITManageSolution" /name:"ITManageSolution" /version:"0.9"


上述命令中的/key、/name、 /version是和前面提及的Java类型项目的代码分析配置文件sonar-project.properties中的sonar.projectKey、sonar.projectName、sonar.projectVersion对应的。

执行结果如下图所示:
wKioL1lsErLjLj-iAADBlNDpgPw967.png-wh_50 
接着执行:

"C:\Program Files (x86)\MSBuild\14.0\Bin\MSBuild.exe" ITManageClient.sln /t:Rebuild


注:ITManageClient.sln是解决方案名字,如果该目录下只存在一个解决方案文件则可省略。
效果如下图所示:
wKiom1lsEsaCwwDTAADfZTJnJZA032.png-wh_50 
最后执行:

"C:\ sonar-scanner-msbuild-3.0.0.629 \MSBuild.SonarQube.Runner.exe" end


执行结果如下图所示:
wKioL1lsEt6Q34NCAADmjAw2Q6Y839.png-wh_50 
至此,已完成对ITManageSolution这个C#项目的代码分析,在http://192.168.60.198:9000中可以看到分析报告。报告查看方法这里就不再赘述了。
需要注意的是如果在C:\ITManageSolution目录下存在多个解决方案文件,需要针对每个解决方案运行一次上述过程。这也很好理解,毕竟使用Visual Studio也是需要打开两次分别编译的,这样一来在SonarQube中也是会显示为多个项目。
4.3与持续集成工具集成来分析代码
在SonarQube中提及了多种代码分析方式,包含:
SonarQube Scanner for MSBuild: 分析.NET项目代码;
SonarQube Scanner for Maven: 在Maven项目中执行分析;
SonarQube Scanner for Gradle: 执行Gradle分析(抱歉,这种方式没试过)
SonarQube Scanner for Ant: 在使用了Ant的项目中进行代码分析;
SonarQube Scanner For Jenkins: 在Jenkins中执行代码分析
SonarQube Scanner:以命令行形式执行代码分析
在本篇中讲述了SonarQube Scanner和SonarQube Scanner for MSBuild两种方式,SonarQube Scanner For Jenkins将会在下一篇讲述Jenkins的时候讲,其它方式需要大家去尝试了。
5.总结
SonarQube是一个通过插件来支持对多种开发语言编写的项目进行分析的开源代码质量管理平台,在本篇讲述了如何在CentOS7上进行安装和配置及使用SonarQube,在SonarQube支持的六种代码分析方式中,以SonarQube Scanner和SonarQube Scanner for MSBuild为例分别讲述了对Java项目和C#项目进行代码质量分析。由于SonarQube涉及的知识点非常多,在本篇并没有一一展开,更多的知识点需要大家去自行学习掌握了。


声明:本文首发于本人个人微信订阅号:zhoujinqiaoIT,其后会同时在本人的CSDN、51CTO及oschina三处博客发布,本人会负责在此四处答疑。