soanrqube結合jenkins 使用shell腳本掃描java語言,c++語言,ios objectivec語言,js語言以及問題匯總


sonrqube版本6.7.7 

關於jenkins和sonarqube的安裝不在本博客中詳細講解,可參考我的其他博客:

https://www.cnblogs.com/zndxall/p/9336879.html   (jenkins集成soanrqube)

https://www.cnblogs.com/zndxall/p/12095769.html   (linux上sonar的安裝和總結)

soanrqube插件很多在應用市場是下載不了的,同樣給出了下載插件的博客:https://www.cnblogs.com/zndxall/p/13534244.html

這是我使用到的插件以及版本(sonarqube-6.7.7/extensions/plugins下):

 

 另外,如果啟動sonarqube的時候報錯jdbc鏈接失敗,你可以會用到下面這個jar:mysql-connector-java-5.1.42.jar     放 在sonarqube-6.7.7/lib/jdbc/mysql路徑下

由於公司代碼倉比較多,涉及到java,js,go,c++,objectivec,不想一個工程一個工程的配置soanrqube,所以打算寫個腳本,根據傳入參數來掃描涉及到的這些語言:

 

 第二個掃C++的,第三個掃objectivec的,第一個和最后一個掃java,go,js的,如下sonar_Ios的工程如下:

 

 設置了掃描倉庫和分支,以及是要執行掃描(run),還是要獲取掃描結果(result),其他工程的配置是一樣的,區別只是倉庫名。

shell腳本調用如下:

 

 參數1: 是run執行掃描,result是獲取掃描結果 ; 參數2是倉庫名,參數3是掃描語言,參數4是掃描分支

如果不知道掃描語言具體怎么寫,可以使用sonarqube-api查詢喲,命令是:

curl http://服務器ip地址:9000/api/languages/list   比如我的返回如下:

 

 表明我的sonarqube支持掃描的語言有這些,其中的‘key’值就是語言的”字符串“

具體的sonarqube api可以查詢http://服務器ip地址:9000/web_api,或者直接從sonarqube界面最下面點擊跳轉:

 

 

下面詳細介紹各語言的掃描,除了sonarqube的界面配置,其他以下語言掃描描述都寫入了sonar_scan.sh腳本,這樣可以提交入庫,查看修改記錄,不然哪天改了掃不出來都不知道為啥,原來是啥也不記得。

關於sonar-project.properties的內容,我是根據不同工程的配置在shell中使用echo寫入的,不需要一個工程一個sonar-project.properties存起來,麻煩。

1.掃描java語言

效果圖:

 

 

這是最好配置的了,很簡單,只需要設置下掃描語言就可以了,sonar-project.properties如下設置:

sonar.projectKey=sonar_test_java
sonar.projectName=sonar_test_java
sonar.projectVersion=1.0.0
sonar.sourceEncoding=UTF-8
sonar.language=java    #掃描語言
sonar.java.binaries=./
sonar.sources=./     #掃描所有代碼,如果你需要指定目錄的話 換成目錄即可,比如test1

然后在sonar-project.properties的同級目錄下執行sonar-runner即可,稍后就能在sonarqube服務器上看到掃描結果。

2.掃描js語言
效果圖:
sonar.projectKey=sonar_test_js
sonar.projectName=sonar_test_js
sonar.projectVersion=1.0.0
sonar.sourceEncoding=UTF-8
sonar.language=js
sonar.java.binaries=./
sonar.sources=./
很明顯,區別只是把語言換成了js
然后在sonar-project.properties的同級目錄下執行sonar-runner即可,稍后就能在sonarqube服務器上看到掃描結果。
3.掃描go
和上面的java和js是一樣的,把語言換成go就可以了
效果圖:

 

 


4.掃描C/C++
效果圖:

 

 

這個花費了我很久的時間,首先是插件問題,最新的1.3.2插件不要用,不然默認規則數是0,掃不出來,因為我看插件網站上https://github.com/SonarOpenCommunity/sonar-cxx/releases
的解釋是這個版本的插件激活的規則太多了,所以默認規則是關閉的,
需要你自己復制一個版本,然后按照自己的規則,激活你想要的已有的資源庫的規則。如下:

 

