简介:sonarqube-7.9.zip是SonarQube 7.9版本的完整服务端部署包,面向需要搭建代码质量管理平台的开发团队、运维人员及技术管理者。该版本在软件质量分析上带来性能提升、新的分析规则以及更多语言与框架支持,可持续扫描漏洞、代码异味和编码规范问题,帮助团队在早期发现潜在缺陷。压缩包约196.67MB,当前文件总数与类型明细暂缺,但解压后目录结构清晰:bin存放跨平台启停脚本,conf管理数据库与端口等核心参数,extensions用于扩展多语言插件与分析规则,lib提供运行依赖,web承载浏览器交互界面,data保存项目度量数据,内置Elasticsearch支持快速检索,logs负责记录运行日志,另含COPYING许可证说明。已有472人浏览/学习,适合用来学习SonarQube环境搭建、规则配置与质量门禁实践,也可作为生产环境升级前的本地验证包,或用于持续集成管道中的代码质量检查。
1. sonarqube 7.9 到底是什么:从一次失败的代码审计说起
先讲一个场景:你刚接手一个跑了两年的 Java 后端服务,代码量八万行,线上偶发报错,但团队没人说得清根因。你打开项目仓库,翻了两天,唯一能确认的是——至少有三个同事在同一个方法里各写了一套空指针防御。这时候你需要的不是 code review,是一次能覆盖全量代码、能按严重级别排序、能告诉你「问题在哪个文件哪一行」的自动审计。SonarQube 7.9 就是干这个的。它是 SonarQube 在 2019 年发布的长周期支持版本(LTS),也是社区版里最后一代能以较低资源成本跑起来、支持传统数据库直连、对私有化部署最友好的版本。本文只讲一件事情:怎么把 7.9 落地成团队真正在用的质量检查工具,而不是装完看一眼就扔掉的摆设。适合刚接触 sonarqube 的中小团队、需要支持老项目的运维,以及所有想给代码库上量尺的人。
2. 安装与初始化:把 sonarqube 7.9 跑起来的三条路线对比
2.1 为什么 7.9 到今天还值得装
SonarQube 7.9 是很多团队刻意留在老版本上的原因,不是懒,是边界清楚。它的软件栈要求非常传统:JDK 8、MySQL 5.6/5.7、内存给 2GB 就能稳定跑,不像 8.x 以后强制要 JDK 11、9.x 以后数据库选择大幅收窄。对还在用 JDK 8 的老项目来说,sonarqube 7.9 的扫描器可以直接在构建机上跑,不需要额外装新版 JDK。另一个实际好处是 7.9 的社区版没有功能裁剪过狠,代码异味、重复度、单测覆盖率这些核心能力都是开箱即用的。团队如果现阶段只是想「先扫起来」,7.9 的投入产出比极好。
我一般会根据团队基础设施选路线:机器上装的是 OpenJDK,就直接下载官方 zip 包手动部署;如果公司已经有 Kubernetes 或 Docker Compose 的习惯,就走镜像;除非你要改 SonarQube 源码做二次开发,否则不碰源码编译那条路,耗时且没有收益。下面把这三条线的关键差别列一张表。
| 路线 | 部署耗时 | 维护成本 | 适合场景 |
|---|---|---|---|
| 官方 zip 手动部署 | 半小时 | 中 | 内网服务器,已存在 JDK8 |
| Docker Compose | 十分钟 | 低 | 本地试验、CI 环境、团队统一镜像 |
| 源码编译 | 半天以上 | 高 | 二次开发,普通团队不建议 |
2.2 先用 Docker 把 sonarqube 7.9 本地跑起来
最常见、最快的起点是 Docker 单节点。因为 7.9 的镜像官方还在维护,拉取后只要把数据目录挂出来就能用。下面这套是我常用的最小启动方式,适用 Linux 和 macOS。
# 创建数据、日志、插件三个持久化目录 mkdir -p /opt/sonarqube/data mkdir -p /opt/sonarqube/logs mkdir -p /opt/sonarqube/extensions # 启动 7.9 版本容器,宿主机映射 9000 端口 docker run -d \ --name sonarqube-7.9 \ -p 9000:9000 \ -e SONARQUBE_JDBC_USERNAME=sonar \ -e SONARQUBE_JDBC_PASSWORD=sonar \ -e SONARQUBE_JDBC_URL="jdbc:postgresql://你的数据库IP:5432/sonar" \ -v /opt/sonarqube/data:/opt/sonarqube/data \ -v /opt/sonarqube/logs:/opt/sonarqube/logs \ -v /opt/sonarqube/extensions:/opt/sonarqube/extensions \ sonarqube:7.9-community这段命令里有三个值得说清楚的参数。SONARQUBE_JDBC_URL是指向外部数据库的 JDBC 连接串,7.9 内置了 PostgreSQL 驱动,但如果你要用 MySQL 需要另外放驱动包到/opt/sonarqube/extensions下,这一步很多人漏掉,容器起来后日志里报找不到驱动。-v挂载的三个目录必须挂全,否则容器重建后规则、插件、历史数据全会丢。sonarqube:7.9-community这个 tag 就是 LTS 对应的社区版镜像,不要拉成latest,否则镜像内容是 9.x/10.x,配置思路完全不同。
启动后等一两分钟,访问http://服务器IP:9000,初始账号密码是admin/admin,首次登录后系统会强制让你改密码。如果页面迟迟打不开,先看容器日志,最常见的翻车点集中在数据库连不上和目录权限不对——容器内进程是以sonar用户运行的,挂载目录宿主机权限如果不是 777 或sonar:sonar,启动会静默失败。
2.3 传统 zip 包部署:内网环境的稳妥选择
Docker 在离线内网环境下经常不现实,很多公司服务器不让你拉镜像。这时候走官方 zip 包是更稳的路。先把 7.9 的安装包下载到服务器,解压后需要手工调整两个配置。
# 解压到 /opt 下 unzip sonarqube-7.9.zip -d /opt mv /opt/sonarqube-7.9 /opt/sonarqube # 编辑 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 sonar.web.javaAdditionalOpts=-server注意characterEncoding=utf8这行不是可选项。MySQL 如果默认字符集不是 utf8,扫描结果里的中文字符会全部乱码,规则名、项目名、问题描述全是问号。rewriteBatchedStatements=true是 7.9 在 MySQL 下写入性能的关键参数,不加它,首次扫描大批量数据插入时速度会慢到让人怀疑机器坏了。配好后用bin/linux-x86-64/sonar.sh start启动,日志在logs/sonar.log,看到SonarQube is up才算成功。
2.4 初始化配置:内存、系统参数和第一个管理员
不管你用哪条路线部署,7.9 启动前都要调两个底层参数,否则 Elasticsearch 内嵌实例起不来。第一个是vm.max_map_count,这是 Linux 内核参数,Elasticsearch 需要的内存映射区域默认值太低,启动报错信息会直接提示你。
sudo sysctl -w vm.max_map_count=262144 echo "vm.max_map_count=262144" >> /etc/sysctl.conf第二个是堆内存。7.9 默认给 Elasticsearch 分配 1GB,给 Web 服务分配 1GB,如果机器只有 2GB 内存,跑起来会非常勉强。进入conf/sonar.properties,把sonar.web.javaOpts里的-Xmx调成-Xmx1024m,把sonar.ce.javaOpts调成-Xmx1024m,尽量减少同时启动的计算任务。如果机器是 4GB 内存,可以把 Web 服务的Xmx设到 2GB,扫描大项目时 Web 服务卡顿会少很多。
初始化完成后,进 Web 界面把默认密码改掉,然后创建两个东西:一个全局令牌(Token),用于后续扫描器认证;一个质量配置,建议复制 SonarQube 自带规则集再自定义调整,这样不会污染原始规则。网上搜索 sonarqube 时你大概率会看到各种推荐规则包,但 7.9 的规则引擎没有后来的热更新能力,一次启用太多规则会导致扫描时间暴涨,我后面会详细讲怎么取舍。
3. 扫描与分析:用 sonarqube 7.9 跑通第一个项目的完整命令
3.1 准备好扫描器:sonar-scanner 和 JDK 的关系
SonarQube 服务端架好之后,你还需要一个客户端用来分析代码。7.9 对应的扫描器版本建议用 sonar-scanner-cli 的 4.x 版本,因为这个版本可以跑在 JDK 8 上,和 7.9 服务端兼容。下载后解压,把bin目录加进 PATH,或者直接用它里面的sonar-scanner脚本。注意一点:7.9 对扫描器版本有隐含要求,如果拿新版扫描器(比如 6.x)去扫 7.9 服务端,经常报协议不支持,所以扫描器的版本和服务端版本最好成对维护。
先验证一下扫描器能不能用:
sonar-scanner -v如果提示找不到 Java,说明当前 shell 里的JAVA_HOME不是 8。用export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64切到 JDK 8 再跑,否则后面扫描阶段会报UnsupportedClassVersionError。这里容易踩坑:很多开发机默认 JDK 是 11 或 17,7.9 不是完全不能用,但各类字节码解析插件的行为会和 JDK 8 下不一样,遇到诡异的分析失败时先查 JDK 版本。
3.2 写一份最小的 sonar-project.properties
在项目根目录创建一个配置文件,告诉 sonarqube 要分析什么、源码在哪、用什么语言规则。下面是我常用的模板,适用于 Java + Maven 项目。
# 项目唯一标识,同一个项目在后续扫描中必须保持一致 sonar.projectKey=my-service # 项目名称,展示在 SonarQube 界面上 sonar.projectName=my-service # 项目版本号,建议直接用代码版本 sonar.projectVersion=1.0.0 # 源码目录,相对于当前配置文件的路径 sonar.sources=src/main/java # 测试代码目录 sonar.tests=src/test/java # Java 字节码目录,用来做精确的跨文件数据流分析 sonar.java.binaries=target/classes # 输出编码,统一 UTF-8 防止中文注释乱码 sonar.sourceEncoding=UTF-8这段配置文件里最容易被忽略的是sonar.java.binaries。很多人只写了sonar.sources就开扫,结果 sonarqube 只能做文本层面的检查,像空指针、资源未关闭这种需要字节码分析的规则一条都不会执行,扫出来的问题数可能只有完整扫描的二分之一不到。这个参数指向 Maven 编译后的target/classes目录,所以扫描前必须保证项目已经编译过。如果项目用了 Lombok,还需要确保target/classes里能看到生成的 getter/setter 字节码,否则数据流分析会把 Lombok 注解的字段当成未使用。
3.3 执行扫描:命令行模式与日志解读
配置写完后,直接在项目根目录执行扫描命令,用上一步创建好的令牌做认证。
sonar-scanner \ -Dsonar.host.url=http://你的服务器IP:9000 \ -Dsonar.login=你的令牌执行过程会输出很多日志,新手看到满屏的INFO容易慌。其实只需要盯三类信息。第一类是SonarQube server相关,确认它连到了正确的服务端。第二类是Sensor列表,7.9 对 Java 项目会跑JavaSensors、SurefireSensor等,如果这里没有出现 Java 相关传感器,说明sonar.java.binaries没配好,后续结果会缺一半规则。第三类是最后的执行统计:
INFO: Analysis total time: 12.345 s INFO: EXECUTION SUCCESS出现EXECUTION SUCCESS只是代表扫描流程完成了,不代表代码质量好。扫描结果异步写入数据库,等几秒后打开 Web 界面,进入项目页面就能看到 BUG 数、漏洞数、代码异味、覆盖率、重复度五项指标。7.9 的界面风格和后来版本不一样,左侧是项目列表,点进去直接看概览,没有后来那些花哨的标签页,反而更适合团队快速聚焦问题。
3.4 覆盖率数据怎么进 7.9
覆盖率是 sonarqube 分析结果里最容易被误解的一项。默认扫描不会自动收集覆盖率,你必须把测试框架生成的报告路径告诉扫描器。以 JaCoCo 为例,首先在 Mavenpom.xml里配置jacoco-maven-plugin的prepare-agent目标,然后在sonar-project.properties里加一行:
sonar.jacoco.reportPaths=target/jacoco.exec需要注意 7.9 对 JaCoCo 版本有限制,用太新的 JaCoCo(0.8.7 以上)生成的.exec文件它解析不了,扫描日志会报Unsupported version。常见做法是锁在 0.8.5 左右,既能配合 JDK8 编译的代码,又和 7.9 的分析器兼容。这一步是网上搜 sonarqube 时最容易搜到却没人提醒的版本兼容性问题。
4. 质量门禁与规则集:让 sonarqube 7.9 在 CI 里真正卡住问题
4.1 质量门禁的默认配置和阈值决策
扫描结果如果只是躺在 Web 页面上,半个月后没人再看,这工具就白装了。质量门禁(Quality Gate)就是让 sonarqube 发挥强制作用的那道闸。7.9 自带一个默认门禁,包含四类硬指标:新增代码的 BUG 数为 0、新增代码的漏洞数为 0、新增代码的代码异味不高于阈值、新增覆盖率不低于阈值(默认 80%)。
这里先说一个常见误判:默认门禁里的覆盖率 80% 是针对「新增代码」而不是全量代码。很多第一次用 sonarqube 的团队看到整体覆盖率只有 30%,但门禁仍然是绿色,就是因为没理解这个看板逻辑。7.9 的指标卡得是每次扫描与上一次相比「新增部分」的质量,不是历史包袱。这个设计很合理,老代码不可能一夜之间全覆盖,但新代码必须达标。
产品团队如果觉得默认 80% 太严,可以先放宽到 60% 跑两周,看历史数据再收紧。门禁阈值可以在项目的Quality Gate设置里改,也可以定义一个全局门禁应用到所有项目。我建议一个团队只维护一套全局门禁,项目多了之后逐项目调阈值是灾难——你会发现每个项目都在为自己的低标准找借口。
4.2 把质量门禁接到 CI:一个最小可用的 Jenkins 配置
门禁不是 Web 页面上那个绿色气泡,而是要嵌到流水线里阻塞合入。以 Jenkins 为例,常见做法是在构建阶段最后调 SonarQube 的 API 拿门禁结果。7.9 提供sonar.qualitygate相关的参数,但更稳妥的方式是用 Web API 判断。
# 等异步分析任务结束,轮询 task 状态 SONAR_TOKEN=你的令牌 TASK_ID=$(curl -s -u $SONAR_TOKEN: "http://你的服务器IP:9000/api/ce/task?id=任务ID" | jq -r '.task.id') # 获取项目状态,如果 quality gate 失败,退出码非 0,流水线会红 STATUS=$(curl -s -u $SONAR_TOKEN: "http://你的服务器IP:9000/api/qualitygates/project_status?projectKey=my-service" | jq -r '.projectStatus.status') if [ "$STATUS" = "ERROR" ]; then echo "Quality Gate 未通过,构建失败" exit 1 fi这段脚本里有几个关键点。/api/ce/task接口返回的是异步分析任务的状态,SUCCESS才代表扫描真正完成。/api/qualitygates/project_status返回OK或ERROR,ERROR就是门禁没通过,脚本通过exit 1让 Jenkins 构建失败,从而阻止代码合入。注意 7.9 的 API 路径和 8.x 之后不完全一致,如果直接从网上抄新版脚本会 404,这是版本差异的重灾区。
如果你用的是 GitLab CI,思路一样,只是把 curl 换成sonar-scanner之后的sonar.qualitygate.wait=true参数,扫描器会一直等到分析完成并返回门禁结果,然后直接以非零退出码中断流水线。这个参数在 7.9 里存在,但需要配合sonar.host.url使用,否则扫描器不知道去哪轮询结果。
4.3 规则集:按项目类型裁剪,不盲目开全量
7.9 自带很多规则集,Java 项目默认启用的是 Sonar Way(Java Profile),里面约 300 条规则。很多人拿到 sonarqube 之后的第一反应是把所有规则都打开,追求「问题数越少越安全」,这是性价比最低的做法。规则多了扫描时间线性上涨,误报也成倍增加,团队每天在真假问题之间扯皮,最后门禁被投诉成形式主义。
我一般会在内置的 Sonar Way 基础上做四步裁剪。第一步,把对当前项目不适用的规则置为关闭,比如项目不用 Spring,就关掉 Spring 相关注解检查。第二步,把误报率高的规则调到INFO级别而不是MAJOR,这样报但不会阻塞门禁。第三步,新项目试点一周,收集误报清单,集中调整一次。第四步,把调好的规则导出为 XML 存在仓库里,作为团队规范的一部分。7.9 支持在 Web 界面的Quality Profiles里做这些操作,不需要改配置文件,但导出的 XML 要放进版本库,不然换一台部署服务器就全丢了。
切换到自定义规则集的地方在Quality Profiles页面,把项目关联的 Profile 从默认改成你复制出来的那一份,改完后要重新跑一次扫描,门禁才会用新规则集计算。这里又一个常见坑:改了规则集但没重扫,门禁结果仍然基于旧的规则集,页面显示和实际情况不一致,容易让团队误以为规则集没生效。
5. 升级与排坑:sonarqube 7.9 的边界、参数与常见问题排查
5.1 插件为什么突然装不上:时区之外的更新源问题
现象:在 7.9 的 Administration > Marketplace 页面搜插件,转圈很久后提示Failed to fetch,或者干脆什么都不显示。
原因:7.9 时代的插件市场默认指向 SonarSource 的更新源地址,这个地址在 2021 年左右被官方切换到新域名。老版本固化的 URL 已经访问不了,自然拉不到插件列表。
解决:不要试图在 7.9 的界面里联网装插件了,直接去插件仓库下载对应 7.9 版本的 jar 包,手动扔到/opt/sonarqube/extensions/plugins目录,重启 SonarQube。注意插件版本必须明确标注兼容 SonarQube 7.9,用新插件版本大概率启动失败,日志会报Plugin ... requires SonarQube 9.9之类的不兼容错误。这是 7.9 用户最头疼的一个点,也是很多团队最终放弃 7.9 的原因之一——维护老版本意味着插件生态也要跟着停在旧时代。
5.2 扫描输出全是问号:中文字符集与 MySQL 的老账
现象:扫描 Java 代码后,SonarQube Web 页面上中文注释、中文规则说明全部乱码,问题描述变成??????。
原因:MySQL 数据库或表字符集不是utf8mb4。SonarQube 服务端默认用 UTF-8 读写数据库,但 MySQL 的utf8实际上是 3 字节编码,存 emoji 或生僻字会被截断成乱码;如果库是latin1,那连中文都存不了。
解决:在部署 sonarqube 之前就要把数据库建好,下面的建库语句在 7.9 上是最稳妥的:
CREATE DATABASE sonar CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;如果库已经建好了但表还是旧的,先ALTER DATABASE sonar CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;,再把所有表转换一遍。注意 7.9 的数据库迁移脚本不会自动改字符集,所以这个操作必须在正式扫描前完成,否则存量乱码数据只能删库重来。
5.3 容器一启动就退出:挂载目录权限是隐形杀手
现象:Docker 方式启动后几秒内容器退出,docker logs显示大量Permission denied或Can not write to ...。
原因:宿主机挂载的目录所有权是 root,而容器内 SonarQube 进程以sonar用户运行,没有写权限。
解决:把挂载目录所有者改成容器内的 UID。7.9 镜像里sonar用户的 UID 是 1000,执行chown -R 1000:1000 /opt/sonarqube再重启容器。如果刚启动过一次已经生成了 root 属主的文件,把它一起chown掉。
5.4 扫描耗时爆炸:先查这两处再怀疑机器性能
现象:项目扫描从十分钟变成四十分钟,甚至EXECUTION SUCCESS但 UI 上任务一直显示进行中。
原因之一:7.9 内置的 Elasticsearch 接收分析结果时,如果堆内存不足会频繁 GC,拖慢整个队列。原因之二:规则集开得太猛,特别是开启了跨文件的规则(例如javax.annotation相关检查),分析复杂度从 O(n) 变成 O(n*m)。
解决:先看服务端日志/opt/sonarqube/logs/ce.log,搜OutOfMemory或GC overhead关键字。有的话调大sonar.ce.javaOpts的-Xmx;没有的话检查规则集,把跨文件规则关掉。还有一个容易被忽略的点:7.9 的sonar-scanner里如果设置了sonar.sourceEncoding=UTF-8但没有设置sonar.java.binaries,会触发字节码猜测逻辑,速度慢且结果不准,这是常见配置误用。
5.5 升级 8.x 前必须做的事:数据备份与插件兼容性预检
现象:有人直接从 7.9 跳到 8.9 LTS,重启后 Web 服务起不来,日志里一堆Plugin相关的UnsupportedOperationException。
原因:7.9 和 8.9 之间的插件 API 变了,大量老插件不兼容,SQS 自己的内置插件也要同步升级。更严重的是数据库 schema 从 7.9 升到 8.9 是一次性不可逆操作,一旦升坏,7.9 的老版本程序再连这个库也起不来。
解决:动手升级前必做三件事——第一,用bin/<platform>/sonar.sh stop停服务后备份整个数据目录和数据库;第二,把extensions/plugins目录下的老插件全部移到备份目录,只保留官方插件;第三,按官方升级路径逐级走,7.9 先升到最新 7.9.x 补丁,再升 8.x 的过渡版本,最后到 8.9 LTS,不要跨大版本跳。没有备份就升级,遇到兼容性问题时你连后悔药都没有。
6. 从 7.9 起步的长期主义:迁移到新版本,还是留在 LTS?
如果你已经按照前面的步骤把 sonarqube 7.9 跑起来,并且稳定运行了一两个月,接下来最纠结的问题通常是:要不要追新版本。我的建议是先别急着升。7.9 这种老 LTS 在工具链里扮演的是「稳定质检台」角色——只要你的项目还在 JDK 8 上、插件需求不旺盛、团队没有强诉求要用新版 API,留在 7.9 完全可行。我见过太多团队把 sonarqube 当玩具,每出一个大版本就升一次,结果升级周报占了整个迭代的三分之一,真正的代码质量反而没人关心。
如果确实要升,可以按我的经验设计一条低风险路径。先在另一台机器把 7.9 的最新补丁版部署起来,导入一次生产数据快照,然后开始做升级演练。每次升级前用curl -u admin:密码 "http://旧地址/api/system/status"确认服务是UP状态,再执行升级,不要把还在跑的实例直接停掉升级,否则用户会在这几分钟内失去质量反馈。升级成功标准不只是 Web 页面能打开,而是用同一份代码分别跑一次旧版和新版扫描,对比 BUG 数量和规则命中列表是否在预期范围内——如果新版报出大量旧版没有的问题,不要急着慌,大概率是新规则集把旧规则替换掉了,需要在质量配置里做映射。
留在 7.9 也有维护技巧。插件手动更新是常态,建议每个季度检查一次插件仓库有没有针对 7.9 的补丁版本。规则集调整比升级规则集更安全,直接在 Web 界面上改,不走数据库操作。数据库备份不要等出问题才做,用 cron 每周全备一次,保留最近一个月,这样即使插件把数据写坏,你也回得到一周前。
我自己的习惯是把 7.9 的sonar-project.properties模板、质量门禁导出文件、规则集 XML 三件套放进团队的 gitops 仓库里。这样无论部署在哪台机器、由谁操作,都能复现同一套扫描标准。曾经我在一次内网迁移时因为没备份data目录,丢了三年的趋势数据,从那以后不管多急的变更,我都要先打快照再动手。这个习惯救过我很多次。
跑通 sonarqube 7.9 只是第一步,真正的收益是把门禁接进流水线,让每次提交都被同一把尺量过。希望帮到你。
本文还有配套的精品资源,点击获取