在 Windows 上搭 SonarQube,再用 Sonar Scanner 把代码分析跑起来,听起来就是“下载、解压、执行”三步的事。但真动起手来,你会发现版本匹配、数据库选型、扫描器执行路径、项目排除规则这些环节,每一个都能卡你一下。我这篇从零开始,在 Windows 10/11 机器上把 SonarQube 服务端和 Sonar Scanner 命令行完整跑通,覆盖 JDK、PostgreSQL、SonarQube、Scanner 的安装配置,以及第一次扫真实项目时踩过的坑。不管你是后端、前端,还是打算在团队里推广代码质量工具的运维或测试,按这套步骤走,能少绕很多弯路。
1. 这套工具到底是怎么工作的
1.1 先搞明白 SonarQube 和 Scanner 的分工
SonarQube 是服务端,负责集中存储规则库、分析结果、质量门禁、用户权限这些数据;Sonar Scanner 是客户端,一个独立命令行工具,在项目目录里读取源代码,做语法解析和逻辑分析,然后把结果上传到服务端。两者不是同一个程序,也不一定装在同一台机器上。
这个分工很重要。很多人第一次用的时候以为下载了 SonarQube 就等于能扫描了,实际上单有服务端扫不了任何代码;反过来,单有 Scanner 又没有地方展示报告、做历史趋势和质量门禁。只有两个组件配合起来,才算形成一条完整的分析链路。
我习惯把它类比成体检中心:Scanner 是上门抽血的检验员,负责采集和分析样本;SonarQube 是病历系统,把检验单归档、对比历史指标、给出合格或不合格的结论。代码分析也是一样的逻辑,本地扫描和集中管理各干各的,职责分清楚,后面接入 CI/CD 流水线时也方便。
为什么 SonarQube 要设计成这种服务端加客户端的架构?核心原因是扩展性。服务端把规则、报告、权限统一管起来,多人协作时每个人只装一个 Scanner 就能工作;以后想扩展到多个项目、多个构建机,也不需要重复搭平台。理解了这一点,你就知道在 Windows 上折腾这套环境时,配置 Service 端是重点,Scanner 端反而越简单越好。
1.2 版本和组件选型的思路
版本选型是所有坑里最隐蔽的一个。SonarQube 对 JDK 版本有硬性要求,我以 9.9 LTS 这个长期支持版本为例,它要求 JDK 17;如果你下载了一个新版 Scanner 又配了旧版 JDK,启动时大概率会报UnsupportedClassVersionError或“requires Java 17”的错误。所以我的建议是:不要无脑下载 latest,先去官方文档看 LTS 版本的 System Requirements,再决定 JDK、Scanner 和数据库的搭配。
数据库这一环也容易踩坑。SonarQube 自带一个内置 H2 数据库,解压后直接启动就能用,适合本地评估和功能体验。但内置 H2 的数据文件就在 SonarQube 安装目录下,升级版本、迁移机器、多用户并发都不够稳。社区版目前主流推荐搭配 PostgreSQL,尤其要记住一点:新版本已经不再支持 MySQL。所以从规划阶段就按 PostgreSQL 来,后面省得换库重来。
Scanner 本身也有 zip 包和源码包,我们在 Windows 上直接下载 zip 版即可,解压就能用。社区版能覆盖常规的 Java、JavaScript、TypeScript、Python、PHP、C# 等语言分析;C/C++、Objective-C 这些高级语言插件是商业版功能,团队还没买授权的话不用花时间折腾。
2. Windows 端基础环境准备
2.1 JDK 安装与 JAVA_HOME 配置
SonarQube 和 Scanner 都是 Java 程序,所以第一步是装 JDK。版本按你选定的 SonarQube 版本来,9.9 系列就装 JDK 17,8.9 LTS 需要 JDK 11,这里千万不要凭感觉选。安装完成后要配置两个环境变量:JAVA_HOME指向 JDK 安装目录,PATH里追加%JAVA_HOME%\bin。
配置步骤很简单,右键“此电脑” -> 属性 -> 高级系统设置 -> 环境变量,新建JAVA_HOME,比如C:\Program Files\Java\jdk-17,再编辑Path变量,新增一行%JAVA_HOME%\bin。配置完重新开一个命令行窗口,执行:
java -version能看到java version "17"之类输出,就说明环境变量生效了。这里有个细节:配置完环境变量一定要新开命令行窗口,系统不会自动刷新旧窗口的环境变量,经常有人在这一步卡十分钟。
还有一个容易忽略的点是机器上可能同时存在多个 JDK。如果你用了一些开发工具自带的 JRE,或者别的软件修改过PATH,命令行里java -version显示的版本可能不是你想用的。最好在JAVA_HOME的 bin 目录手动执行java -version,确认当前命令行实际调用的 JDK 路径,避免启动 SonarQube 时突然爆版本错误。
2.2 目录规划与下载解压
我习惯把 SonarQube 和 Scanner 放到同一个工作目录下,比如E:\sonar,下面分成sonarqube-9.9和sonar-scanner。这样做的好处是后续配置里写路径、看日志、升级替换都一目了然。
下载时注意选对平台包。SonarQube 在官网下载页面有 Windows zip 包,解压后目录名一般带版本号,例如sonarqube-9.9.x;Sonar Scanner 下载sonar-scanner-cli版本,解压后目录名是sonar-scanner-...。解压工具建议用带管理员权限的软件,避免出现文件只读或目录权限问题。
项目目录建议使用纯英文路径,不要带空格和中文。虽然现代版本对中文路径兼容性好了很多,但 Scanner 解析路径时偶发编码问题,Windows 下中文路径遇到特殊字符很容易让分析任务失败。为了减少排查成本,安装目录、项目目录、日志路径都尽量避开中文。
确认目录就绪后,可以先启动一下 SonarQube 自带的 H2 数据库模式,验证基础环境能不能跑起来,再切换成 PostgreSQL。这样可以把环境问题拆开,不至于一步错全盘乱。
3. 启动服务端:数据库优先,SonarQube 在后
3.1 PostgreSQL 初始化
PostgreSQL 在 Windows 上有官方安装包,安装过程会把服务注册到系统服务,默认端口是 5432。安装时设置一个 postgres 超级用户密码,后面创建 SonarQube 专用库会用到。
安装完成后,打开命令行或者用数据库管理工具,执行以下 SQL 创建专用用户和数据库。我建议密码别太复杂,因为 JDBC URL 里特殊字符可能要做转义,但也不能太弱,毕竟是代码库的元数据存储。
CREATE USER sonar WITH PASSWORD 'sonar123'; CREATE DATABASE sonar OWNER sonar; GRANT ALL PRIVILEGES ON DATABASE sonar TO sonar;这里有个小技巧:给 SonarQube 创建一个独立的数据库用户,不要用超级用户 postgres 直接跑。因为 SonarQube 启动时会自动做表结构和数据迁移,如果用管理员权限,一旦误操作影响面很大;用专用用户能隔离风险,将来备份迁移也更清晰。
另外确认一下 PostgreSQL 服务是否开机自启,因为 SonarQube 每次启动都需要连数据库,如果 PG 服务没起来,SonarQube 会直接报数据库连接失败。Windows 上可以在“服务”窗口里找到 PostgreSQL 服务,把启动类型改为“自动”。
3.2 修改 sonar.properties 并首次启动
找到 SonarQube 解压目录下的conf/sonar.properties文件,用文本编辑器打开。默认文件里有大量注释,我们主要改三行:
sonar.jdbc.username=sonar sonar.jdbc.password=sonar123 sonar.jdbc.url=jdbc:postgresql://localhost:5432/sonar取消注释后保存。这个文件控制的是 SonarQube 服务端启动参数,修改后必须重启服务才生效。如果你只是下载后解压看一眼,还没配置数据库,那用的就是内置 H2,第一次启动不会有问题;但如果你后面已经用内置库跑出过数据,再切换 PostgreSQL,之前的数据不会自动迁移,所以一开始就选 PG 更省事。
启动方式很简单,进入bin\windows-x86-64目录,双击或执行StartSonar.bat。启动时窗口会滚动日志,第一次启动尤其慢,因为要初始化数据库表结构。看到日志输出里出现类似SonarQube started的字样,就说明服务端起来了。
启动之后打开浏览器访问http://localhost:9000,默认账号是admin/admin,登录后系统会强制要求修改密码。这一步别偷懒直接跳过,SonarQube 默认管理员账号暴露在公司内网已经是安全隐患,改成强密码是基本操作。
如果你觉得英文界面不顺手,可以在 Administration -> Marketplace 里搜索 Chinese Pack 语言包,安装后重启即中文。社区版在线安装语言包是支持的,需要注意 marketplace 网络环境,如果无法访问插件市场,就以后再说,不影响核心功能。
4. 安装 Scanner 并完成第一次扫描
4.1 Scanner 安装和认证令牌
Sonar Scanner 解压后就是一个完整的命令工具目录。把sonar-scanner的bin目录加入系统PATH,同时可以设置一个SONAR_SCANNER_HOME环境变量指向解压根目录,方便脚本引用。
配置完成后,新开一个命令行窗口执行:
sonar-scanner -v能看到版本信息就说明 Scanner 安装成功。如果提示命令不存在,检查 PATH 是否真的加对了,或者当前窗口没刷新。
接下来生成访问令牌。在 SonarQube 界面右上角点头像,进入 My Account -> Security,输入一个令牌名称,点 Generate,会生成一串不可见的字符串。选择令牌有效期时要务实,本地测试可以设长一点,集成到 CI 里建议用短期令牌或每次都通过环境变量注入。
认证方式我推荐用令牌,而不是直接在命令里写admin/密码。原因很简单:命令行和配置文件都可能被 Git 记进历史,密码暴露是迟早的事;令牌可以单独撤销,泄露后重新生成一个就行,不会影响账号本身。在 Scanner 侧,可以通过sonar.token参数传入。
4.2 准备一个真实项目并运行扫描
为了演示,我建一个最简单的 JavaScript 项目,目录结构如下:
demo-project ├── src │ └── index.js └── sonar-project.propertiessrc/index.js里故意留一些问题,比如一个空的 catch 块和一段重复代码:
function add(a, b) { return a + b; } function sub(a, b) { return a - b; } function returnZero() { const zero = 0; return zero; } function handleError() { try { // some operation } catch (e) { // empty } }在项目根目录创建sonar-project.properties:
sonar.projectKey=demo-project sonar.projectName=Demo Project sonar.projectVersion=1.0 sonar.sources=src sonar.exclusions=**/node_modules/**,**/coverage/**,**/vendor/**,**/dist/**,**/build/** sonar.sourceEncoding=UTF-8 sonar.host.url=http://localhost:9000 sonar.token=你的令牌配置好之后,在该项目根目录打开命令行,执行:
sonar-scannerScanner 会读取sonar-project.properties,分析src目录,然后把结果上传到 SonarQube。执行过程会输出很多日志,重点看几个关键行:
SONAR_SCANNER_HOME指向的路径是否正确Project root configuration file是否找到了sonar-project.properties1 file indexed表示确实索引到了源码文件- 最后
EXECUTION SUCCESS表示分析成功
sonar-project.properties里的sonar.token如果不想写进项目仓库,可以改用命令行参数:
sonar-scanner -Dsonar.token=你的令牌两种方式效果一样,看你的场景。分析完成后,项目页会出现在 SonarQube 的 Projects 列表里,点进去就能看到报告。
4.3 分析语言和工程结构的补充
上面例子是 JavaScript 项目,Scanner 不需要编译产物就能直接分析。如果你要分析 Java 项目,情况就复杂一点,Scanner 需要读取编译后的字节码来做数据流分析,单纯给src目录往往不够。
Java 项目常见配置是在sonar-project.properties里加一行:
sonar.java.binaries=target/classes如果项目用的是 Maven,也可以直接在项目里执行mvn sonar:sonar,让 Maven 自动找到 class 文件和依赖;但标题既然限定在 Sonar Scanner,那 CLI 方式就要保证先把代码编译过,再给 Scanner 提供 class 路径。没给sonar.java.binaries最典型的症状是:扫描任务显示成功,但报告里看不到行数或者大量源码没被对标。
多模块项目要额外配置模块间的关系,这会用到sonar.modules,新手阶段可以先拿单模块项目练手,等把基础链路跑通后再考虑模块合并。Scaner 每次运行都会在项目根目录生成.scannerwork临时目录,分析完成理论上会自动清理,偶尔卡住也会残留,看到它不用慌,删除不影响结果。
5. 看报告、质量门禁和避坑清单
5.1 从 UI 读懂分析结果
项目分析完成后,进入 SonarQube 的 Project 页面,第一眼会看到一个大大的 Quality Gate 状态。绿色代表通过,红色代表未通过。质量门禁(Quality Gate)不是简单地看一眼 bug 数量,而是由一组条件组成,例如“新增代码的 BUG 数不能为 0”“新增代码的重复率不超过 3%”等。默认门禁规则叫 Sonar Way,新项目可以直接用。
Overview 页面会把问题分成几类:可靠性相关的 Bugs,安全性相关的 Vulnerabilities,安全热点 Security Hotspots,可维护性相关的 Code Smells,还有单元测试覆盖率 Coverage 和重复率 Duplications。这些分类对应 SONAR 的核心公式:代码质量不只是“有没有 bug”,还包括“未来改代码时会不会踩雷、维护成本高不高”。
点击具体 issue,界面会跳到对应源码行,并显示规则说明和严重程度。我第一次跑成功时,看到空 catch 块直接被打上 Bug,还挺有成就感的。修复之后重新执行一次扫描,服务端会做增量对比,同一个 issue 的状态会从 Open 变成 Closed,这样就能看到代码质量的趋势变化。
有些团队只看单元测试覆盖率,这是不对的。静态分析的 Bug 和坏味道,和测试覆盖覆盖的是两个维度,Scanner 优势就是能发现“没被测试覆盖的逻辑分支里可能存在的空指针、资源泄漏、未处理异常”。所以报告里每个指标都值得认真看一遍。
5.2 高频问题速查表
这一路配置下来,问题集中在几个固定位置。我整理一个实战速查表,按出现频率从高到低排,值得收藏:
| 现象 | 最常见原因 | 排查和解决 |
|---|---|---|
Scanner 报SonarQube server can not be reached | sonar.host.url 配错,或 SonarQube 服务没启动 | 浏览器先访问 host.url,确认能打开 9000 页面;再检查配置里是否漏了http:// |
Scanner 报Unauthorized | token 错误、过期或者复制多了空格 | 在 My Account -> Security 重新生成 token,拷贝后确认没有多余字符 |
| 项目报告显示 0 行代码 | sources 路径不对,或 Java 项目没指定编译产物 | 检查 sonar.sources 是否指向真实源码目录;Java 项目补sonar.java.binaries |
| 分析报读不了某个文件 | 路径里有中文、空格或特殊字符 | 项目路径统一用英文,来源文件编码保持 UTF-8 |
| 中文注释乱码 | 文件是 UTF-8,但 sonar.sourceEncoding 没配 | 显式设置sonar.sourceEncoding=UTF-8,别依赖系统默认编码 |
| SonarQube 启动报数据库连接失败 | PostgreSQL 服务没启动,或 JDBC 配置有误 | 检查服务列表,确认sonar.jdbc.url的库名、ip、端口和密码 |
| 扫描速度特别慢 | 把 node_modules、target、dist 等生成目录都索引了 | 在 sonar.exclusions 里排除依赖和构建产物目录 |
| 启动后 9000 端口被占 | 别的进程占用了端口 | 修改 conf/sonar.properties 里的sonar.web.port,重启服务 |
| 服务端运行时内存不足 | 默认 JVM 堆不够,尤其大项目 | 打开 conf/wrapper.conf 调整 JVM 堆上限,然后重启 |
写这篇的时候我又重新在一台干净的 Windows 机器上按这个流程走了一遍,有一点感触特别深:这类工具链问题,九成出在版本和路径上,不是工具本身不行。你按这张表逐项排除,基本都能找到答案。