點擊“Ensure that a rule is enabled” 

 

 我使用的是1.3.0版本的。

還有一點,我以為我掃描出來的bug和漏洞都是0是因為我插件不兼容導致的,因為我看到了上面的兼容性表,發現只有0.9.5和0.9.1和sonarqube 6.7.*系列兼容,但是使用這兩個版本,
我連sonarqube都起不來了,web.log報錯就是報加載c++插件失敗,詳細的報錯是一個類找不到,我呵呵了,不用這兩個版本,那沒版本了呀,要不我再裝一個7.9TLS的版本的,結果啟動的
時候,告訴我不在支持mysql,O!M!G! 果斷放棄了7.9系列的。接下來就解密下我為什么c++一直掃出來的bug和漏洞都是0吧?可是我單獨執行cppcheck分明bug不為0啊!
是因為我沒有實現執行cppcheck
下面的這一段話提醒了我:

 

 

sonar-project.properties 配置如下:
sonar.projectKey=sonar_test_c
sonar.projectName=sonar_test_c
sonar.projectVersion=1.0.0
sonar.sourceEncoding=UTF-8
sonar.language=c++
sonar.sources=dir1,dir2,dir3  #多個目錄用逗號隔開,比如dir1,dir2,dir3,所有使用./
sonar.cxx.cppcheck.reportPath=cppcheck-result.xml
sonar.cxx.suffixes.sources=cpp
然后在
sonar-project.properties相同目錄下執行如下幾條腳本:

if [ "$scan_lan" == "c++" ];then #掃描C++語言,需要先執行cppcheck 生成報告,然后執行sonar-runner將結果上傳到sonarqube上
      scan_dir="`cat sonar-project.properties | grep sonar.sources |awk -F "=" '{print $2}' | sed 's/,/ /g'`"
      echo scan_dir=$scan_dir
      [ "x$scan_dir" == "x" ] && echo not find sonar.sources && exit 1
      [ -f cppcheck-result.xml ] && echo rm cppcheck-result.xml && rm -f cppcheck-result.xml
      echo cppcheck -q -j 8 --enable=warning --inconclusive --xml --xml-version=2 \"$scan_dir\" #默認是enable=error的,添加其他是追加
      cppcheck -q -j 8 --enable=warning --inconclusive --xml --xml-version=2 \"$scan_dir\" 2> cppcheck-result.xml   #重點是這條,cppchek掃描sonar-           project.properties中配置的sonar.sources指定的目錄
      error_msg="cppcheck: error: could not find or open any of the paths given"
      error_flag=`grep "$error_msg" cppcheck-result.xml`
      [ "x$error_msg" == "x" ] && echo $error_msg && echo cppcheck failed && exit 1
fi

相同目錄下執行sonar-runner將掃描結果cppcheck-result.xm上傳到sonarqube上。

另外sonarqube上關於掃描報告需要配置下:

 

 然后就可以在sonarqube上看到bug不是0的掃描結果了。

5.掃描ios的objectivec 

這個就有點復雜了,不單純是sonar-runner,還要執行編譯,和生成oclint報告

效果圖:

 

 

先看看sonar-project.properties的配置:

sonar.projectKey=sonar_test_objectivec
sonar.projectName=sonar_test_objectivec
sonar.projectVersion=1.0.0
sonar.sourceEncoding=UTF-8
sonar.language=objectivec
sonar.objectivec.project=HPtest.xcodeproj
sonar.objectivec.appScheme=HPOff
sonar.sources=./
sonar.objectivec.oclint.report=oclint.xml
然后在相同目錄下執行:
(1)當是workspace的時候

      xcodebuild clean -workspace "$bscheme".xcworkspace -scheme "$bscheme" -configuration Release
     xcodebuild archive -workspace "$bscheme".xcworkspace -scheme "$bscheme" -archivePath arch/"$bscheme".xcarchive -configuration Release | tee xcodebuild.log | xcpretty -r json-compilation-database --output compile_commands.json

