简介SonarQube 7.4 是一款开源代码质量管理工具的完整安装包面向 Java、Python、C#、JavaScript 等多语言开发者及需要搭建代码质量平台的团队。它可帮助发现代码漏洞、代码异味与复杂度问题并支持与 Jenkins、GitLab CI/CD 等持续集成工具对接实现自动化质量检查。压缩包为 rar 格式整体约 161.38MB内含 bin、conf、extensions、lib、web、libexec 等目录及 README、LICENSE 文件分别用于服务启停脚本、数据库与端口配置、插件扩展、运行库、前端界面资源和辅助工具结构完整解压后按 conf/sonar.properties 调整即可部署。目前已有 637 人学习下载适合需要快速获取 7.4 版本、搭建本地代码质量分析环境的中高级开发者参考使用。1. 为什么 2024 年还有人把 SonarQube 7.4 装进内网上周帮一个做军工配套的团队排查代码质量平台他们内网跑的就是 SonarQube 7.4一台 4C8G 的 CentOS 7 虚拟机从 2019 年上线到现在没动过。新来的同事想升级到最新版结果发现新版要求 JDK 11 以上、数据库必须 PostgreSQL 12而他们那台机器上还跑着 JDK 8 和 MySQL 5.7 的老业务。折腾两天后决定不升了继续用 7.4。这个场景其实很典型。SonarQube 7.4 是 2018 年底发布的 LTS 版本支持 JDK 8、MySQL 5.6/5.7、PostgreSQL 9.6-10对老内网环境极其友好。它的核心能力——静态代码分析、代码异味检测、覆盖率报告、质量门禁——放到今天依然够用。如果你手上有一台不能随便动环境的机器或者需要给一个离线团队搭一套代码扫描服务7.4 反而是最省事的选择。这篇文章面向三类人一是要在内网离线部署 SonarQube 的运维二是想给老项目加代码扫描但不想动 JDK 的开发者三是需要理解 SonarQube 扫描器与服务器交互机制的技术负责人。我会从安装、配置、扫描器对接、质量门禁设置一路讲到踩坑排查所有步骤都在一台干净的 CentOS 7 虚拟机上验证过。2. 环境准备与数据库选型为什么 MySQL 5.7 是 7.4 的甜点区2.1 版本兼容性矩阵与选型逻辑SonarQube 7.4 对运行环境有明确的硬性要求选错了版本连启动都过不去。先看这张表组件最低要求推荐版本说明JDK8Oracle JDK 8u191 或 OpenJDK 8不支持 JDK 11数据库MySQL 5.6 / PostgreSQL 9.6MySQL 5.7 / PostgreSQL 10内网首选 MySQL 5.7内存2GB4GB 以上Elasticsearch 内嵌吃内存磁盘10GB50GB SSD索引和报告会持续增长操作系统任意支持 JDK 8 的系统CentOS 7.x内核参数需调整为什么推荐 MySQL 5.7 而不是 PostgreSQL不是技术优劣问题而是内网运维的现实大多数国内企业的内网数据库运维体系围绕 MySQL 建立备份脚本、监控模板、权限审批流程都是现成的。SonarQube 7.4 对 MySQL 5.7 的支持已经非常稳定只要注意字符集和 SQL 模式两个参数就行。有一个容易被忽略的点SonarQube 7.4 内置了 Elasticsearch 5.6.3而 Elasticsearch 对文件描述符和虚拟内存有硬性要求。如果这两项没调启动时会直接报错退出日志里写的是max file descriptors [4096] for elasticsearch process is too low。这不是 SonarQube 的问题是 Elasticsearch 的 bootstrap 检查。2.2 系统参数调整与数据库初始化先处理操作系统层面的限制。以下命令在 CentOS 7 上验证通过# 查看当前限制 ulimit -n sysctl vm.max_map_count # 永久调整文件描述符限制 echo sonar soft nofile 65536 /etc/security/limits.conf echo sonar hard nofile 65536 /etc/security/limits.conf # 调整虚拟内存映射数Elasticsearch 要求至少 262144 echo vm.max_map_count262144 /etc/sysctl.conf sysctl -p # 创建专用用户不要用 root 跑 SonarQube useradd sonar passwd sonarvm.max_map_count这个参数控制进程可以拥有的内存映射区域数量。Elasticsearch 的 Lucene 索引在底层大量使用 mmap默认值 65530 不够用启动时会抛max virtual memory areas vm.max_map_count [65530] is too low。改成 262144 是官方建议值改完必须执行sysctl -p让它生效重启后也会保留。接下来初始化数据库。SonarQube 7.4 要求数据库使用 UTF-8 字符集并且不能开启ONLY_FULL_GROUP_BY模式-- 创建数据库和用户 CREATE DATABASE sonar CHARACTER SET utf8 COLLATE utf8_general_ci; CREATE USER sonarlocalhost IDENTIFIED BY Sonar2024; GRANT ALL PRIVILEGES ON sonar.* TO sonarlocalhost; FLUSH PRIVILEGES; -- 检查 SQL 模式必须去掉 ONLY_FULL_GROUP_BY SELECT sql_mode; -- 如果结果中包含 ONLY_FULL_GROUP_BY需要在 my.cnf 中移除ONLY_FULL_GROUP_BY是 MySQL 5.7 的默认 SQL 模式之一它要求 GROUP BY 查询中 SELECT 的列必须出现在 GROUP BY 中或使用聚合函数。SonarQube 7.4 的部分内置查询不满足这个约束开启后会在启动初始化阶段报 SQL 语法错误。修改/etc/my.cnf在[mysqld]段下添加sql_modeSTRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION然后重启 MySQL。注意数据库密码不要用特殊字符$和!SonarQube 的配置文件对这两个字符的转义处理有问题会导致连接失败但报错信息不明确。3. 安装部署与扫描器对接从零到第一次扫描成功3.1 SonarQube 服务端安装与配置下载 SonarQube 7.4 的发行包社区版即可内网代码扫描不需要开发者版的多分支分析。解压到/opt下目录结构里需要关注三个位置conf/sonar.properties是主配置bin/linux-x86-64/sonar.sh是启动脚本logs/下是运行日志。# 解压并设置权限 cd /opt unzip sonarqube-7.4.zip chown -R sonar:sonar /opt/sonarqube-7.4 chmod x /opt/sonarqube-7.4/bin/linux-x86-64/sonar.sh # 编辑主配置 vim /opt/sonarqube-7.4/conf/sonar.properties配置文件里需要改动的核心项# 数据库连接 sonar.jdbc.usernamesonar sonar.jdbc.passwordSonar2024 sonar.jdbc.urljdbc:mysql://localhost:3306/sonar?useUnicodetruecharacterEncodingutf8rewriteBatchedStatementstrueuseConfigsmaxPerformanceuseSSLfalse # Web 服务端口默认 9000如果被占用改这里 sonar.web.port9000 sonar.web.context/sonar # 允许匿名访问内网可选方便查看报告 sonar.forceAuthenticationfalse # Elasticsearch 存储路径默认在 data/ 下数据量大时建议挂独立磁盘 sonar.path.data/data/sonar/data sonar.path.temp/data/sonar/temprewriteBatchedStatementstrue这个参数很关键。SonarQube 在分析大型项目时会批量写入大量数据开启这个选项后 MySQL 驱动会把多条 INSERT 合并成一条写入性能提升明显。useConfigsmaxPerformance是 MySQL 驱动内置的性能优化配置集配合rewriteBatchedStatements使用效果最好。启动服务# 切换到 sonar 用户启动 su - sonar /opt/sonarqube-7.4/bin/linux-x86-64/sonar.sh start # 查看启动日志 tail -f /opt/sonarqube-7.4/logs/sonar.log启动过程分三个阶段先启动 Elasticsearch日志里能看到Elasticsearch started再启动 Web ServerWeb server started最后是 Compute EngineCompute Engine started。三个都出现才算成功。首次启动会初始化数据库表结构大概需要 1-2 分钟。浏览器访问http://服务器IP:9000/sonar默认账号密码都是admin。3.2 扫描器配置与项目接入SonarQube 的扫描器Scanner是独立于服务端的命令行工具负责在代码所在机器上执行分析然后把结果推送到服务端。7.4 时代主流用的是sonar-scanner命令行工具Maven 项目也可以用sonar-maven-plugin。下载 sonar-scanner 3.3 版本与 7.4 服务端匹配解压后配置conf/sonar-scanner.properties# 指向 SonarQube 服务端地址 sonar.host.urlhttp://192.168.1.100:9000/sonar # 如果服务端开启了强制认证需要配置 token # sonar.loginyour_token_here然后在项目根目录创建sonar-project.properties# 项目唯一标识不能重复 sonar.projectKeymy-java-app sonar.projectNameMy Java Application sonar.projectVersion1.0.0 # 源码目录多个用逗号分隔 sonar.sourcessrc/main/java sonar.testssrc/test/java # 编码 sonar.sourceEncodingUTF-8 # 排除目录 sonar.exclusions**/generated/**,**/node_modules/**,**/*.min.js # 覆盖率报告路径如果接了 JaCoCo sonar.jacoco.reportPathstarget/jacoco.exec执行扫描# 在项目根目录执行 /path/to/sonar-scanner/bin/sonar-scanner \ -Dsonar.projectKeymy-java-app \ -Dsonar.sourcessrc/main/java \ -Dsonar.host.urlhttp://192.168.1.100:9000/sonar \ -Dsonar.loginadmin \ -Dsonar.passwordadmin扫描完成后服务端会自动触发质量门禁计算。如果项目是第一次扫描需要等几秒钟让 Compute Engine 处理完报告然后在 Web 界面就能看到代码异味、Bug、漏洞的统计。注意sonar.login和sonar.password用默认 admin 账号只适合测试。生产环境应该在 SonarQube 界面生成专用 Token用户头像 → My Account → Security → Generate Tokens然后用-Dsonar.logintoken值的方式认证避免密码明文出现在命令行历史里。3.3 质量门禁与规则集定制SonarQube 7.4 默认的质量门禁叫 Sonar way核心指标是新代码覆盖率不低于 80%、新代码重复率不高于 3%、新代码没有 Blocker 级别问题。这个门禁对老项目改造来说太严了直接套用会导致所有项目都是红色。我一般会新建一个质量门禁针对存量项目放宽标准指标Sonar way 默认值存量项目建议值说明新代码覆盖率≥ 80%≥ 60%老项目补测试成本高新代码重复率≤ 3%≤ 5%容忍少量复制粘贴Blocker 问题00这个不能松Critical 问题0≤ 5给修复缓冲期代码异味无要求不设门禁只做统计不卡流程在 Web 界面Quality Gates→Create新建门禁然后到Rules→Quality Profile里激活或关闭特定规则。比如 Java 项目中squid:S106用日志代替 System.out.println这条规则如果项目里大量使用System.out做调试输出可以先降级为 Minor 而不是直接报 Critical。规则集调整有个原则先跑一遍全量扫描看问题分布再决定关哪些规则。不要一上来就关规则那样等于把 SonarQube 当摆设。正确的做法是看Issues页面按规则分组找出误报率最高的几条规则针对性关闭或调整阈值。4. 避坑排查7.4 版本特有的五个翻车现场4.1 启动报错 max file descriptors too low现象执行sonar.sh start后进程立刻退出sonar.log里出现max file descriptors [4096] for elasticsearch process is too low, increase to at least [65536]。原因Elasticsearch 启动时检查当前用户的文件描述符限制默认的 1024 或 4096 不满足要求。虽然/etc/security/limits.conf里改了但sonar.sh脚本启动时可能没有加载 PAM 限制。解决除了改limits.conf还要在sonar.sh脚本开头手动设置ulimit -n 65536。或者用 systemd 管理服务在 unit 文件里加LimitNOFILE65536。最直接的办法是在启动命令前加ulimit -n 65536 。4.2 数据库连接失败但报错信息模糊现象启动日志里写Cannot connect to database. Please check your JDBC URL and credentials但用 mysql 客户端能正常连接。原因SonarQube 7.4 使用的 MySQL 驱动版本较老5.1.x不支持 MySQL 8 的默认认证插件caching_sha2_password。如果数据库是 MySQL 8即使端口密码都对也连不上。解决确认数据库版本。如果是 MySQL 8要么把用户认证插件改成mysql_native_passwordALTER USER sonarlocalhost IDENTIFIED WITH mysql_native_password BY 密码要么换 MySQL 5.7。7.4 官方不支持 MySQL 8强行用会有各种兼容问题。4.3 扫描大型项目时 Compute Engine 卡死现象扫描器显示ANALYSIS SUCCESSFUL但 Web 界面一直显示Pending报告出不来。查看ce.log发现处理线程卡在某个任务上。原因项目文件太多超过 10 万个文件Compute Engine 的默认堆内存不够或者数据库写入超时。解决调整sonar.properties里的 Compute Engine 内存参数sonar.ce.javaOpts-Xmx2g -Xms512m -XX:HeapDumpOnOutOfMemoryError。同时检查数据库连接池配置适当增大sonar.jdbc.maxActive默认 10可以调到 20。如果还是卡在扫描器端加-Dsonar.scm.disabledtrue关闭 SCM 信息采集能减少大量数据写入。4.4 中文乱码与编码问题现象扫描包含中文注释的 Java 文件后Web 界面显示的代码片段里中文变成问号或乱码。原因扫描器默认使用系统编码读取源文件如果服务器 locale 是 POSIX 或 C中文会被错误解码。解决在sonar-project.properties里显式指定sonar.sourceEncodingUTF-8同时在扫描器启动脚本里设置export LANGen_US.UTF-8或zh_CN.UTF-8。数据库连接 URL 里也要带characterEncodingutf8。三个地方都对了才不会乱码。4.5 质量门禁不生效或状态不更新现象扫描完成后质量门禁一直显示None或停留在上一次的状态新提交的代码问题没有触发门禁失败。原因SonarQube 7.4 的质量门禁计算依赖 Compute Engine 的任务队列。如果 CE 进程异常或队列积压门禁状态不会刷新。另外如果项目没有关联到正确的 Quality Gate比如新建的门禁没有设为默认也会出现这个问题。解决先检查ce.log是否有异常堆栈。然后在项目设置里确认Quality Gate选的是正确的门禁。如果是队列积压重启 SonarQube 服务清空队列。还有一个隐蔽原因扫描时没有传sonar.projectVersion导致新代码和老代码无法区分门禁只统计新代码的指标就失效了。5. 进阶技巧用 Web API 把扫描结果接进 CI 流水线SonarQube 7.4 的 Web API 是它最被低估的能力。很多团队只把它当网页看板用其实通过 API 可以把扫描结果直接卡在 CI 流水线的构建步骤里实现「质量门禁不通过则构建失败」。核心 API 是/api/qualitygates/project_status传入项目 key 就能拿到门禁状态# 查询项目质量门禁状态 curl -s -u admin:admin \ http://192.168.1.100:9000/sonar/api/qualitygates/project_status?projectKeymy-java-app \ | python -m json.tool返回的 JSON 里status字段是OK或ERROR。在 Jenkins 或 GitLab CI 的构建脚本里加一段判断#!/bin/bash # 在扫描完成后检查质量门禁 SONAR_URLhttp://192.168.1.100:9000/sonar PROJECT_KEYmy-java-app TOKENyour_token_here STATUS$(curl -s -u ${TOKEN}: \ ${SONAR_URL}/api/qualitygates/project_status?projectKey${PROJECT_KEY} \ | grep -o status:[^]* | head -1 | cut -d -f4) if [ $STATUS ! OK ]; then echo 质量门禁未通过当前状态${STATUS} # 拉取具体失败指标 curl -s -u ${TOKEN}: \ ${SONAR_URL}/api/qualitygates/project_status?projectKey${PROJECT_KEY} \ | python -m json.tool exit 1 fi echo 质量门禁通过这段脚本的逻辑是扫描完成后调 API 查门禁状态如果不是 OK 就打印详细失败指标并返回非零退出码CI 流水线收到非零退出码就会标记构建失败。-u ${TOKEN}:的写法是 curl 的 basic auth 语法冒号后面留空表示只用 token 不用密码。还有一个实用 API 是/api/measures/component可以拉取指定项目的具体指标值# 获取代码覆盖率、代码异味数、Bug 数 curl -s -u ${TOKEN}: \ ${SONAR_URL}/api/measures/component?component${PROJECT_KEY}metricKeyscoverage,code_smells,bugs,vulnerabilities \ | python -m json.tool这个接口适合做自定义报表。比如每周跑一次定时任务把各项目的指标拉下来存到自己的数据库里做趋势分析。SonarQube 自带的趋势图只能看单个项目跨项目对比还是要自己动手。我一般会在 CI 脚本里加一个「扫描后等待」的逻辑扫描器返回成功后Compute Engine 处理报告需要几秒到几十秒不等如果立刻调 API 可能拿到的是上一次的状态。稳妥做法是轮询/api/ce/task?idxxx直到任务状态变成SUCCESS再查门禁。扫描器输出里会带ceTaskId用grep提取出来就行。从那以后我每次配 CI 流水线都会强制走一遍「扫描 → 等 CE 完成 → 查门禁 → 失败则阻断」的完整链路不再只看扫描器返回的 SUCCESS。因为扫描成功只代表分析完成不代表质量达标。希望帮到你。本文还有配套的精品资源点击获取