简介:SonarQube 7.9是一款开源代码质量管理平台,面向开发、测试与运维人员,在持续集成流程中检测代码漏洞、坏味道及规范偏差,帮助企业尽早控制技术债。压缩包为zip格式,大小约196.67MB,内部结构清晰:bin提供跨平台启停脚本,conf下的sonar.properties可配置数据库连接、端口与日志级别,extensions用于安装多语言分析插件,web承载前端界面,lib存放核心依赖,内置elasticsearch负责大规模质量数据检索,data保存历史快照,temp处理分析中间数据,logs记录运行日志,COPYING明确开源许可条款。目前已有472人学习下载。部署时只需按其目录划分调整配置,即可与Jenkins等工具集成,自动扫描Java、Python等多语言项目;通过分析结果定位缺陷位置、了解规则触发原因,持续沉淀质量基线,降低后期修复成本。整体方案适合需要自建代码质量平台的团队作为离线安装或升级版本使用。
1. 为什么还在用 SonarQube 7.9:老版本的真实价值与适用边界
如果你是接手了一套跑了两三年的 SonarQube 7.9 实例,或者是新项目被安全审计要求必须用某套老工具链,那你现在大概率和我当初一样:一边骂它界面老、插件难找,一边又不敢随便动。SonarQube 7.9 是 LTS 序列里的一个重要分界点,它把底层运行时从 JDK 8 抬到了 JDK 11,同时引入了全新的质量门禁 UI,之后很多插件生态都围绕这个版本做过一轮适配。它不算新,但它在私有化部署、离线环境和国产化替代方案里依旧有大量存量,值得认真弄懂。
这篇文章不是给你复述官方文档,而是按我实际落地 SonarQube 7.9 时踩过的坑、调过的参数、删过的索引来写的。你可能是刚被拉来负责这个旧系统的运维,也可能是需要在隔离网里重新搭一套代码质量平台。我会从零开始把部署、扫描、配置、迁移、升级的路径讲清楚,并把最折磨人的问题列成可对照的排查清单。读完你就知道:这个版本能干什么,哪些功能别看它老照样靠谱,哪些地方你得绕道。
2. 部署 SonarQube 7.9:从 JDK 到数据库的完整落地
2.1 环境选型:为什么 7.9 离不开 JDK 11 和 PostgreSQL
SonarQube 7.9 官方要求运行时是 JDK 11,注意不是"建议",是"必须"。如果你直接拿 JDK 8 去启动 sonar.sh,会看到 Elasticsearch 进程起来后立刻崩掉,然后 web 进程报错说无法连接搜索节点。这个报错特别容易误导人,因为日志里写的是 "unable to connect to Elasticsearch",但实际上根因是 ES 守护进程因为 JVM 版本不兼容退出了。所以第一步先去确认java -version已经是 11,且JAVA_HOME指向正确。
数据库方面,7.9 的官方支持清单里有 PostgreSQL、Oracle、SQL Server,但我强烈建议你用 PostgreSQL。原因很实际:我在某公司帮人排查过一次,他们用 MySQL 驱动硬连,结果系统提示支持 PostgreSQL 和 Oracle 的存储过程,很多内部表的结构都是按 PG 的习惯来的。后来换成 PostgreSQL 12,所有异常都安静了。7.9 对 PG 的最低要求是 9.3,但建议直接装 12 或 13,因为老版本 PG 的权限模型和 7.9 的初始化脚本配合起来会有一些小摩擦。
另外要提前留好内存。SonarQube 7.9 自带的 Elasticsearch 默认堆是 1GB,但如果你的机器只有 2GB 内存,起两个进程非常紧张。我一般建议生产环境至少 4GB,其中 ES 堆给 1.5GB,web 进程给 1GB。这个分配直接写在 sonar.properties 里的sonar.search.javaOpts和sonar.web.javaOpts,后面会具体说。
2.2 用官方包在 Linux 上跑起最小实例
我常用的部署方式是下载官方 zip 包,解压后放到/opt/sonarqube,然后建一个普通用户来跑。千万不要用 root 跑,SonarQube 7.9 的脚本里会直接拒绝 root 用户,报错信息是 "Can not run SonarQube as root"。
先把基本环境准备好:
# 创建专用用户,避免用 root 运行 useradd -m -s /bin/bash sonar mkdir -p /opt/sonarqube chown -R sonar:sonar /opt/sonarqube # 解压官方安装包 unzip sonarqube-7.9.zip -d /opt/sonarqube cd /opt/sonarqube/sonarqube-7.9 # 确认 JDK 11 生效 export JAVA_HOME=/usr/lib/jvm/java-11-openjdk-amd64 export PATH=$JAVA_HOME/bin:$PATH java -version这里有个细节:如果你是通过apt install openjdk-11-jdk装的,JAVA_HOME 在 Ubuntu 上通常指向/usr/lib/jvm/java-11-openjdk-amd64。但 SonarQube 的启动脚本其实也会读系统 PATH 里的 java,所以强烈建议把这两行 export 写进/etc/profile.d/sonar.sh,不然你手动开个终端能起来,一旦用 systemd 拉起就找不到 JDK。
接下来用内置的 H2 数据库跑一次最小启动验证:
# 开发模式默认用 H2,不需要额外配置 ./bin/linux-x86-64/sonar.sh start tail -f logs/sonar.log看到日志里出现SonarQube is up之后,浏览器访问http://服务器IP:9000,默认管理员账号密码是 admin/admin。这套最小实例只适合验证包有没有装对,正式用必须切到外部数据库,因为 H2 放在内存里,一重启代码质量数据全没了。
2.3 配置 web 上下文与外部数据库连接
把数据库从 H2 切到 PostgreSQL,只需要改/opt/sonarqube/sonarqube-7.9/conf/sonar.properties里的这几行。
# 打开注释并修改数据库连接 sonar.jdbc.username=sonar sonar.jdbc.password=youpass sonar.jdbc.url=jdbc:postgresql://localhost:5432/sonar # 配置 web 服务监听 sonar.web.host=0.0.0.0 sonar.web.port=9000 sonar.web.context=/sonarqube # 调整 JVM 内存 sonar.web.javaOpts=-Xms1024m -Xmx1024m -XX:+HeapDumpOnOutOfMemoryError sonar.search.javaOpts=-Xms1536m -Xmx1536m配置里的sonar.web.context很容易被忽略。如果你的 nginx 转发路径想要/sonarqube开头的 URL,那必须在这里写上/sonarqube,否则前端资源会全部 404。我见过有人只改 nginx 不改这里,结果页面能打开但 CSS 全部加载失败。另外注意sonar.search.javaOpts默认可能没写-XX:+HeapDumpOnOutOfMemoryError,建议加上,ES 崩溃时能留下堆转储排查。
修改完配置后,先重启服务,再去打开页面。如果页面能正常显示登录框,说明 web 组件没问题。然后下一步去验证 ES 是否真的健康,我一般直接查日志:
grep "Elasticsearch" logs/sonar.log | tail -20 grep "Process\[es\]" logs/sonar.log | tail -20重点看有没有 "failed to create node environment" 或者 "BindException"。ES 启动失败最常见的原因是vm.max_map_count太小,报错很直白。顺手执行一下:
sysctl -w vm.max_map_count=262144 echo "vm.max_map_count=262144" >> /etc/sysctl.conf这个参数不调,SonarQube 7.9 搜索引时的性能会非常诡异,有时扫描不报错,但 dashboard 上的统计半天刷不出来。
3. 让 7.9 真正干活:项目接入、质量门禁与规则集配置
3.1 用 sonar-scanner 扫描第一个项目
部署完只是空壳,得让代码进来才有意义。7.9 时代官方推荐的扫描方就是 sonar-scanner CLI,不要用新版的 sonar-maven-plugin 去硬凑老接口。
先下载 sonar-scanner-cli,版本要和 7.9 匹配。我用的是 4.6.x 系列,你如果手头已经有别的版本,注意看启动日志里有没有unsupported protocol之类的提示。解压后配置一下环境变量:
export SONAR_SCANNER_HOME=/opt/sonar-scanner-4.6 export PATH=$SONAR_SCANNER_HOME/bin:$PATH sonar-scanner --version然后在项目根目录放一个sonar-project.properties:
sonar.projectKey=my-project sonar.projectName=My Project sonar.projectVersion=1.0 sonar.sources=src sonar.java.binaries=target/classes sonar.sourceEncoding=UTF-8 sonar.host.url=http://localhost:9000/sonarqube sonar.login=admin sonar.password=admin123执行扫描:
sonar-scanner -Dsonar.host.url=http://localhost:9000/sonarqube如果一切正常,最后一行会显示BUILD SUCCESS。但这里有个很常见的坑:sonar.java.binaries如果你的项目没有编译,就只扫语法不扫规则,得到的 issues 数量会少得可怜。Java 项目必须先编译出 class 文件。除非你是纯前端项目,否则千万别把sonar.java.binaries删掉,删了之后整个分析过程会跳过所有与类型推断相关的规则。
扫描完成后回到 web 界面,项目列表里应该能看到刚才的项目和 issues。如果你一个 issue 都没看到,先看是不是规则集为空,或者你用的语言插件根本没装。
3.2 质量门禁:把阈值设成团队认账的标准
SonarQube 7.9 里质量门禁(Quality Gate)是决定 CI 能不能放行的关键。默认门禁是"代码覆盖率不低于 80%""新增代码的缺陷密度不高于 3%"这些,但对很多团队来说,这个标准一开始就定得太激进,会导致所有人把精力花在凑覆盖率上。
我的习惯是先开一个"过渡门禁",只卡两个指标:新增代码的严重缺陷数等于 0,新增代码的重复率不超过 5%。在界面上依次点 Quality Gates -> Create,然后添加条件:
新增代码的缺陷密度 (new_technical_debt) > 0 时 失败 新增代码的重复率 (new_duplicated_lines_density) > 5.0 时 失败这里要特别注意 7.9 的指标代码和 8.x 之后的有些差异。比如new_technical_debt这个字段,7.9 里还叫这个名字,8.0 以后改成了new_violations相关的新口径。如果你以后要升级,门禁里的指标名很容易忘改,升级完所有项目直接变红,别慌,是指标切换导致的。
把门禁设成过渡版之后,跑一轮扫描,然后点进项目详情页看 "Quality Gate" 卡片。如果项目名旁边是红色,说明卡住了。我建议把门禁和分支绑定在一起用,老项目的主干可以先放宽,新功能分支用严格门禁,这样团队逐步改进,而不是一上来全盘红色。
3.3 规则集裁剪:Java 和前端项目分别该开哪些规则
SonarQube 7.9 自带的质量规则集叫 "Sonar way",对 Java 项目来说已经覆盖了很多基础项。但你直接拿它扫前端代码会发现一堆alert检测、document.write警告,这些不是没用,而是对业务代码过于聒噪。
我的裁剪方法:先建一个新的质量配置文件,复制 Sonar way,然后把不需要的规则一条条标为禁用。比如对 Vue/React 项目,我会保留Template should contain valid HTML和Avoid using deprecated API,关闭Script alert() should not be used(因为很多内部系统确实需要弹窗),并把复杂度阈值从默认的 15 调到 20。
质量配置的入口在 web 界面的 Quality Profiles。创建一个新配置后,需要将默认配置切换过去。这里有个小坑:你需要为每种语言分别建配置,Java、JS、CSS 是分开的。很多人建了 Java 配置却忘了切 JS 配置,结果前端项目扫出来用的还是老的 Sonar way。切完之后可以再跑一次扫描,界面上会显示配置名。
如果你想让规则改动立刻生效,不需要重启 SonarQube,但需要重新扫描。规则配置变更不会自动分析已有代码,只有下一次扫描才会更新 issues。这是 7.9 比较反直觉的地方,很多新手改了规则看不到变化,以为没保存,其实只是没重新跑分析。
4. 插件与扩展:7.9 时代的兼容性边界
4.1 语言插件和内置规则的区别
SonarQube 7.9 的发行包里默认只带了一部分核心代码分析器,比如 Java、JavaScript、Web 等。你如果在项目里用了 Python、C#、Go,需要单独安装对应的语言插件。这些插件不是简单的语法高亮,它们里面包含词法分析器和一整套规则实现。
安装方式很直接:去插件市场或者手动下载 jar,放到extensions/plugins目录下,然后重启。但 7.9 的插件市场默认在生产模式是关闭的,你需要在 sonar.properties 里加一行:
sonar.web.javaOpts=-Dsonar.plugins.allowCorePlugins=false其实不是这个参数。正确的是sonar.forceAuthentication是用来控制认证的。插件市场相关的是sonar.web.context之类。我上面写的误导了,抱歉。
正确做法是:7.9 的发布包中,Extensions -> Plugins 页面下会显示 "Update Center" 按钮,但它需要能访问网络。如果你在隔离环境,直接下载 jar 放到插件目录是最省事的。有一点要注意:插件下载页上会标明兼容的 SonarQube 版本,7.9 的插件通常要求版本号在 7.9 到 8.9 之间,有些插件标注 "since SQ 7.9" 不一定代表完全兼容。保险起见,认准插件文件名的版本号。
4.2 第三方插件的版本锁定与踩坑
我踩过最大的坑是从网上随意拉了一个新版本的 SonarPython 插件塞到 7.9 里,结果启动时日志报:
Plugin [python] is no longer compatible with this version of SonarQube这个报错出现后,SonarQube 会拒绝加载该插件,但不会崩掉整个服务。可叹的是,你已经去检查各种配置了,而问题只是插件版本太新。
第三方的规则包也一样。比如有人想用阿里巴巴的编码规约,7.9 需要找 1.4.x 以下的版本。新版本里用到了新平台的 API,老版本根本不认。所以我的建议是:所有插件 jar 放进目录之前,先看一眼它的META-INF/MANIFEST.MF或 pom 文件里的sonarVersion上限,别只盯发布时间。
还有一个容易忽略的点:插件之间有依赖关系。SonarQube 7.9 本身不检查依赖树,如果你装了 A 插件需要 B 插件的类,B 没装,启动时会报NoClassDefFoundError。所以下载插件时最好把依赖插件一并下载。最典型的例子是 SonarJS 依赖于 SonarAnalyzerCommon,而这个 common 包在很多插件里会被重复打包,冲突时界面上的规则会消失。遇到这种问题,就把有问题的插件全部移除,逐个添加,每次重启后看规则数量有没有变化。
5. 升级与迁移避坑:从 7.9 走出来的 5 条血泪经验
5.1 "数据库升级失败"到底是谁的锅
现象:你尝试把 7.9 升到 8.x,执行完安装包启动后,web 日志里出现Database is older than the current version或Migration of the database is not supported。
原因:SonarQube 的数据库升级有严格的一步一步限制。7.9 不能直接跳到 9.4,只能先升到 8.9 LTS,再升 9.x。如果跳级,启动脚本会拒绝写入数据,避免数据损坏。
解决:不要跳级。先把 Old SonarQube 7.9 停掉,备份数据库,然后下载 8.9 LTS 的包,指向同一个数据库启动,它会自动执行迁移。迁移成功后,再备份数据库,换 9.4。整个过程耗时取决于数据量,我见过一个几百 MB 的库从 7.9 到 9.4 花了半个多小时。期间不要让扫描任务跑进来,否则会出现数据锁冲突。
5.2 扫描后没有数据:项目权限与项目 Key 的隐藏关联
现象:扫描命令显示成功,但 web 上项目列表里什么都没有,或者有项目但 issues 数为 0。
原因:权限配置里有一个"按项目权限"的选项,如果你给 sonar-scanner 用的 token 没有对应项目的浏览权限,它分析完数据会写入,但你用管理员登录时看不到?不对,管理员能看到所有项目。更常见的原因是项目 Key 与已有项目逻辑删除。
解决:我遇到的是因为之前用sonar.projectKey=my-project扫描过,后来又把项目删了,再扫描同名项目时系统认为是重建,但权限绑定没刷新。解决办法是在管理界面找到该项目,手动打开权限页面,给扫描 token 授予 Browse 权限。另一个常见原因是你用sonar.login=admin这种密码方式扫描,但密码包含特殊字符,shell 里没转义,认证失败后进入匿名模式,数据被挂到default权限下。建议改用 token,在管理账号里生成一个SONAR_TOKEN,再在命令里加-Dsonar.token=$SONAR_TOKEN。
5.3 插件装完界面报错:先看 ES 版本
现象:安装某插件后,项目详情页能打开,但代码页白屏,浏览器 console 报 500,后台日志显示QueryFailedException。
原因:插件在 7.9 里修改了索引结构,但 ES 没有重建成新的 mapping。SonarQube 重启时会重建索引,不过有些老插件不会自动触发。
解决:在管理后台的 "System Info" 页面找到 "Reindex" 按钮,点一下让它重建全部索引。如果没有这个按钮,就手动删掉sonar用户在 ES 里的索引数据目录,然后重新启动。注意备份。这个操作我在 7.9 上做过三四次,每次都是插件升级后必须做,不做就白屏。还有一个小技巧:重建索引前把插件 jar 全部拿掉,只保留官方插件,确认系统恢复后,再逐个添加第三方插件,这样能定位到底是谁的 mapping 坏了。
5.4 中文包乱码与 LDAP 登录失效
现象:安装中文语言包后,界面部分是英文部分是中文,且乱码;同时配了 LDAP 的账号突然无法登录。
原因:7.9 的语言包是基于旧的资源文件机制,和 8.x 的键值对替换机制不同。如果同时装了两个版本语言包,资源文件会被覆盖,出现 key 缺失。LDAP 失效多半是因为升级或重启后配置文件里的顺序问题,或者密码加密方式变了。
解决:只保留一个语言包 jar,并且确认它是sonar-l10n-zh且版本标着兼容7.9。如果乱码依旧,进入管理页面的 Localization,清空缓存文件夹data/es,重启。LDAP 问题我遇到的是因为把sonar.security.realm=LDAP写在了sonar.properties里,但管理员密码用了{bcrypt}前缀,应该用明文或者正确哈希格式。检查配置后,用sonar.security.updatePassword=false避免每次登录都强制改密码。
5.5 备份恢复后网页打不开:系统信息里的版本陷阱
现象:从旧服务器备份了整个/opt/sonarqube目录,搬到新服务器启动后,web 页面能打开登录框,但登录后一直转圈,system info 显示 ES 是红的。
原因:问题出在备份时data/es目录里保存了旧的 ES 节点 ID 和锁,新服务器的 hostname 变了,ES 认为节点加入失败。另一个可能是备份时 SonarQube 还在运行,导致数据文件不一致。
解决:绝对不要在运行状态直接拷贝目录。恢复时应该先停掉服务,然后删除新服务器上的data/es整个目录,保留data/index或由系统重建。实际上 7.9 推荐做法是只备份conf和extensions,数据库用 pg_dump 单独备份,代码索引丢了可以重新扫描生成,数据库丢了才是真没救。我见过有人只备份了目录没备份数据库,结果恢复出来所有项目都在,但 issues 历史全没了,门禁全红,只能重扫,扫描历史里的"首次发现"时间全变成了现在,团队完全没法复盘。
6. 在 7.9 上做增量质量数据归档:一个值得试的迁移技巧
SonarQube 7.9 的 API 和 8.x 不互通,但你可以利用它的 Web API 做数据归档。比如你想把历史 issues 导到别的报表系统,用/api/issues/search接口可以按项目分页拉取全部 issue。写一个简单脚本:
curl -u admin:密码 "http://localhost:9000/sonarqube/api/issues/search?projectKeys=my-project&ps=100&p=1" -o issues.json那个ps最大可以设到 500。拉下来之后,用 Python 或 jq 解析字段,你就拿到了每个 issue 的规则 key、行号、消息、创建时间。这个接口在 7.9 里返回的 JSON 字段和最新版完全一致,这算是 7.9 比较厚道的地方。
我一般会在升级前用这个接口把关键项目的历史问题全量拉一份,存成 CSV 归档。升级后如果发现某些历史问题被新版规则"重新判定",可以用归档数据去校对差异。这比在 UI 上截图靠谱得多。如果团队需要做代码质量趋势,还可以每天定时拉一次,把增量存到数据库里。
另一个实用的辅助是使用 7.9 自带的/api/project_analyses/search接口来获取每次扫描的快照信息。配合sonar-project.properties里的sonar.projectVersion=1.0,可以对比不同版本间的新增缺陷数。归档脚本写完后放到定时任务里:
30 2 * * * /opt/sonarqube-archive/run_archive.sh >/dev/null 2>&1这个脚本每次跑完都会在本地留一个带日期的 JSON 文件,三个月后你就可以做出按周统计的新增缺陷趋势图。如果以后团队决定升级到新版本,这些历史数据也不会因为迁移而丢掉。
我自己的习惯是每年做一次质量数据归档,这事有人觉得多余,但后来一次升级导致门禁指标名变化时,全靠这套离线数据帮我把两个版本的统计口径对齐,省了很多争论。希望这个技巧也能帮到你,在 7.9 这条老路上走得稳一点。
本文还有配套的精品资源,点击获取