(2)但是project的時候

    xcodebuild clean -project "$bscheme".xcodeproj -scheme "$bscheme" -configuration Release
    xcodebuild build -project "$bscheme".xcodeproj -scheme "$bscheme" -configuration Release | tee xcodebuild.log | xcpretty -r json-compilation-database --output compile_commands.json

以上(1)(2)是兩種不一樣的代碼倉庫結構配置,根據自己的代碼選擇一直即可。$bscheme是你的工程名或者scheme的名字,因為我的都是一樣的,所以我引用了相同的變量。
命令執行結束以后會在當前目錄下生成一個compile_commands.json。
然后相同目錄下執行:

oclint-json-compilation-database -- -max-priority-1 10000 -max-priority-2 10000 -max-priority-3 10000 -extra-arg=-Wno-everything -rc LONG_LINE=150 -report-type pmd -o oclint.xml
要等一段時間,會輸出類似下面的東東:

 

 然后最后會生成一個oclint.xml 的掃描報告文件,如果你想生成html的, 把上面的oclint-json-compilation-database命令后面換成-report-type html就可以了。

再在同一目錄下執行sonar-runner把這個oclint.xml的掃描報告上傳到sonarqube服務器上,此外sonarqube服務器液壓配置objective-c下這個掃描報告的名字,如下:

 

 這樣,就可以掃描objectivec了。

另外,由於我的jenkins采用的是分布式的方式,也就是說用master-slaver的方式,master是centos的,負責執行一部分linux任何和下發任務到各個slave機器上,比如這樣的:

 

 master jenkins 控制了各個slave,可以根據不同的編譯環境下發不同的編譯任務,關於如何配置這種master-slave的jenkins,如果有需要的話,請參考我的另外的博客:https://www.cnblogs.com/zndxall/p/8297356.html

很明顯,這里我們需要處理的是ios、mac的代碼,那么我們執行上面的xcodebuild命令肯定是在上面截圖的“Ios-mac”的mac機器上執行,這就涉及到環境變量的問題了,我們用到的xcpretty,sonar-runner,oclint-json-compilation-database ,要加到環境變量中,然后jenkins調用腳本時要先source下,比如我把他們的環境變量加到了我的~/.bashrc文件中,如下:

 

 olcint-json-compilation-database在bin中,xcpretty在截圖的ruby那個路徑下,還加了sonar-runner到環境變量中,如果你不知道他們在哪,執行which 后解命令,比如which xcpretty 就可以找到他們在哪,一般環境變量只需要到bin層就夠了。

加號以后,在shell腳本中要source下才能生效,即source ~/.bashrc,這段如下:

 

 

這里要說一下為什么掃描出來的bug總是0,只有壞味道,原因如下:

 

 這里的一個bug的規則描述看一下:

 

 掃描出的bug一直是0的原因:代碼規則中只有一個bug的規則,其他都是壞味道,這一個bug還是關於單元測試的,就是說如果你的單元測試沒過,才算觸發了這條規則,如果你都沒有單元測試,那你的掃描結果中bug為0,其他都是壞味道,就說的通了。你可以嘗試激活更多規則來看看會不會有更多關於bug的規則,目前我沒有嘗試。

 

報錯處理:

1.ERROR: Caused by: The rule 'OCLint:compiler warning' does not exist.

解決:加“-extra-arg=-Wno-everything”,如下:

  oclint-json-compilation-database -- -max-priority-1 10000-max-priority-2 10000 -max-priority-3 10000 -extra-arg=-Wno-everything -rc LONG_LINE=150 -report-type pmd -o oclint.xml

2.ERROR: Caused by: The rule 'OCLint:compiler error' does not exist

解決:看描述是這條規則不存在,但是查資料沒查到如何禁用這條規則,也沒查到如何加這條規則,詳細的規則是類似如下這樣的:

 

 rule="compiler error" ruleset="clang",但是他掃描到oclint.xml文件中了,沒辦法,只能刪掉他了,但是看上面的截圖可以,應該把整個<file></file>節點刪掉,而不是只刪除匹配的這一行,因為他關聯了好幾行,如果只刪這一條,依然后sonar-runner失敗,所以我寫了一個函數來專門刪除這個規則,放在oclint-json-comilation-database后,即下面截圖的del_clang

 

 del_clang函數的詳細腳本如下:

function del_clang()
{   
    grep -rn "rule=\"compiler error\"" oclint.xml | awk -F ":" '{print $2}' > clang_lines
    lnsum=`cat clang_lines |wc -l`
     for ((i=1;i<=$lnsum;i++)) #循環次數  
        do
            cls=`grep -rn "rule=\"compiler error\"" oclint.xml | awk -F ":" '{print $2}' |sed -n 1p` #因為刪除過程中行號會變化,所以要動態獲取
            cl1=`expr $cls - 1`  #獲取匹配上的上一行行號
            cl2=`expr $cls + 3` #獲取匹配上的下三行行號
            sed -i "" $cl1,"$cl2"d oclint.xml #刪除匹配行的從上一行到下三行的內容,比如匹配了第3行,那么就使用就刪除第2行到第6行
        done
    clang_flag=`grep "rule=\"compiler error\"" oclint.xml`
    [ "x$clang_flag" != "x" ] && echo also have clang compiler error, this rule not exist && exit 1 #刪除后還要匹配行,表示刪除失敗
    #sed -i "" 3'b\'"<pmd version=\"oclint-0.13\">" oclint.xml #在第三行前插入這個 因為前面的刪除會把這行刪掉(這里在mac上執行一直失敗,所以用下面色sed -n 那幾行代替)
    sed -n 1p oclint.xml > oclint_bak.xml #顯示第一行重定向到新文件
    echo "<pmd version=\"oclint-0.13\">" >> oclint_bak.xml #寫入pmd版本這一行到新文件(如果不加這一行,不僅bug漏洞為0,壞味道也會為0)
    sed -n '3,$p' oclint.xml >> oclint_bak.xml #顯示第三行以及后面全部到新文件中
    rm -f oclint.xml
    mv oclint_bak.xml oclint.xml #重命名新文件
    sed -i "" '/^\s*$/d'  oclint.xml #刪除文件中的空行
}

其中,上面紅色的加粗這行很重要,執行del_clang函數之前,打開oclint.xml你就明白了,

 

 

因為第一個匹配的file行包含了<pmd version="oclint-0.13">,執行首次執行sed -i "" $cl1,"$cl2"d oclint.xml 會把行刪掉,所以后面要追加進去,否則bug,漏洞,壞味道都全部為0.

3.log日志報錯:Caused by: com.mysql.jdbc.PacketTooBigException: Packet for query is too large (4522715 > 4194304). You can change this value on the server by setting the max_allowed_packet' variable.

解決:https://www.cnblogs.com/zndxall/p/13531151.html

 4. The size of BLOB/TEXT data inserted in one transaction is greater than 10% of redo log size. Increase the redo log size using innodb_log_file_size

解決:在/etc/my.cnf中加上(大小根據自己的時間情況調整),添加以后記得重啟數據庫( systemctl restart mysqld),然后記得還要重啟sonarqube(記得不能使用root用戶啟動喲,切換到普通用戶才能啟動成功)

                 max_allowed_packet = 64M

                 innodb_log_file_size=640M

5.oclint: error: Cannot change dictionary into "/Users/xxxx/Classes/Files\(文件\)/Libs/Core/WebSocket.m", please make sure the directory exists and you have permission to access!

解決:這個報錯是因為路徑中含有中文,把路徑中的中文改成英文就可以了。(因為我換了掃描一個英文文件夾就正常了,使用-i 指定)

(oclint-json-compilation-database -i  Classes/AppsModule  -- -max-priority-1 10000 -max-priority-2 10000 -max-priority-3 10000 -extra-arg=-Wno-everything  -rc LONG_LINE=150 -report-type pmd -o oclint.xml    -i 指定要掃描的目錄)

參考:

http://www.uml.org.cn/jchgj/201808103.asp?artid=21046?weiid=2390


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM