13. Sonarqube实现代码扫描

1 代码质量测试

官方网站:http://www.sonarqube.org/

SonarQube 是一个用于代码质量管理的开放平台,通过插件机制,SonarQube可以
集成不同的测试工具,代码分析工具,以及持续集成工具,例如 Hudson/Jenkins 等

下载地址:https://www.sonarqube.org/downloads/

七个维度检测代码质量:

复杂度分布:代码复杂度过高将难以理解
重复代码:程序中包含大量复制、粘贴的代码而导致代码臃肿,sonar 可以展示源码中重复严重的地方
单元测试统计:统计并展示单元测试覆盖率,开发或测试可以清楚测试代码的覆盖情况
代码规则检查:检查代码是否符合规范
注释率:若代码注释过少,特别是人员变动后,其他人接手比较难接手;若过多,又不利于阅读
潜在的 Bug:检测潜在的 bug
结构与设计:找出循环,展示包与包、类与类之间的依赖、检查程序之间耦合度

2 Sonarqube

2.1 Sonarqube架构

图片.png
Sonarqube代码检测功能由Sonarqube服务器端提供
SonarScanner需要在执行代码扫描的服务器安装, 用于扫描代码, 并且上传到Sonarqube Server端

2.2 Sonarqube部署环境

10.0.0.139  Sonarqube Server 4G 2c  v7.9.6
10.0.0.149 PGSQL 4G 2c
Jenkins master服务器负责代码扫描, 需要安装Sonar Scanner

2.3 Sonarqube Server安装

2.3.1 包下载

https://www.sonarqube.org/downloads/

root@sonarserver:~# ls
sonarqube-7.9.6.zip

2.3.2 配置环境依赖

  • 内核参数要求
root@sonarserver:~# vim /etc/sysctl.conf

vm.max_map_count=262144
fs.file-max=65536 
root@sonarserver:~# sysctl -p
vm.max_map_count = 262144
fs.file-max = 65536
  • 文件描述符限制
root@sonarserver:~# vim /etc/security/limits.conf
sonarqube - nofile 65536
sonarqube - nproc 65536  

2.3.3 创建sonarqube用户

Sonarqube Server不能用root账户启动

root@sonarserver:~# useradd -m -r -s /bin/bash sonarqube

2.3.4 安装jdk-11

Sonarqube Server只支持jdk-11, 而SonarScanner支持jdk8和jdk11

root@sonarserver:~# apt -y install openjdk-11-jdk
root@sonarserver:~# reboot 

2.3.5 安装PGSQL

Sonarqube7.x开始支持PGSQL, 支持v10和v9.3-v9.6, 字符集必须是UTF-8

root@pgsql:~# apt-cache madison postgresql
postgresql | 10+190ubuntu0.1 | http://mirrors.aliyun.com/ubuntu bionic-security/main amd64 Packages
postgresql | 10+190ubuntu0.1 | http://mirrors.aliyun.com/ubuntu bionic-security/main i386 Packages
postgresql | 10+190ubuntu0.1 | http://mirrors.aliyun.com/ubuntu bionic-updates/main amd64 Packages
postgresql | 10+190ubuntu0.1 | http://mirrors.aliyun.com/ubuntu bionic-updates/main i386 Packages
postgresql |     10+190 | http://mirrors.aliyun.com/ubuntu bionic/main amd64 Packages
postgresql |     10+190 | http://mirrors.aliyun.com/ubuntu bionic/main i386 Packages
postgresql-common |        190 | http://mirrors.aliyun.com/ubuntu bionic/main Sources
postgresql-common | 190ubuntu0.1 | http://mirrors.aliyun.com/ubuntu bionic-security/main Sources
postgresql-common | 190ubuntu0.1 | http://mirrors.aliyun.com/ubuntu bionic-updates/main Sources
root@pgsql:~# apt install postgresql -y

切换到 postgres 操作,PostgresSQL 安装后会自动创建 postgres 用户且没有密码. 数据库的创建必须使用postgres账户操作

