SonarQube介绍、安装、使用、错误总结
- 一、Sonar介绍
- 二、Sonar组成
- 三、SonarQube、JDK、MySQL 版本对应说明
- 四、Ubuntu 18.0.4 SonarQube-7.1.x 安装教程
- 1. zip安装下载地址
- 2. 环境准备
- 3.上传到ubuntu
- 4. 数据库配置
- 5.配置sonar的数据库信息(vim conf/sonar.properties)
- 6.启动
- 7. 登录系统
- 五、sonarqube安装后,汉化
- 六、sonar扫描gradle项目
- 七、将sonar检测结果导出为PDF
- 八、ide集成sonar
- 九、错误总结
- 错误1:Elasticsearch 虚拟内存需要至少[262144]
- 错误2:使用root账户启动
- 十、未解决问题【docker安装】
- docker安装步骤【未成功】
一、Sonar介绍
Sonar(SonarQube)是一个开源平台,用于管理源代码的质量。Sonar 不只是一个质量数据报告工具,更是代码质量管理平台。支持的语言包括:Java、PHP、C#、C、Cobol、PL/SQL、Flex 等。
特性
idea在集成sonar插件后,就可以在代码提交前发现代码中的不规范和漏洞,即使进行修复,而不是等到提交到仓库后在进行代码质量扫描,然后重复提交–检测–修复的过程。
sonar目前可以扫除以下类型的问题点
- 不遵循代码规范
sonar可以通过PMD,CheckStyle,Findbugs等代码规则检测工具规范代码编写 - 潜在的缺陷
sonar可以通过PMD,CheckStyle,Findbugs等等代码规则检测工具检测出潜在的缺陷 - 复杂度过高的代码
如果复杂度过高将难以改变,这会降低代码的可读性,而且会造成开发人员理解难度加大 - 重复代码
显然程序中包含大量复制粘贴的代码是质量低下的,sonar可以展示源码中重复严重的地方 - 注释不足或者冗余
没有注释将使代码可读性变差,程序的可读性将大幅下降而过多的注释又会使得开发人员将精力过多地花费在阅读注释上,浪费时间 - 缺乏单元测试
sonar可以很方便地统计并展示单元测试覆盖率 - 糟糕的设计
通过sonar可以找出循环,展示包与包、类与类之间相互依赖关系,可以检测自定义的架构规则通过sonar可以管理第三方的jar包,可以利用LCOM4检测单个任务规则的应用情况, 检测耦合
它是从 Architecture Design(架构设计) , Coding Rule(编码规则), Potential Bugs(潜在错误), Duplications(重复代码), Comments(注释), Unit Tests(单元测试), Complexity(复杂度) 7个维度检查代码质量的。 相比lint工具检测维度比较全面, 有可视化的友好展示代码缺陷的界面,结合CI/CD工具,可以不依赖手工检查,定时清查代码。
二、Sonar组成
sonarqube系统是一个代码质量检测工具 由以下四个组件组成
一个sonarqube服务器,包含三个子进程(web服务(界面管理),搜索服务,计算引擎服务(写入数据库))。
一个sonarqube数据库,配置sonarqube服务 。
多个sonarqube插件,位于解压目录extensionsplugins目录 。
一个或者多个sonarqube scanners用于分析特定的项目,相当于客户端。
工作流转
以下架构图为 sonar 项目的工作流转图:
- 开发人员在其IDE中进行编码,并使用SonarLint运行本地分析。
- 开发人员将其代码推送到他们最喜欢的SCM中:git,SVN,TFVC等。
- Continuous Integration Server会触发自动构建,并执行运行SonarQube分析所需的SonarScanner。
- 分析报告将发送到SonarQube服务器进行处理。
- SonarQube Server处理分析报告结果并将其存储在SonarQube数据库中,并在UI中显示结果。
- 开发人员通过SonarQube UI审查,评论,挑战他们的问题,以管理和减少技术债务。
- 经理从分析中接收报告。Ops使用API自动执行配置并从SonarQube提取数据。运维人员使用JMX监视SonarQube Server。
三、SonarQube、JDK、MySQL 版本对应说明
文档地址:https://docs.sonarqube.org/latest/requirements/prerequisites-and-overview/
SonarQube 与 JDK 和 MySQL 都有版本对应,查看 SonarQube 与 JDK、数据库 版本对应:
例如 SonarQube 9.8 对应JDK 17,PostgreSQL 15。
SonarQube 7.6, 对应 JDK8,MySQL 版本>=5.6 && <8.0。(sonarqube从7.8起,不再支持mysql)(要安装对版本,比如mysql要求5.6或者5.7 你要是使用8.0 就会失败,亲测–)
大家安装时,一定要注意,本人在此踩过坑
如果本地jdk是8以下的,安装7.8及以下版本
四、Ubuntu 18.0.4 SonarQube-7.1.x 安装教程
zip安装
版本注意:jdk8支持的sonarqube版本最高是7.8,,而从7.9版本开始都是要求jdk11了,下载的话需要注意版本的对应关系,不要走弯路
1. zip安装下载地址
- sonarQube最新版下载地址:(最新版不支持mysql)https://www.sonarsource.com/products/sonarqube/downloads/
- 7.1版本下载地址: https://binaries.sonarsource.com/Distribution/sonarqube/sonarqube-7.1.zip
- Sonar-Scanner 2.5下载地址: https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/
下载不了:参考该地址中的下载:
https://blog.51cto.com/u_14082075/5465953#1__6
2. 环境准备
(1)Java环境(1.8+)
(2)MySql数据库(5.6+)
(3)SonarQube 7.1
注意:sonarQube 7.9的版本之后就不在支持mysql,所以下载的是7.1版本。
3.上传到ubuntu
//解压
unzip sonarqube-6.7.7.zip
//移动目录
mv sonarqube-6.7.7 /usr/local/sonar
4. 数据库配置
.进入mysql容器并创建用户账户密码均为sonar
# docker exec -it mysql bash
# mysql -u root -p
# create database sonar;
# CREATE USER 'sonar'@'%' IDENTIFIED WITH mysql_native_password BY 'sonar';
# GRANT ALL PRIVILEGES ON *.* TO 'sonar'@'%';
# exit
5.配置sonar的数据库信息(vim conf/sonar.properties)
安装目录下的conf中的配置文件,
sonar.jdbc.url=jdbc:mysql://localhost:3306/sonar?useUnicode=true&characterEncoding=utf8&rewriteBatchedStatements=true&useConfigs=maxPerformance&useSSL=false
sonar.jdbc.username=sonar
sonar.jdbc.password=sonar
6.启动
不能使用root用户启动,新建个用户
//新建用户
useradd sonar
//赋权
chown -R sonar.sonar /usr/local/sonar
//修改密码
passwd sonar
//切换到sonar用户
su sonar
//启动: 进入到sonar目录下,即bin的同级目录,执行下边的命令
./bin/linux-x86-64/sonar.sh console
7. 登录系统
http://ip:9000 用户名密码:admin
汉化,重启服务即可
五、sonarqube安装后,汉化
如果出现“Error while downloading plugin ‘l10nzhtw’ with version ‘1.0’. No compatible plugin found.”错误,那说明版本不兼容,可到官网查找对应版本的插件放到…/…/extensions/plugins目录下,重新启动sonar服务【使用命令…/…/sonar.sh start 也可以通过页面操作“配置->系统->重启服务器”】,即可生效。但如果安装的插件比当前版本低的话,会出现部分显示还是英文。
汉化插件下载[找到对应的版本,下载对应的插件]:https://github.com/xuhuisheng/sonar-l10n-zh/releases?page=2
放到该路径下:
cd /usr/local/sonarqube-8.6.0/extensions/plugins
重启服务即可【不可使用root用户登录】
- 生成令牌(需要将生成的令牌复制下来):
启动成功后,会在对应的sonar中创建对应的数据库
六、sonar扫描gradle项目
- git上下载gradle项目
这是我的项目目录
2.配置
buildscript {
repositories {
maven {
url "http://xxxxxxxxxx"
}
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
// 添加依赖信息
classpath("org.sonarsource.scanner.gradle:sonarqube-gradle-plugin:2.6.2")
}
}
// 声明插件
apply plugin: "org.sonarqube"
//配置sonar的配置信息
sonarqube {
properties {
property "sonar.host.url", "http://127.0.0.1:9000"
property "sonar.login", "admin"
property "sonar.password", "admin"
property "sonar.scm.provider", "git"
property "sonar.projectKey", artifactId
property "sonar.projectVersion", version
property "sonar.sourceEncoding", defaultCharset
property "sonar.sources", "src/main/java"
//property "sonar.tests", "src/test/java"
property "sonar.java.source", "1.8"
property "sonar.java.binaries", "build/classes/java/main/"
//property "sonar.java.test.binaries", "build/classes/java/test/"
property "sonar.java.coveragePlugin", "jacoco"
property "sonar.coverage.jacoco.xmlReportPaths", "build/reports/jacoco/test/jacocoTestReport.xml"
property "sonar.dependencyCheck.xmlReportPath", "build/reports/dependency-check-report.xml"
property "sonar.dependencyCheck.jsonReportPath", "build/reports/dependency-check-report.json"
property "sonar.dependencyCheck.htmlReportPath", "build/reports/dependency-check-report.html"
}
}
3.执行gradle sonarqube
gradle sonarqube
4.查看web页面是否有扫描信息
七、将sonar检测结果导出为PDF
1.下载PDF导出插件
https://gitee.com/zzulj/sonar-pdf-plugin
找到对应的sonarqube版本进行下载,这里直接下载jar就可以了,如果下载源码还需要编译
2.复制sonar-pdfreport-plugin-xxxxx.jar,到sonarqube的extensions的plugins里。
3.重新启动sonarqube,web可以看到一个PDF Report,需要对PDF插件进行配置,首先是在网页上,如下图,配置完了password,网页下面还有个userName要配置,我这里配置的都是admin
4.在网页配置完了后,还需要在sonarqube中对pdf-plugin进行配置
vi /usr/local/sonar/conf/sonar.properties
# 在该文件中增加
-Dsonar.pdf.password=admin
-Dsonar.pdf.username=admin
5在进行完一些列配置后,重新对项目进行扫描,在build的过程中,会出现pdf-plugin的相关信息,之后在网页上就可以按照下图的步骤导出PDF了
八、ide集成sonar
SonarLint:IDEA 的 Sonar 插件
1.在插件仓库中搜索 “SonarLint” 插件,找到插件后点击安装即可
2.插件安装完成后,右击项目出现SonarLint 选择 “Analyze with SonarLint” 即可
九、错误总结
错误1:Elasticsearch 虚拟内存需要至少[262144]
# docker logs sonarqube_sonarqube_1
ERROR: [1] bootstrap checks failed. You must address the points described in the following [1] lines before starting Elasticsearch.
bootstrap check failure [1] of [1]: max virtual memory areas vm.max_map_count [65530] is too low, increase to at least [262144]
ERROR: Elasticsearch did not exit normally - check the logs at /opt/sonarqube/logs/sonarqube.log
解决方案:
大致看了一下,是因为ElasticSearch运行的时候最小内存消耗要达到262144,所以,如果是在自己的虚拟机运行,可以临时调整vm.max_map_count的大小,max_map_count文件包含限制一个进程可以拥有的VMA(虚拟内存区域)的数量,临时调整的语句如下:
sysctl -w vm.max_map_count=262144
调整之后再运行es集群就不会有问题了。
如果想永久修改vm.max_map_count的大小,则可以使用如下命令:
echo vm.max_map_count=262144>> /etc/sysctl.conf sysctl -p
错误2:使用root账户启动
不能使用root用户启动,新建个用户,我新建了一个sonar用户,然后给该用户授权,启动
十、未解决问题【docker安装】
一开始为了省事,使用docker安装,但是一直启动不起来,报错 Can not connect to database. Please check connectivity and settings (see the properties prefixed by ‘sonar.jdbc.’).
根据网上提供的方案,都没有用
- 1.数据库用户名、密码均使用sonar/sonar 数据库名:sonar
-
docker安装步骤【未成功】
1…docker拉取sonarqube镜像
docker pull sonarqube:7.8-community
可在官网查找你想要的版本:https://hub.docker.com/_/sonarqube?tab=tags&page=9
2…进入mysql容器并创建用户账户密码均为sonar
# docker exec -it mysql bash
# mysql -u root -p
# create database sonar;
# CREATE USER 'sonar'@'%' IDENTIFIED WITH mysql_native_password BY 'sonar';
# GRANT ALL PRIVILEGES ON *.* TO 'sonar'@'%';
# exit
3.启动sonarqube
docker run -d --name sonar -p 9000:9000 -p 9092:9092 -v /data/sonar/conf:/opt/sonarqube/conf -v /data/sonar/data:/opt/sonarqube/data -v /data/sonar/logs:/opt/sonarqube/logs -v /data/sonar/extensions:/opt/sonarqube/extensions -e "SONARQUBE_DATABASE_USER=sonar" -e "SONARQUBE_DATABASE_NAME=sonar" -e "SONARQUBE_DATABASE_PASSWORD=sonar" -e "SONARQUBE_JDBC_URL=jdbc:mysql://127.0.0.1:3306/sonar?useUnicode=true&characterEncoding=utf8&rewriteBatchedStatements=true&useConfigs=maxPerformance&useSSL=false" sonarqube:7.8-community
4.对应的映射配置/data/sonar/conf中的数据库配置是否正确
vi sonar.properties
#sonar.jdbc.url=jdbc:mysql://localhost:3306/sonar?useUnicode=true&characterEncoding=utf8&rewriteBatchedStatements=true&useConfigs=maxPerformanc
e#sonar.jdbc.username=sonar
#sonar.jdbc.password=sonar
#sonar.sorceEncoding=UTF-8
root@koal-ipsec:/data/sonar/conf# docker logs sonar
2022.12.26 05:15:07 INFO app[][o.s.a.AppFileSystem] Cleaning or creating temp directory /opt/sonarqube/temp
2022.12.26 05:15:07 INFO app[][o.s.a.es.EsSettings] Elasticsearch listening on /127.0.0.1:9001
2022.12.26 05:15:07 INFO app[][o.s.a.p.ProcessLauncherImpl] Launch process[[key='es', ipcIndex=1, logFilenamePrefix=es]] from [/opt/sonarqube/elasticsearch]: /opt/sonarqube/elasticsearch/bin/elasticsearch -Epath.conf=/opt/sonarqube/temp/conf/es
2022.12.26 05:15:07 INFO app[][o.s.a.SchedulerImpl] Waiting for Elasticsearch to be up and running
2022.12.26 05:15:07 INFO app[][o.e.p.PluginsService] no modules loaded
2022.12.26 05:15:07 INFO app[][o.e.p.PluginsService] loaded plugin [org.elasticsearch.transport.Netty4Plugin]
2022.12.26 05:15:14 INFO app[][o.s.a.SchedulerImpl] Process[es] is up
2022.12.26 05:15:14 INFO app[][o.s.a.p.ProcessLauncherImpl] Launch process[[key='web', ipcIndex=2, logFilenamePrefix=web]] from [/opt/sonarqube]: /usr/lib/jvm/java-8-openjdk-amd64/jre/bin/java -Djava.awt.headless=true -Dfile.encoding=UTF-8 -Djava.io.tmpdir=/opt/sonarqube/temp -Xmx512m -Xms128m -XX:+HeapDumpOnOutOfMemoryError -Djava.security.egd=file:/dev/./urandom -cp ./lib/common/*:./lib/server/*:/opt/sonarqube/lib/jdbc/mysql/mysql-connector-java-5.1.42.jar org.sonar.server.app.WebServer /opt/sonarqube/temp/sq-process8004789798386622755properties
2022.12.26 05:15:14 INFO web[][o.s.p.ProcessEntryPoint] Starting web
2022.12.26 05:15:15 INFO web[][o.a.t.u.n.NioSelectorPool] Using a shared selector for servlet write/read
2022.12.26 05:15:15 INFO web[][o.e.p.PluginsService] no modules loaded
2022.12.26 05:15:15 INFO web[][o.e.p.PluginsService] loaded plugin [org.elasticsearch.index.reindex.ReindexPlugin]
2022.12.26 05:15:15 INFO web[][o.e.p.PluginsService] loaded plugin [org.elasticsearch.join.ParentJoinPlugin]
2022.12.26 05:15:15 INFO web[][o.e.p.PluginsService] loaded plugin [org.elasticsearch.percolator.PercolatorPlugin]
2022.12.26 05:15:15 INFO web[][o.e.p.PluginsService] loaded plugin [org.elasticsearch.transport.Netty4Plugin]
2022.12.26 05:15:16 INFO web[][o.s.s.e.EsClientProvider] Connected to local Elasticsearch: [127.0.0.1:9001]
2022.12.26 05:15:16 INFO web[][o.s.s.p.LogServerVersion] SonarQube Server / 6.7.5.38563 / ec8ab77fa180a9edaf664075e8e76ae0b4a2d9f1
2022.12.26 05:15:16 INFO web[][o.sonar.db.Database] Create JDBC data source for jdbc:mysql://127.0.0.1:3306/db_sonar?useUnicode=true&characterEncoding=utf8&rewriteBatchedStatements=true&useConfigs=maxPerformance&useSSL=false
2022.12.26 05:15:16 ERROR web[][o.s.s.p.Platform] Web server startup failed
java.lang.IllegalStateException: Can not connect to database. Please check connectivity and settings (see the properties prefixed by 'sonar.jdbc.').
at org.sonar.db.DefaultDatabase.checkConnection(DefaultDatabase.java:108)
at org.sonar.db.DefaultDatabase.start(DefaultDatabase.java:75)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.picocontainer.lifecycle.ReflectionLifecycleStrategy.invokeMethod(ReflectionLifecycleStrategy.java:110)
at org.picocontainer.lifecycle.ReflectionLifecycleStrategy.start(ReflectionLifecycleStrategy.java:89)
at org.picocontainer.injectors.AbstractInjectionFactory$LifecycleAdapter.start(AbstractInjectionFactory.java:84)
at org.picocontainer.behaviors.AbstractBehavior.start(AbstractBehavior.java:169)
at org.picocontainer.behaviors.Stored$RealComponentLifecycle.start(Stored.java:132)
at org.picocontainer.behaviors.Stored.start(Stored.java:110)
at org.picocontainer.DefaultPicoContainer.potentiallyStartAdapter(DefaultPicoContainer.java:1016)
at org.picocontainer.DefaultPicoContainer.startAdapters(DefaultPicoContainer.java:1009)
at org.picocontainer.DefaultPicoContainer.start(DefaultPicoContainer.java:767)
at org.sonar.core.platform.ComponentContainer.startComponents(ComponentContainer.java:134)
at org.sonar.server.platform.platformlevel.PlatformLevel.start(PlatformLevel.java:90)
at org.sonar.server.platform.Platform.start(Platform.java:211)
at org.sonar.server.platform.Platform.startLevel1Container(Platform.java:170)
at org.sonar.server.platform.Platform.init(Platform.java:86)
at org.sonar.server.platform.web.PlatformServletContextListener.contextInitialized(PlatformServletContextListener.java:45)
at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4745)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5207)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1419)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1409)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
Caused by: org.apache.commons.dbcp.SQLNestedException: Cannot create PoolableConnectionFactory (Communications link failure
The last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the server.)
at org.apache.commons.dbcp.BasicDataSource.createPoolableConnectionFactory(BasicDataSource.java:1549)
at org.apache.commons.dbcp.BasicDataSource.createDataSource(BasicDataSource.java:1388)
at org.apache.commons.dbcp.BasicDataSource.getConnection(BasicDataSource.java:1044)
at org.sonar.db.profiling.NullConnectionInterceptor.getConnection(NullConnectionInterceptor.java:31)
at org.sonar.db.profiling.ProfiledDataSource.getConnection(ProfiledDataSource.java:323)
at org.sonar.db.DefaultDatabase.checkConnection(DefaultDatabase.java:106)
... 29 common frames omitted
Caused by: com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure
The last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the server.
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at com.mysql.jdbc.Util.handleNewInstance(Util.java:425)
at com.mysql.jdbc.SQLError.createCommunicationsException(SQLError.java:989)
at com.mysql.jdbc.MysqlIO.<init>(MysqlIO.java:341)
at com.mysql.jdbc.ConnectionImpl.coreConnect(ConnectionImpl.java:2192)
at com.mysql.jdbc.ConnectionImpl.connectOneTryOnly(ConnectionImpl.java:2225)
at com.mysql.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:2024)
at com.mysql.jdbc.ConnectionImpl.<init>(ConnectionImpl.java:779)
at com.mysql.jdbc.JDBC4Connection.<init>(JDBC4Connection.java:47)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at com.mysql.jdbc.Util.handleNewInstance(Util.java:425)
at com.mysql.jdbc.ConnectionImpl.getInstance(ConnectionImpl.java:389)
at com.mysql.jdbc.NonRegisteringDriver.connect(NonRegisteringDriver.java:330)
at org.apache.commons.dbcp.DriverConnectionFactory.createConnection(DriverConnectionFactory.java:38)
at org.apache.commons.dbcp.PoolableConnectionFactory.makeObject(PoolableConnectionFactory.java:582)
at org.apache.commons.dbcp.BasicDataSource.validateConnectionFactory(BasicDataSource.java:1556)
at org.apache.commons.dbcp.BasicDataSource.createPoolableConnectionFactory(BasicDataSource.java:1545)
... 34 common frames omitted
Caused by: java.net.ConnectException: Connection refused (Connection refused)
at java.net.PlainSocketImpl.socketConnect(Native Method)
at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350)
at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206)
at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188)
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
at java.net.Socket.connect(Socket.java:589)
at com.mysql.jdbc.StandardSocketFactory.connect(StandardSocketFactory.java:211)
at com.mysql.jdbc.MysqlIO.<init>(MysqlIO.java:300)
... 50 common frames omitted
2022.12.26 05:15:17 INFO app[][o.s.a.SchedulerImpl] Process [web] is stopped
2022.12.26 05:15:17 WARN app[][o.s.a.p.AbstractProcessMonitor] Process exited with exit value [es]: 143
2022.12.26 05:15:17 INFO app[][o.s.a.SchedulerImpl] Process [es] is stopped
2022.12.26 05:15:17 INFO app[][o.s.a.SchedulerImpl] SonarQube is stopped
最后
以上就是俏皮胡萝卜最近收集整理的关于Sonar介绍、Ubuntu 18.0.4 SonarQube安装、使用、错误总结的全部内容,更多相关Sonar介绍、Ubuntu内容请搜索靠谱客的其他文章。
发表评论 取消回复