简介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 和 PostgreSQLSonarQube 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.5GBweb 进程给 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.usernamesonar sonar.jdbc.passwordyoupass sonar.jdbc.urljdbc:postgresql://localhost:5432/sonar # 配置 web 服务监听 sonar.web.host0.0.0.0 sonar.web.port9000 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_count262144 echo vm.max_map_count262144 /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.propertiessonar.projectKeymy-project sonar.projectNameMy Project sonar.projectVersion1.0 sonar.sourcessrc sonar.java.binariestarget/classes sonar.sourceEncodingUTF-8 sonar.host.urlhttp://localhost:9000/sonarqube sonar.loginadmin sonar.passwordadmin123执行扫描sonar-scanner -Dsonar.host.urlhttp://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.allowCorePluginsfalse其实不是这个参数。正确的是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.projectKeymy-project扫描过后来又把项目删了再扫描同名项目时系统认为是重建但权限绑定没刷新。解决办法是在管理界面找到该项目手动打开权限页面给扫描 token 授予 Browse 权限。另一个常见原因是你用sonar.loginadmin这种密码方式扫描但密码包含特殊字符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.realmLDAP写在了sonar.properties里但管理员密码用了{bcrypt}前缀应该用明文或者正确哈希格式。检查配置后用sonar.security.updatePasswordfalse避免每次登录都强制改密码。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?projectKeysmy-projectps100p1 -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.projectVersion1.0可以对比不同版本间的新增缺陷数。归档脚本写完后放到定时任务里30 2 * * * /opt/sonarqube-archive/run_archive.sh /dev/null 21这个脚本每次跑完都会在本地留一个带日期的 JSON 文件三个月后你就可以做出按周统计的新增缺陷趋势图。如果以后团队决定升级到新版本这些历史数据也不会因为迁移而丢掉。我自己的习惯是每年做一次质量数据归档这事有人觉得多余但后来一次升级导致门禁指标名变化时全靠这套离线数据帮我把两个版本的统计口径对齐省了很多争论。希望这个技巧也能帮到你在 7.9 这条老路上走得稳一点。本文还有配套的精品资源点击获取