Jenkins 在 Tomcat 中的部署及代码静态检查工具集成
Jenkins 的簡單部署
在安裝了 Jenkins 運行所需的依賴(主要是 JDK)之后,可以通過如下步驟簡單快速地部署 Jenkins:
下載 Jenkins.
打開終端并切換至下載目錄。
運行命令 java -jar jenkins.war --httpPort=8080。
--httpPort 參數用于指定 Jenkins 服務運行的端口。這條命令將運行 Jenkins 服務。
打開瀏覽器并輸入網址 http://localhost:8080。
URL 中的端口需要與上面運行 Jenkins 時指定的端口一致。在瀏覽器中我們能看到 Jenkins 的頁面了。
按照指示完成安裝過程。
安裝插件,并對 Jenkins 做配置。
Jenkins 在 Tomcat 中的部署
雖然上面的 Jenkins 部署很方便快捷,但是服務管理卻不是很方便。Jenkins 作為一個 Java Web 應用,其 war 包可以非常方便的部署在 Tomcat 容器中。Tomcat 在 Ubuntu 系統中的安裝過程可以參考 Ubuntu 16.04 Tomcat 8安裝指南 一文。
要在 Tomcat 容器中部署 Jenkins,只需將 jenkins.war 復制到 $TOMCAT_HOME/webapps,然后通過 URL http://yourhost/jenkins 訪問即可。
如果 Tomcat 容器中只部署 Jenkins 服務,可以移除 $TOMCAT_HOME/webapps 目錄中的所有內容,然后將 jenkins.war 放進這個目錄中并重命名為 ROOT.war(注意大小寫要保持一致)。Tomcat 將展開這個文件并創建 ROOT 目錄,然后我們應該可以在 http://yourhost 看到 Jenkins,而無需任何額外的路徑(如果采用了 Tomcat 的默認配置,應該是 http://yourhost:8080)
如 Ubuntu 16.04 Tomcat 8安裝指南 一文的介紹,如果為 Tomcat 建立了 systemd 服務文件,可以通過如下命令重啟 Tomcat 服務:
$ sudo systemctl stop tomcat $ sudo systemctl start tomcat并可以通過如下命令查看 Tomcat 的運行狀態:
$ sudo systemctl status tomcat在 Jenkins 服務啟動之前,設置環境變量 JENKINS_HOME 可以指定 Jenkins 服務的主目錄。這可以通過為 Tomcat 的 systemd 服務文件 /etc/systemd/system/tomcat.service 添加如下的行來實現:
Environment=JENKINS_HOME=/opt/tomcat/jenkins_home這行配置在啟動 Tomcat 容器之前,導出環境變量。
更多關于在 Tomcat 中部署 Jenkins 的內容可以參考 Tomcat - Jenkins - Jenkins Wiki。
nginx 反向代理
將 Tomcat 容器作為 Web 服務器不是那么的方便,通過 nginx 做反向代理會好很多。在 Ubuntu 中可以通過如下命令安裝并運行 nginx:
$ sudo apt-get install nginx $ sudo nginx修改 nginx 的配置文件 /etc/nginx/nginx.conf,在 http 塊的最后添加如下幾行為 Jenkins 設置反向代理:
server {listen 80;server_name 59.111.103.32;location / {proxy_pass http://127.0.0.1:8080;proxy_redirect off;proxy_set_header Host $host;proxy_set_header X-Real-IP $remote_addr;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;proxy_set_header X-Forwarded-Proto $scheme;}}隨后,就可以通過 http://yourhost URL,經過 nginx 訪問 Jenkins 服務了。登陸之后,打開 Jenkins 左上角的 Jenkins -> Manage Jenkins -> Configure System Jenkins 全局配置頁面,滾動到 Jenkins Location 的部分,正確配置 Jenkins URL:
Jenkins 作為一個強大的持續集成平臺,其強大之處的重要體現就是,支持許許多多的插件,可以將功能強大的第三方工具集成進來,代碼質量保障相關的工具,比如代碼的靜態檢查工具,是其中比較常用的一些。常用的代碼靜態檢查工具有 PMD,FindBugs,Android Lint,CheckStyle 和 SonarQube Scanner 等。
PMD
PMD 是一個可擴展跨語言的靜態代碼分析器。它查找常見的編程缺陷,如未使用的變量,空 catch 塊,不必要的對象創建,等等。此外它還包含 CPD,復制粘貼探測器。CPD 查找重復代碼。
PMD 掃描 Java 和其它編程語言 的源代碼,并查找像下面這樣的潛在問題:
- 可能的 bugs - 空的 try/catch/finally/switch 聲明
- 死碼 - 未使用的本地變量,參數和私有方法
- 次優代碼 - 無用的 String/StringBuffer 使用
- 過于復雜的表達式 - 不必要的 if 聲明,可能可以寫成 while 的 for 循環
CPD,復制粘貼探測器,查找多種語言的重復代碼:
- 重復代碼常常是由復制粘貼產生的。這意味著,bugs 也被復制粘貼了。修正它們意味著,修正所有重復的代碼。
在正式開始集成 PMD 之前,首先需要通過 Jenkins 左上角的 Jenkins -> Manage Jenkins -> Manage Plugins,在 Jenkins 中安裝 PMD 的插件:
我們通過為 Jenkins Project 添加 Post-build Action 來集成 PMD。打開 Jenkins Project 的主頁,點擊左邊的 Configure 打開工程的配置頁面,找到頁面最下邊的 Post-build Actions,點擊 Add post-build action 的下拉箭頭,并找到 Publish PMD analysis results,添加 PMD post-build action,如下圖:
在 PMD results 輸入框中輸入 PMD 檢查結果文件的路徑,這個結果文件需要我們在構建期間調用 PMD 工具生成。配置了 PMD post-build action 之后,點擊左下角的 Save 按鈕保存退出配置。
使用 PMD 工具生成源代碼的靜態檢查分析報告的方法如下:
$ cd $HOME $ wget https://github.com/pmd/pmd/releases/download/pmd_releases%2F6.2.0/pmd-bin-6.2.0.zip $ unzip pmd-bin-6.2.0.zip $ alias pmd="$HOME/pmd-bin-6.2.0/bin/run.sh pmd" $ pmd -d /usr/src -f xml -r pmd.xml -rulesets java-basic,java-designPMD 工具的 -d 參數用于指定項目的源碼路徑,-f 參數用于指定輸出報告文件的格式,-r 用于指定輸出報告文件的文件名,-rulesets 則用于指定檢查規則集合。這個命令將產生名為 pmd.xml 的 XML 格式的檢查報告,這也是 Jenkins 的 PMD 插件所支持的格式。
在下載并安裝 PMD 工具之后,在 Jenkins 工程的構建腳本中執行 PMD 工具產生檢查報告,如將 PMD 檢查的功能集成進一個用 Python 寫的構建腳本:
def run_pmd(wrapper_module_name, target_module_name):if "PMD_ROOT_PATH" not in os.environ.keys():print("Cannot find PMD")returnpmd_root_path = os.environ["PMD_ROOT_PATH"]pmd_cmd_path = pmd_root_path + os.path.sep + "bin/run.sh"src_dir = wrapper_module_name + os.path.sep + target_module_name + os.path.sep + "src/main/java"pmd_cmd_path = "%s pmd -d %s -f xml -r pmd.xml -rulesets java-basic,java-design" % (pmd_cmd_path, src_dir)print(pmd_cmd_path)os.system(pmd_cmd_path)Jenkins 工程在構建結束之后,將根據配置的 PMD results 路徑查找 PMD 檢查的結果,并將結果展示在 Jenkins 工程的主頁面上,如下圖所示:
點擊 PMD Trend 將可以看到 PMD 檢查的詳細結果,如下圖:
關于 PMD 工具用法更詳細的內容,可以參考它的 主頁 和 官方文檔。
FindBugs
FindBugs 是另一個強大的靜態代碼檢查工具,它主要用于查找 Java 代碼 中的 bugs,它查找 正確性 bugs,糟糕的做法及 Dodgy 等問題。
與在 Jenkins 中集成 PMD 類似,同樣需要先在 Jenkins 中為 FindBugs 安裝插件:
然后配置 Jenkins 工程,添加 post-build action Publish FindBugs analysis results,如下圖:
FindBugs results 輸入框中需要輸入 FindBugs 工具代碼檢查的結果文件。Jenkins 將在構建結束之后,掃描這個文件,并在頁面中展示出來。
在 Jenkins 工程的構建階段,需要調用 FindBugs 工具生成檢查報告,方法如下:
$ cd $HOME $ wget https://jaist.dl.sourceforge.net/project/findbugs/findbugs/3.0.1/findbugs-3.0.1.tar.gz $ tar xvf findbugs-3.0.1.tar.gz $ findbugs-3.0.1/bin/findbugs -textui -low -xml -output findbugs.xml module/build/intermediates/bundles/debug/classes.jarFindBugs 提供了兩種用戶界面,分別是 GUI 和命令行用戶界面,在 Jenkins 的構建腳本中,我們以命令行界面執行 findbugs,這通過 -textui 參數來指定。-low 參數用于指明希望輸出所有類型的問題,-xml 參數用于指定生成的檢查報告的文件格式,-output 參數指明輸出文件名,最后是模塊編譯生成的 class jar 文件。
在 Jenkins 服務器上下載安裝了 FindBugs 工具之后,集成代碼檢查過程進 Python 構建腳本的方法大體如下:
def run_findbugs(wrapper_module_name, target_module_name):if "FIND_BUGS_ROOT_PATH" not in os.environ.keys():print("Cannot find findbugs")returnfindbugs_root_path = os.environ["FIND_BUGS_ROOT_PATH"]findbugs_cmd_path = findbugs_root_path + os.path.sep + "bin/findbugs"class_file_path = wrapper_module_name + os.path.sep + target_module_name + os.path.sep + "build/intermediates/bundles/debug/classes.jar"findbugs_cmd_path = "%s -textui -low -xml -output findbugs.xml %s" % (findbugs_cmd_path, class_file_path)print(findbugs_cmd_path)os.system(findbugs_cmd_path)在 Jenkins 的構建任務結束之后,它掃描 FindBugs 的檢查結果,并展示出來:
點進去可以查看更詳細的找到的問題:
關于 FindBugs 更詳細的內容,可以參考其主頁和文檔。
總結一下 PMD、FindBugs 集成進 Jenkins 的流程:
- 全局 Jenkins 配置方面,為相應的代碼靜態檢查工具安裝插件。
- 在 Jenkins 工程配置中,為相應的代碼靜態檢查工具添加 post-build action,配置檢查結果文件的存放路徑。
- 為 Jenkins 服務器下載并安裝代碼靜態檢查工具。
- 在 Jenkins 工程的構建腳本中,調用代碼檢查工具生成檢查報告文件。
其它的代碼靜態檢查工具集成進 Jenkins 的過程與此類似,如 Checkstyle 和 Android Lint。
Checkstyle
Checkstyle 是一個幫助程序員編寫符合某一編碼規范的 Java 代碼 的開發工具。為它提供編碼規范的定義文件和源代碼,它自動檢查源代碼中不符合規范的地方。編碼規范的定義文件可以自行配置,比較常用的 Java 代碼編碼規范如 Sun 代碼規范 和 Google Java 代碼規范。
在 Jenkins 中集成 Checkstyle 的整體過程與集成 PMD 和 FindBugs 的過程類似。需要為 Checkstyle 安裝的插件為 Checkstyle Plug-in,需要為 Jenkins 工程添加的 post-build action 為 Publish Checkstyle analysis results。下載并安裝 Checkstyle 工具的方法如下:
$ wget https://excellmedia.dl.sourceforge.net/project/checkstyle/checkstyle/8.8/checkstyle-8.8-bin.tar.gz $ tar xvf checkstyle-8.8-bin.tar.gz此外還需要自己定義或下載公開的代碼風格定義文件,如 Sun 代碼規范 sun_checks.xml 和 Google Java 代碼規范 google_checks.xml
執行 Checkstyle 工具生成檢查報告的方法如下:
$ java -jar checkstyle-8.8/checkstyle-8.8-all.jar com.puppycrawl.tools.checkstyle.Main -c checkstyle_config/google_checks.xml module/src/main/java -f xml -o checkstyle-result.xmlCheckstyle 工具的 -c 參數用于指定代碼風格的定義文件,-f 參數用于指定用于指定輸出檢查報告文加的格式,-o 參數用于指定輸出報告文件的文件名,同時需要為 Checkstyle 指定項目的 Java 源代碼路徑。上面的命令中 Checkstyle 將輸出文件名為 checkstyle-result.xml 格式為 xml 的檢查報告。
將 Checkstyle 工具集成進 Python 的工程構建腳本的方法如下:
def run_checkstyle(wrapper_module_name, target_module_name):if "CHECKSTYLE_ROOT_PATH" not in os.environ.keys():print("Cannot find Checkstyle")returnjar_path = os.environ["CHECKSTYLE_ROOT_PATH"] + os.path.sep + "checkstyle-8.8-all.jar"checkstyle_cmd = "java -jar " + jar_path + " com.puppycrawl.tools.checkstyle.Main"script_path = __file__config_file_path = os.path.dirname(script_path) + os.path.sep + "checkstyle_config/google_checks.xml"checkstyle_cmd = checkstyle_cmd + " -c " + config_file_pathsrc_dir = " " + wrapper_module_name + os.path.sep + target_module_name + os.path.sep + "src/main/java"checkstyle_cmd = checkstyle_cmd + src_dir + " -f xml -o checkstyle-result.xml"print(checkstyle_cmd)os.system(checkstyle_cmd)Jenkins 在工程構建結束之后,掃描 Checkstyle 的檢查報告,并展示出來:
Checkstyle 更詳細的用法可以參考其主頁 和它的 命令行用法說明文檔。
Android Lint
將 Android Lint 集成進 Jenkins 的過程,與前面的那些 PMD、FindBugs 和 Checkstyle 的過程類似,只是需要安裝的 Jenkins 插件為 Android Lint Plugin,需要為 Jenkins 工程添加的 post-build action 為 Publish Android Lint results。
更為簡單的是,Android Lint 是 Android Sdk 中的工具,因而無需單獨下載安裝。對于 Gradle 工程而言,甚至無需單獨運行 Android lint 工具,而只需運行 lintDebug 或 lintRelease gradle 任務即可,它們將在模塊的 build/reports/lint-results*.xml 處生成 檢查報告。
在 Python 的 Jenkins 工程構建腳本中生成 Android Lint 檢查報告的方法如下:
def run_android_lint(target_module_name):lint_task_name = ":%s:lintDebug" % target_module_nameos.system("./gradlew " + lint_task_name)Android Lint 的檢查結果類似于下面這樣:
SonaQube Scanner
SonaQube 是一個開源的代碼質量分析管理平臺,它專注于持續地分析和測量技術方面的質量,從項目組合到方法。通過插件,它可以支持包括 Java,C#,C/C++,PL/SQL,Cobol,JavaScrip,Groovy 等在內的 20 多種編程語言 的代碼質量檢測與管理。
SonaQube 對代碼質量的管理通過 Web 服務 SonaQube 提供,代碼質量檢測通過 SonaQube Scanner 完成。通常的流程是,SonaQube Scanner 執行代碼的靜態檢查分析,然后將檢查的結果傳給 SonaQube 服務,SonaQube 服務解析并展示分析結果。
SonaQube Scanner 可以集成進 MSBuild,Maven,Gradle,Ant 等構建系統中,當然也可以集成進 Jenkins 或在命令行上運行。
安裝 SonaQube 服務
在 Jenkins 中集成 SonaQube Scanner,分析結果依然需要由 SonaQube 服務來解析與展示,因而首先需要安裝 SonaQube 服務。在 SonarQube 的下載頁面 選擇需要的版本并下載,如 SonarQube 6.7.2 (LTS *) 。
下載完成后,執行如下命令安裝并啟動 SonaQube 服務:
$ unzip sonarqube-6.7.2.zip $ sonarqube-6.7.2/bin/linux-x86-64/sonar.sh startSonarQube 自帶數據庫和 Web 服務器,因而通過上面簡單的兩條命令,就可以將 SonaQube 服務運行起來了。默認情況下,SonaQube 服務運行于 9000 端口上:
但需要注意不能以 root 用戶啟動 SonaQube 服務,否則將啟動失敗。通過 sonarqube-6.7.2/logs/ 目錄下的 ElasticSearch 日志文件 es.log 和 SonaQube 日志文件 sonar.log 可以看到這一點。為了獲得更好的性能和穩定性,可以使用外部的數據庫服務, SonaQube 服務對此提供了良好的支持。關于 SonaQube 服務安裝配置更詳細的過程,可以參考 SonaQube 的官方文檔 Installing the Server。
命令行運行 SonaQube Scanner
SonaQube Scanner 可以集成進 MSBuild,Maven,Gradle,Ant 及 Jenkins 等工具中,也可以在命令上獨立運行。首先下載并安裝 SonaQube Scanner:
$ wget https://sonarsource.bintray.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-3.1.0.1141-linux.zip $ unzip sonar-scanner-cli-3.1.0.1141-linux.zip然后為要檢查的工程編寫屬性配置文件 sonar-project.properties,如:
java-module.sonar.projectName=Java Module java-module.sonar.language=java # .表示projectBaseDir指定的目錄 java-module.sonar.sources=study-project/lib-module-question/src/main/java java-module.sonar.projectBaseDir=study-project/lib-module-question sonar.binaries=classes sonar.projectKey=study-project sonar.sources=study-project/lib-module-question/src/main/java sonar.java.binaries=study-project/lib-module-question/build/intermediates/bundles/debug/classes.jar上面的配置中,sonar.projectKey 用于指定工程名稱,工程名稱標識一個工程,SonaQube Scanner 在檢查結束之后向 SonaQube 服務發布檢查結果,SonaQube 服務以工程為單位展示檢查結果。sonar.sources 用于指定要檢查的源碼的路徑。sonar.java.binaries 用于指定編譯生成的 jar 文件的路徑。
在命令行中,在 sonar-project.properties 文件的相同目錄下,執行如下命令:
$ sonar-scanner-3.1.0.1141-linux/bin/sonar-scanner它將根據 sonar-project.properties 配置文件的內容靜態分析源碼,并將結果發布給 SonaQube 服務。默認情況下,分析結果將發布給位于 http://localhost:9000 的 SonaQube 服務。但可以通過如下配置項來進行定制:
sonar.host.url=http://localhost:9000 sonar.login=apitoken/username sonar.password=blank/passwd關于 SonaQube Scanner 執行、配置更詳細的信息,可以參考官方文檔 Analyzing with SonarQube Scanner、Advanced SonarQube Scanner Usages
和 Analysis Parameters。
在 Jenkins 中集成 SonaQube Scanner
同樣需要先為 SonaQube Scanner 安裝插件,這次為 SonarQube Scanner for Jenkins。然后以管理員身份登錄 Jenkins,并進入 Manage Jenkins > Configure System。向下滾動到 SonarQube configuration 的部分,點擊 Add SonarQube,然后按提示輸入對應的值,如下圖這樣:
其中 Name 一欄輸入 SonaQube 的名稱,名稱任意取。Server URL 一欄輸入 SonaQube 服務的 Url。Server authentication token 輸入用戶認證 token,這個 token 是由 SonaQube 服務生成的。
登錄 SonaQube 服務(如第一次以 admin(用戶名)/admin(密碼)登錄 SonaQube 服務)之后,點擊右上角的用戶圖標,選擇 My Account,打開賬戶主頁,并選擇 Security:
在 Generate New Token: 輸入框中輸入 token 名稱,token 名稱可任意選擇,然后點擊 Generate 生成 token。如 SonaQube 服務給出的提示,生成的 token 需要復制出去,這個 token 將無法被再次看到。這個 token 即是前面需要提供給 Jenkins 的 Server authentication token。
然后執行 Jenkins 全局的一些配置,具體而言,是添加 SonarQube Scanner:
最后是 Jenkins 工程的配置:
然后點擊左下角的 Save,保存并結束配置。后面在執行 Jenkins Project 的構建任務時,SonarQube Scanner 將執行,生成分析報告并發送給 SonaQube 服務,報告有 SonaQube 解析并展示。更多內容請參考 Analyzing with SonarQube Scanner for Jenkins。
參考文檔
Getting started with the Guided Tour
Tomcat - Jenkins - Jenkins Wiki
Analyzing with SonarQube Scanner for Jenkins
使用 Jenkins 與 Sonar 集成對代碼進行持續檢測
SonarQube代碼質量管理平臺安裝與使用
Analyzing Source Code
Dong.
總結
以上是生活随笔為你收集整理的Jenkins 在 Tomcat 中的部署及代码静态检查工具集成的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: GitLab 自动触发 Jenkins
- 下一篇: 为 Android 编译 MuPDF 查