root@pgsql:~# su -  postgres
postgres@pgsql:~$ psql -U postgres
psql (10.17 (Ubuntu 10.17-0ubuntu0.18.04.1))
Type "help" for help.

postgres=#  CREATE DATABASE sonar;
CREATE DATABASE
postgres=# CREATE USER sonar WITH ENCRYPTED PASSWORD '123456';
CREATE ROLE
postgres=# GRANT ALL PRIVILEGES ON DATABASE sonar TO sonar;
GRANT
postgres=#  ALTER DATABASE sonar OWNER TO sonar;
ALTER DATABASE

修改监听地址, 使用root账号配置

root@pgsql:~# vim /etc/postgresql/10/main/postgresql.conf
listen_addresses = '*'  # 修改第59行

开启远程访问

root@pgsql:~# vim /etc/postgresql/10/main/pg_hba.conf
host    all             all             10.0.0.0/24            md5 # 修改第92行, 允许某个网段或者某台主机访问

重启服务

root@pgsql:~# systemctl restart postgresql
root@pgsql:~# ss -ntl
State                 Recv-Q                 Send-Q                                  Local Address:Port                                   Peer Address:Port                 
LISTEN                0                      128                                           0.0.0.0:5432          # 监听在0.0.0.0                              0.0.0.0:*                    
LISTEN                0                      128                                     127.0.0.53%lo:53                                          0.0.0.0:*                    
LISTEN                0                      128                                           0.0.0.0:22                                          0.0.0.0:*                    
LISTEN                0                      128                                              [::]:5432                                           [::]:*                    
LISTEN                0                      128                                              [::]:22                                             [::]:* 

2.3.6 安装Sonarqube Server

root@sonarserver:~# mkdir /apps
root@sonarserver:~# ls
sonarqube-7.9.6.zip
root@sonarserver:~# unzip sonarqube-7.9.6.zip  -d /apps
root@sonarserver:~# cd /apps
root@sonarserver:/apps# ll
total 12
drwxr-xr-x  3 root root 4096 Jul  6 22:33 ./
drwxr-xr-x 25 root root 4096 Jul  6 22:32 ../
drwxr-xr-x 11 root root 4096 Mar  1 09:21 sonarqube-7.9.6/
root@sonarserver:/apps# ln -sv sonarqube-7.9.6/ sonarqube
'sonarqube' -> 'sonarqube-7.9.6/'
root@sonarserver:/apps# chown -R sonarqube.sonarqube /apps/sonarqube
root@sonarserver:/apps# chown -R sonarqube.sonarqube /apps/sonarqube/
root@sonarserver:/apps# ll /apps
total 12
drwxr-xr-x  3 root      root      4096 Jul  6 22:34 ./
drwxr-xr-x 25 root      root      4096 Jul  6 22:32 ../
lrwxrwxrwx  1 sonarqube sonarqube   16 Jul  6 22:34 sonarqube -> sonarqube-7.9.6//
drwxr-xr-x 11 sonarqube sonarqube 4096 Mar  1 09:21 sonarqube-7.9.6/
sonarqube@sonarserver:/apps/sonarqube$ vim conf/sonar.properties 
sonarqube@sonarserver:/apps/sonarqube$ grep -E '^[a-zA-Z]' conf/sonar.properties 
sonar.jdbc.username=sonar  # 数据库账号
sonar.jdbc.password=123456 # 密码
sonar.jdbc.url=jdbc:postgresql://10.0.0.149/sonar # 数据库地址

2.3.7 启动服务

使用sonarqube普通账户启动, 如果用root账户启动, 那么ES服务无法启动, 间接造成Sonarqube无法启动

