1. 摘要
SonarQube是一款用于代碼質量管理的開源工具,它主要用于管理源代碼的質量。 通過插件形式,可以支持眾多計算機語言,比如 java, C#, go,C/C++, PL/SQL, Cobol, JavaScrip, Groovy 等。sonar可以通過PMD,CheckStyle,Findbugs等等代碼規則檢測工具來檢測你的代碼,幫助你發現代碼的漏洞,Bug,異味等信息。
本文講解該軟件在Ubuntu環境的搭建過程。
2. 內容
2.1 前置環境
從Sonar7.8版本開始,要求支持Java11,不再支持MySQL數據庫。
本文講解目前主流環境下(在Java8(JDKv1.8.0)和MySQL)版本中安裝Sonar7.7的完整過程。
2.2 配置MySQL數據庫
登錄MySQL
mysql -u root -p
create database sonar character set utf8 collate utf8_general_ci;
create user 'sonar' identified by 'sonar';
grant all on sonar.* to 'sonar'@'%' identified by 'sonar';
grant all on sonar.* to 'sonar'@'localhost' identified by 'sonar';
flush privileges;
輝哥實際采用寶塔完成數據庫的創建和配置,數據庫名:sonar 用戶名:sonar 同以上命令實現。
2.2 下載安裝sonar
2.2.1 下載安裝sonar
(1)在國內從官網下載sonar的速度特別慢。下載地址:https://binaries.sonarsource.com/Distribution/sonarqube/sonarqube-7.7.zip
下載后上傳到Linux服務器,進行解壓縮安裝。
$ unzip sonarqube-7.7.zip
$ mkdir /opt/sonar
$ mv sonarqube-7.7/* /opt/sonar/
(2)sonar無法使用root啟動,需要創建新的sonar用戶,密碼自行記錄。
$ useradd sonar
$ passwd sonar
賦予普通用戶sonar具有sonar軟件的所有讀寫執行權限。
chown將指定文件的擁有者改為指定的用戶或組,用戶可以是用戶名或者用戶ID;組可以是組名或者組ID;文件是以空格分開的要改變權限的文件列表,支持通配符。-R表示 處理指定目錄以及其子目錄下的所有文件
$ chown -R sonar. /opt/sonar/
(3)sonar默認偵聽接口為9000。啟動前采用netstat查看9000接口有無被占用。修改sonar配置文件。
9001默認被自帶的elastic search啟動占用,也要保證該端口不被其他進程占用。
$ netstat -nltp
$ cd /opt/sonar/
$ vim conf/sonar.properties
編輯的核心內容如下:
sonar.jdbc.username=sonar
sonar.jdbc.password=***#需要修改訪問數據庫的密碼
sonar.jdbc.url=jdbc:mysql://localhost:3306/sonar?useUnicode=true&characterEncoding=utf8&rewriteBatchedStatements=true&useConfigs=maxPerformance&useSSL=false
sonar.web.port=9000 #偵聽端口
sonar.web.host=0.0.0.0 # 開放,允許所有IP訪問該端口。
#sonarWEB登錄用戶密碼
sonar.login=admin
sonar.password=***#需要修改為訪問頁面的初始密碼,可以修改
(4)啟動sonarqube
啟動sonarqube:
$ su sonar
$ ./bin/linux-x86-64/sonar.sh start
查看sonarqube,這個表示啟動成功。16395是其進程號。
$ ./bin/linux-x86-64/sonar.sh status
SonarQube is running (16395)
kill -9 進程號可殺死。也可以采用stop命令關閉。
$ ./bin/linux-x86-64/sonar.sh stop
2.2.2 常見啟動失敗問題及排查
如果啟動不成功,可能有各種原因。可以查看啟動日志,并逐個排查問題解決。
$ tail -f logs/sonar.log
(1)JAVA版本不合適
vim logs/sonar.log
【問題】
WrapperSimpleApp: Encountered an error running main: java.lang.IllegalStateException: SonarQube requires Java 11 to run
java.lang.IllegalStateException: SonarQube requires Java 11 to run
at com.google.common.base.Preconditions.checkState(Preconditions.java:173)
【分析結論】
需要Java11運行。這個是安裝sonarqube-7.9 TLS版本遇到的問題。改為安裝sonarqube-7.7版本,以便支持JDK1.8的環境。
(2)以root用戶運行
【問題】
vim logs/sonar.log
2021.03.18 15:19:02 INFO app[][o.s.a.AppFileSystem] Cleaning or creating temp directory /opt/sonar/temp
2021.03.18 15:19:02 INFO app[][o.s.a.es.EsSettings] Elasticsearch listening on /127.0.0.1:9001
2021.03.18 15:19:02 INFO app[][o.s.a.p.ProcessLauncherImpl] Launch process[[key='es', ipcIndex=1, logFilenamePrefix=es]] from [/opt/sonar/elasticsearch]: /opt/sonar/elasticsearch/bin/elasticsearch
2021.03.18 15:19:02 INFO app[][o.s.a.SchedulerImpl] Waiting for Elasticsearch to be up and running
2021.03.18 15:19:03 INFO app[][o.e.p.PluginsService] no modules loaded
2021.03.18 15:19:03 INFO app[][o.e.p.PluginsService] loaded plugin [org.elasticsearch.transport.Netty4Plugin]
2021.03.18 15:19:05 WARN app[][o.s.a.p.AbstractProcessMonitor] Process exited with exit value [es]: 1
2021.03.18 15:19:05 INFO app[][o.s.a.SchedulerImpl] Process [es] is stopped
2021.03.18 15:19:05 INFO app[][o.s.a.SchedulerImpl] SonarQube is stopped
<-- Wrapper Stopped
vim es.log
java.lang.RuntimeException: can not run elasticsearch as root
at org.elasticsearch.bootstrap.Bootstrap.initializeNatives(Bootstrap.java:103) ~[elasticsearch-6.6.2.jar:6.6.2]
at org.elasticsearch.bootstrap.Bootstrap.setup(Bootstrap.java:170) ~[elasticsearch-6.6.2.jar:6.6.2]
at org.elasticsearch.bootstrap.Bootstrap.init(Bootstrap.java:333) [elasticsearch-6.6.2.jar:6.6.2]
at org.elasticsearch.bootstrap.Elasticsearch.init(Elasticsearch.java:159) [elasticsearch-6.6.2.jar:6.6.2]
at org.elasticsearch.bootstrap.Elasticsearch.execute(Elasticsearch.java:150) [elasticsearch-6.6.2.jar:6.6.2]
at org.elasticsearch.cli.EnvironmentAwareCommand.execute(EnvironmentAwareCommand.java:86) [elasticsearch-6.6.2.jar:6.6.2]
at org.elasticsearch.cli.Command.mainWithoutErrorHandling(Command.java:124) [elasticsearch-cli-6.6.2.jar:6.6.2]
at org.elasticsearch.cli.Command.main(Command.java:90) [elasticsearch-cli-6.6.2.jar:6.6.2]
at org.elasticsearch.bootstrap.Elasticsearch.main(Elasticsearch.java:116) [elasticsearch-6.6.2.jar:6.6.2]
at org.elasticsearch.bootstrap.Elasticsearch.main(Elasticsearch.java:93) [elasticsearch-6.6.2.jar:6.6.2]
2021.03.18 15:19:05 WARN es[][o.e.b.ElasticsearchUncaughtExceptionHandler] uncaught exception in thread [main]
org.elasticsearch.bootstrap.StartupException: java.lang.RuntimeException: can not run elasticsearch as root
at org.elasticsearch.bootstrap.Elasticsearch.init(Elasticsearch.java:163) ~[elasticsearch-6.6.2.jar:6.6.2]
at org.elasticsearch.bootstrap.Elasticsearch.execute(Elasticsearch.java:150) ~[elasticsearch-6.6.2.jar:6.6.2]
at org.elasticsearch.cli.EnvironmentAwareCommand.execute(EnvironmentAwareCommand.java:86) ~[elasticsearc
【分析結論】
sonar.log沒有有效信息。但是es.log明確指出不能使用root用戶啟動的。
切換到sonar用戶,重新啟動sonar服務了。
(3)端口被占用
vim logs/sonar.log
【問題】
sh-4.4$ ./bin/linux-x86-64/sonar.sh console
Running SonarQube...
wrapper | --> Wrapper Started as Console
wrapper | Launching a JVM...
jvm 1 | Wrapper (Version 3.2.3) http://wrapper.tanukisoftware.org
jvm 1 | Copyright 1999-2006 Tanuki Software, Inc. All Rights Reserved.
jvm 1 |
jvm 1 | 2021.03.15 21:42:37 INFO app[][o.s.a.AppFileSystem] Cleaning or creating temp directory /opt/sonar/temp
jvm 1 | 2021.03.15 21:42:37 INFO app[][o.s.a.es.EsSettings] Elasticsearch listening on /127.0.0.1:9001
jvm 1 | 2021.03.15 21:42:37 INFO app[][o.s.a.p.ProcessLauncherImpl] Launch process[[key='es', ipcIndex=1, logFilenamePrefix=es]] from [/opt/sonar/elasticsearch]: /opt/sonar/elasticsearch/bin/elasticsearch
jvm 1 | 2021.03.15 21:42:37 INFO app[][o.s.a.SchedulerImpl] Waiting for Elasticsearch to be up and running
jvm 1 | 2021.03.15 21:42:37 INFO app[][o.e.p.PluginsService] no modules loaded
jvm 1 | 2021.03.15 21:42:37 INFO app[][o.e.p.PluginsService] loaded plugin [org.elasticsearch.transport.Netty4Plugin]
jvm 1 | 2021.03.15 21:42:50 INFO app[][o.s.a.SchedulerImpl] Process[es] is up
jvm 1 | 2021.03.15 21:42:50 INFO app[][o.s.a.p.ProcessLauncherImpl] Launch process[[key='web', ipcIndex=2, logFilenamePrefix=web]] from [/opt/sonar]: /usr/lib/jvm/java-8-openjdk-amd64/jre/bin/java -Djava.awt.headless=true -Dfile.encoding=UTF-8 -Djava.io.tmpdir=/opt/sonar/temp -Xmx512m -Xms128m -XX:+HeapDumpOnOutOfMemoryError -cp ./lib/common/*:/opt/sonar/lib/jdbc/mysql/mysql-connector-java-5.1.46.jar org.sonar.server.app.WebServer /opt/sonar/temp/sq-process6941314718593124808properties
jvm 1 | 2021.03.15 21:42:51 INFO app[][o.s.a.SchedulerImpl] Process [web] is stopped
jvm 1 | 2021.03.15 21:42:52 INFO app[][o.s.a.SchedulerImpl] Process [es] is stopped
jvm 1 | 2021.03.15 21:42:52 INFO app[][o.s.a.SchedulerImpl] SonarQube is stopped
jvm 1 | 2021.03.15 21:42:52 WARN app[][o.s.a.p.AbstractProcessMonitor] Process exited with exit value [es]: 143
wrapper | <-- Wrapper Stopped
然后vim logs/web.log,保存信息如下:
2021.03.15 21:42:51 WARN web[][o.s.p.ProcessEntryPoint] Fail to start web
java.lang.RuntimeException: org.apache.catalina.LifecycleException: Failed to initialize component [StandardServer[-1]]
at com.google.common.base.Throwables.propagate(Throwables.java:160)
at org.sonar.server.app.EmbeddedTomcat.start(EmbeddedTomcat.java:65)
at org.sonar.server.app.WebServer.start(WebServer.java:51)
at org.sonar.process.ProcessEntryPoint.launch(ProcessEntryPoint.java:113)
at org.sonar.process.ProcessEntryPoint.launch(ProcessEntryPoint.java:100)
at org.sonar.server.app.WebServer.main(WebServer.java:91)
Caused by: org.apache.catalina.LifecycleException: Failed to initialize component [StandardServer[-1]]
at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:112)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:140)
at org.apache.catalina.startup.Tomcat.start(Tomcat.java:427)
at org.sonar.server.app.EmbeddedTomcat.start(EmbeddedTomcat.java:61)
... 4 common frames omitted
Caused by: org.apache.catalina.LifecycleException: Failed to initialize component [StandardService[Tomcat]]
at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:112)
at org.apache.catalina.core.StandardServer.initInternal(StandardServer.java:875)
at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:107)
... 7 common frames omitted
Caused by: org.apache.catalina.LifecycleException: Failed to initialize connector [Connector[HTTP/1.1-9001]]
at org.apache.catalina.core.StandardService.initInternal(StandardService.java:559)
at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:107)
... 9 common frames omitted
【分析結果】
sonar.log的日志表示sonar的web服務啟動后又被關閉了。無法確定其原因。
web.log的日志表示之前配置的已經被占用,導致連接失敗。" Failed to initialize connector [Connector[HTTP/1.1-9001]]"
9001端口默認被es占用,改為9000即可。
輸入curl http://127.0.0.1:9000可以獲取反饋頁面內容。
(4)
【問題描述】
sonar先啟動成功,然后not running了。
vim ./logs/sonar.log
WrapperSimpleApp: Encountered an error running main: java.nio.file.AccessDeniedException: /opt/sonar/temp/conf/es/log4j2.properties
java.nio.file.AccessDeniedException: /opt/sonar/temp/conf/es/log4j2.properties
at sun.nio.fs.UnixException.translateToIOException(UnixException.java:84)
at sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:102)
at sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:107)
at sun.nio.fs.UnixFileSystemProvider.implDelete(UnixFileSystemProvider.java:244)
at sun.nio.fs.AbstractFileSystemProvider.delete(AbstractFileSystemProvider.java:103)
at java.nio.file.Files.delete(Files.java:1126)
at org.sonar.process.FileUtils2$DeleteRecursivelyFileVisitor.visitFile(FileUtils2.java:186)
at org.sonar.process.FileUtils2$DeleteRecursivelyFileVisitor.visitFile(FileUtils2.java:181)
at java.nio.file.Files.walkFileTree(Files.java:2670)
at java.nio.file.Files.walkFileTree(Files.java:2742)
at org.sonar.process.FileUtils2.deleteDirectoryImpl(FileUtils2.java:143)
at org.sonar.process.FileUtils2.deleteDirectory(FileUtils2.java:112)
at org.sonar.application.AppFileSystem$CleanTempDirFileVisitor.visitFile(AppFileSystem.java:117)
at org.sonar.application.AppFileSystem$CleanTempDirFileVisitor.visitFile(AppFileSystem.java:101)
at java.nio.file.Files.walkFileTree(Files.java:2670)
at org.sonar.application.AppFileSystem.createOrCleanTempDirectory(AppFileSystem.java:96)
at org.sonar.application.AppFileSystem.reset(AppFileSystem.java:62)
at org.sonar.application.App.start(App.java:55)
at org.sonar.application.App.main(App.java:78)
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.tanukisoftware.wrapper.WrapperSimpleApp.run(WrapperSimpleApp.java:240)
at java.lang.Thread.run(Thread.java:748)
<-- Wrapper Stopped
【分析結論】
之前因為root賬戶運行導致es失敗。切換到sonar賬戶后,還是失敗,報錯如上。沒有/opt/sonar/temp/conf/es權限?
刪除sonarqube temp目錄重新運行就成功了。
sudo rm -rf temp
2.2.3 配置https域名和反向代理
增加NGINX配置的反代理,以便安全保護。這個步驟不是必選項。
在nginx配置增加sonar的路由,然后把conf/sonar.properties的開放IP“sonar.web.host=0.0.0.0 ”注釋掉關閉。
最終域名:
https://sonar.artarva.com/
配置參考文章《【DevOps實踐】2. 使用NGINX配置Jenkins的https域名訪問》
2.3 登錄
https://sonar.artarva.com/就可以訪問sonarqube主頁了。
3. 參考
(1)Ubuntu 16.04下安裝配置SonarQube+MySQL
https://www.linuxidc.com/Linux/2017-05/143860.htm
【說明】主要參考這個。
(2)sonarqube環境搭建采坑詳解
https://blog.csdn.net/weixin_40686603/article/details/90208627
(3)SonarQube 7.9.x LT安裝
https://blog.csdn.net/u010948569/article/details/111991998
【說明】安裝參考這個,需要JAVA11,無奈放棄。
[1] SonarQube安裝教程與簡單使用(基于Centos7,JDK1.8)
[2] 下載文件列表【最后顯示所有版本】
https://www.sonarqube.org/downloads/
https://docs.sonarqube.org/7.7/requirements/requirements/
【說明】7.7為最后一個支持JDK1.8的版本
[3] 有安裝sonar scanner的幫助
(4)GO語言監測配置
How to run SonarQube for Go code using Jenkins
https://stackoverflow.com/questions/63832311/how-to-run-sonarqube-for-go-code-using-jenkins
https://docs.sonarqube.org/latest/analysis/languages/go/
(5)Jenkins+SonarQube+Gitlab搭建自動化持續代碼掃描質量平臺
https://blog.csdn.net/zuozewei/article/details/84539396
【說明】介紹sonar的作用整體。
(6) SonarQube集成golang檢測
https://blog.csdn.net/baidu_36943075/article/details/90634160
(7)GO項目配置
https://docs.sonarqube.org/latest/analysis/languages/go/
(8) sonarqube SonarGo 搭建和golang代碼檢視的使用教程
http://www.lxweimin.com/p/95ae320aa46d