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