sonarqube@sonarserver:/apps/sonarqube$ ./bin/linux-x86-64/sonar.sh start
Starting SonarQube...
Started SonarQube.
sonarqube@sonarserver:/apps/sonarqube$ tail logs/*.log

2021.07.06 22:41:32 INFO  app[][o.s.a.SchedulerImpl] Process[ce] is up
2021.07.06 22:41:32 INFO  app[][o.s.a.SchedulerImpl] SonarQube is up

2.3.8 访问sonarqube

账号:admin
密码:admin

图片.png

2.3.9 使用官方提供的Service文件启动sonarqube

  • 先停止服务
sonarqube@sonarserver:~$ /apps/sonarqube/bin/linux-x86-64/sonar.sh stop
Gracefully stopping SonarQube...
Stopped SonarQube.
  • 使用root账号, 创建Service文件
root@sonarserver:~# vim /etc/systemd/system/sonarqube.service 

[Unit]                                                                                                                                                                      
Description=SonarQube service
After=syslog.target network.target

[Service]
Type=simple
User=sonarqube
Group=sonarqube
PermissionsStartOnly=true
ExecStart=/usr/bin/nohup /usr/bin/java -Xms1024m -Xmx1024m -Djava.net.preferIPv4Stack=true -jar /apps/sonarqube/lib/sonar-application-7.9.6.jar
StandardOutput=syslog
LimitNOFILE=131072
LimitNPROC=8192
TimeoutStartSec=5
Restart=always
SuccessExitStatus=143

[Install]
WantedBy=multi-user.target

root@sonarserver:~# systemctl daemon-reload
root@sonarserver:~# systemctl restart sonarqube
root@sonarserver:~# systemctl enable --now sonarqube
Created symlink /etc/systemd/system/multi-user.target.wants/sonarqube.service → /etc/systemd/system/sonarqube.service.
root@sonarserver:/apps/sonarqube# ss -ntl
State                Recv-Q                Send-Q                                     Local Address:Port                               Peer Address:Port                
LISTEN               0                     128                                        127.0.0.53%lo:53                                      0.0.0.0:*                   
LISTEN               0                     128                                              0.0.0.0:22                                      0.0.0.0:*                   
LISTEN               0                     128                                                 [::]:22                                         [::]:*                   
LISTEN               0                     25                                                     *:9000                                          *:*                   
LISTEN               0                     128                                   [::ffff:127.0.0.1]:9001                                          *:*   

2.3.10 安装中文插件

图片.png

插件保存目录

root@sonarserver:~# ll /apps/sonarqube/extensions/plugins/
total 87836
drwxr-xr-x 2 sonarqube sonarqube     4096 Mar  1 09:10 ./
drwxr-xr-x 5 sonarqube sonarqube     4096 Jul  6 22:41 ../
-rw-r--r-- 1 sonarqube sonarqube      224 Mar  1 09:10 README.txt
-rw-r--r-- 1 sonarqube sonarqube   287504 Mar  1 09:10 sonar-auth-github-plugin-1.5.0.870.jar
-rw-r--r-- 1 sonarqube sonarqube  3312399 Mar  1 09:10 sonar-auth-saml-plugin-1.2.0.682.jar
-rw-r--r-- 1 sonarqube sonarqube  4094975 Mar  1 09:10 sonar-csharp-plugin-7.15.0.8572.jar
-rw-r--r-- 1 sonarqube sonarqube  7015434 Mar  1 09:10 sonar-css-plugin-1.1.1.1010.jar
-rw-r--r-- 1 sonarqube sonarqube  1544789 Mar  1 09:10 sonar-flex-plugin-2.5.1.1831.jar
-rw-r--r-- 1 sonarqube sonarqube  3903342 Mar  1 09:10 sonar-go-plugin-1.1.1.2000.jar
-rw-r--r-- 1 sonarqube sonarqube  1727846 Mar  1 09:10 sonar-html-plugin-3.1.0.1615.jar
-rw-r--r-- 1 sonarqube sonarqube    15098 Mar  1 09:10 sonar-jacoco-plugin-1.0.2.475.jar
-rw-r--r-- 1 sonarqube sonarqube  8302745 Mar  1 09:10 sonar-java-plugin-5.13.1.18282.jar
-rw-r--r-- 1 sonarqube sonarqube  6866969 Mar  1 09:10 sonar-javascript-plugin-5.2.1.7778.jar
-rw-r--r-- 1 sonarqube sonarqube  7595999 Mar  1 09:10 sonar-kotlin-plugin-1.5.0.315.jar
-rw-r--r-- 1 sonarqube sonarqube   300503 Mar  1 09:10 sonar-ldap-plugin-2.2.0.608.jar
-rw-r--r-- 1 sonarqube sonarqube  5105268 Mar  1 09:10 sonar-php-plugin-3.2.0.4868.jar
-rw-r--r-- 1 sonarqube sonarqube  2752167 Mar  1 09:10 sonar-python-plugin-1.14.1.3143.jar
-rw-r--r-- 1 sonarqube sonarqube 10036210 Mar  1 09:10 sonar-ruby-plugin-1.5.0.315.jar
-rw-r--r-- 1 sonarqube sonarqube  9202024 Mar  1 09:10 sonar-scala-plugin-1.5.0.315.jar
-rw-r--r-- 1 sonarqube sonarqube  2538373 Mar  1 09:10 sonar-scm-git-plugin-1.12.1.2064.jar
-rw-r--r-- 1 sonarqube sonarqube  7229293 Mar  1 09:10 sonar-scm-svn-plugin-1.9.0.1295.jar
-rw-r--r-- 1 sonarqube sonarqube  2239156 Mar  1 09:10 sonar-typescript-plugin-1.9.0.3766.jar
-rw-r--r-- 1 sonarqube sonarqube  3580236 Mar  1 09:10 sonar-vbnet-plugin-7.15.0.8572.jar
-rw-r--r-- 1 sonarqube sonarqube  2242738 Mar  1 09:10 sonar-xml-plugin-2.0.1.2020.jar

看到install pending后, 要点击重启服务器, 以便开始安装

图片.png
图片.png
图片.png

2.4 Sonar-Scanner安装

Sonar-Scanner可以部署在单独的服务器, 也可以部署在Jenkins服务器, Jenkins把代码拉取到本地后, 直接通过Sonar-Scanner扫描

下载地址:https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/
官方文档:https://docs.sonarqube.org/latest/analysis/scan/sonarscanner/

root@jenkins:/opt# ls
sonar-scanner-cli-4.5.0.2216-linux.zip
root@jenkins:~# unzip sonar-scanner-cli-4.5.0.2216-linux.zip -d /apps/
root@jenkins:/apps# ln -sv sonar-scanner-4.5.0.2216-linux/ sonar-scanner
root@jenkins:/apps# cd sonar-scanner
root@jenkins:/apps/sonar-scanner# vim conf/sonar-scanner.properties
#----- Default SonarQube server
sonar.host.url=http://10.0.0.139:9000

#----- Default source code encoding
sonar.sourceEncoding=UTF-8  

2.5 利用官方提供的bug代码进行扫描测试

https://github.com/SonarSource/sonar-scanning-examples

将示例代码传到Jenkins服务器

root@jenkins:~# cd /opt
root@jenkins:/opt# ls
sonar-scanning-examples-master.zip
root@jenkins:/opt# unzip sonar-scanning-examples-master.zip
root@jenkins:/opt/sonar-scanning-examples-master/sonarqube-scanner# cd src/ # 代码示例存放位置
root@jenkins:/opt/sonar-scanning-examples-master/sonarqube-scanner/src# ll
total 80
drwxr-xr-x 20 root root 4096 Jun 24 16:41 ./
drwxr-xr-x  5 root root 4096 Jun 24 16:41 ../
drwxr-xr-x  2 root root 4096 Jun 24 16:41 abap/
drwxr-xr-x  2 root root 4096 Jun 24 16:41 cobol/
drwxr-xr-x  2 root root 4096 Jun 24 16:41 directory/
drwxr-xr-x  2 root root 4096 Jun 24 16:41 erlang/
drwxr-xr-x  2 root root 4096 Jun 24 16:41 flex/
drwxr-xr-x  2 root root 4096 Jun 24 16:41 html/
drwxr-xr-x  2 root root 4096 Jun 24 16:41 javascript/
drwxr-xr-x  2 root root 4096 Jun 24 16:41 kotlin/
drwxr-xr-x  2 root root 4096 Jun 24 16:41 package/
drwxr-xr-x  2 root root 4096 Jun 24 16:41 php/
drwxr-xr-x  2 root root 4096 Jun 24 16:41 pli/
drwxr-xr-x  2 root root 4096 Jun 24 16:41 python/
drwxr-xr-x  2 root root 4096 Jun 24 16:41 rpg/
drwxr-xr-x  2 root root 4096 Jun 24 16:41 samples/
drwxr-xr-x  2 root root 4096 Jun 24 16:41 sql/
drwxr-xr-x  2 root root 4096 Jun 24 16:41 swift/
drwxr-xr-x  2 root root 4096 Jun 24 16:41 vb6/
drwxr-xr-x  2 root root 4096 Jun 24 16:41 xml/

扫描php代码, 每个代码目录都要有一个sonar-project.properties文件, 来指定项目名称, 扫描代码后会在sonarqube显示

root@jenkins:/opt/sonar-scanning-examples-master/sonarqube-scanner/src/php# vim ../../sonar-project.properties 

sonar.projectKey=org.sonarqube:sonarqube-scanner                                                                                                                            
sonar.projectName=Example of SonarQube Scanner Usage
sonar.projectVersion=1.0

sonar.sources=src,copybooks

sonar.sourceEncoding=UTF-8

## Cobol Specific Properties

# comma-separated paths to directories with copybooks
sonar.cobol.copy.directories=copybooks
# comma-separated list of suffixes
sonar.cobol.file.suffixes=cbl,cpy
sonar.cobol.copy.suffixes=cpy



## Flex Specific Properties

# retrieve code coverage data from the Cobertura report
sonar.flex.cobertura.reportPath=coverage-report/coverage-cobertua-flex.xml



# PL/I Specific Properties
sonar.pli.marginLeft=2
sonar.pli.marginRight=0

root@jenkins:/opt/sonar-scanning-examples-master/sonarqube-scanner/src/php# ll
total 16
drwxr-xr-x  2 root root 4096 Jun 24 16:41 ./
drwxr-xr-x 20 root root 4096 Jun 24 16:41 ../
-rw-r--r--  1 root root 5559 Jun 24 16:41 Math.php

sonar-project.properties文件拷贝到php目录下, 做修改

root@jenkins:/opt/sonar-scanning-examples-master/sonarqube-scanner# cp sonar-project.properties src/php/
root@jenkins:/opt/sonar-scanning-examples-master/sonarqube-scanner# cd src/php
root@jenkins:/opt/sonar-scanning-examples-master/sonarqube-scanner/src/php# vim sonar-project.properties

sonar.projectKey=sonarqube-sample-php-projectKey                                                                                                                            
sonar.projectName=sonarqube-sample-php-projectName
sonar.projectVersion=1.0

sonar.sources=src # src目录相对于php目录, 因此, 在php目录下还要创建src目录, 存放php代码
sonar.language=php
sonar.sourceEncoding=UTF-8

root@jenkins:/opt/sonar-scanning-examples-master/sonarqube-scanner/src/php# mkdir src
root@jenkins:/opt/sonar-scanning-examples-master/sonarqube-scanner/src/php# mv Math.php src/
root@jenkins:/opt/sonar-scanning-examples-master/sonarqube-scanner/src/php# ll
total 16
drwxr-xr-x  3 root root 4096 Jul  6 23:47 ./
drwxr-xr-x 20 root root 4096 Jun 24 16:41 ../
-rw-r--r--  1 root root  172 Jul  6 23:47 sonar-project.properties
drwxr-xr-x  2 root root 4096 Jul  6 23:47 src/
root@jenkins:/opt/sonar-scanning-examples-master/sonarqube-scanner/src/php# ll src/
total 16
drwxr-xr-x 2 root root 4096 Jul  6 23:47 ./
drwxr-xr-x 3 root root 4096 Jul  6 23:47 ../
-rw-r--r-- 1 root root 5559 Jun 24 16:41 Math.php

php目录下执行扫描命令

root@jenkins:/opt/sonar-scanning-examples-master/sonarqube-scanner/src/php# /apps/sonar-scanner/bin/sonar-scanner
...
INFO: ANALYSIS SUCCESSFUL, you can browse http://10.0.0.139:9000/dashboard?id=sonarqube-sample-php-projectKey
...
NFO: EXECUTION SUCCESS
INFO: ------------------------------------------------------------------------
INFO: Total time: 8.974s
INFO: Final Memory: 6M/24M
INFO: 
  • 查看结果
图片.png
图片.png

3 Gitlab+Jenkins+Sonarqube结合使用

让Jenkins到Gitlab拉取代码到本地, 之后使用SonarScanner进行代码扫描, 然后传到Sonarqube

3.1 通过Jenkins插件执行代码扫描

3.1.1 创建一个测试项目, 测试web-02项目克隆

图片.png
图片.png
图片.png
图片.png

3.1.2 Jenkins安装插件

图片.png
root@jenkins:/tmp# systemctl restart jenkins

3.1.3 在Jenkins上, 配置Sonarqube Server地址

图片.png
图片.png

3.1.4 在Jenkins上, 配置Sonarscanner的路径

图片.png
图片.png
  • 如果Jenkins服务器可以联网, 也可使用自动安装, 这样Jenkins会自动下载Scanner到本地, 如果不能上网, 就要通过离线安装包的方式

3.1.5 在Jenkins上, 配置项目构建

选择项目 --> 配置 --> 构建 --> Execute SonarQube Scanner --> 将Analysis properties里的内容填写为代码扫描的properties文件里的内容

图片.png
jenkins@jenkins:/opt/sonar-scanning-examples-master/sonarqube-scanner/src/php$ vim sonar-project.properties 

sonar.projectKey=sonarqube-sample-php-projectKey
sonar.projectName=sonarqube-sample-php-projectName
sonar.projectVersion=1.0

sonar.sources=src
sonar.language=php
sonar.sourceEncoding=UTF-8

本案例内容

sonar.projectKey=project-web-02
sonar.projectName=project-web-02
sonar.projectVersion=1.0

sonar.sources=./ # 这里写./表示当前目录, 也就是相对于/var/lib/jenkins/workspace/test-scanner目录, Scanner会扫描该目录下的所有文件. 如果代码放到了$WORKSPACE/src目录, 那么这里就写src
sonar.languagehtml # web-02里只有一个html文件
sonar.sourceEncoding=UTF-8
  • 执行构建
图片.png
  • Sonarqube Server查看结果
图片.png

3.2 通过脚本自定义代码扫描

配置项目构建时, 无需指定git仓库, 也无需使用Scanner插件, 而是统一把流程定义在构建的Shell脚本中.

先在Jenkins服务器上, 用Jenkins用户运行脚本测试, 如果没问题, 再把脚本保存的构建的Shell脚本中

先用root用户创建/data/jenkins/qq目录, 然后授权给jenkins用户
root@jenkins:~# mkdir -pv /data/jenkins/qq
root@jenkins:~# chown -R jenkins.jenkins /data/jenkins/
切换到jenkins用户下, 创建脚本

jenkins@jenkins:/opt$ vim sonar.sh

#!/bin/bash
  
cd /data/jenkins/qq # 进到项目目录

rm -rf * && git clone [email protected]:qq/web-02.git # 删除旧的项目内容, clone新的内容
 
cd web-02 # 进到项目里面

cat >> sonar-project.properties <
INFO: Analysis total time: 3.226 s
INFO: ------------------------------------------------------------------------
INFO: EXECUTION SUCCESS
INFO: ------------------------------------------------------------------------
INFO: Total time: 3.916s
INFO: Final Memory: 12M/44M
INFO: ------------------------------------------------------------------------

测试没问题, 保存到Jenkins配置

图片.png

图片.png

你可能感兴趣的:(13. Sonarqube实现代码扫描)