返回

解决SonarQube启动失败:禁止root运行及专用用户配置

Linux

搞定 SonarQube 启动后就停了的麻烦

哥们儿,搭 SonarQube 环境,有时候挺顺溜,有时候就给你整点幺蛾子。就像这次,跑 ./sonar.sh start 显示启动成功了,回头 ./sonar.sh status 一看,“Not running” —— 这感觉,真挺挠头的。

root@automation:/opt/sonarqube-7.8/bin/linux-x86-64# ./sonar.sh start
Starting SonarQube...
Started SonarQube.
root@automation:/opt/sonarqube-7.8/bin/linux-x86-64# ./sonar.sh status
SonarQube is not running.

遇到这情况,别慌,日志是咱最好的朋友。

问题在哪儿?扒一扒日志

看看 sonar.log 的关键信息:

--> Wrapper Started as Daemon
Launching a JVM...
# ... 省略一些启动信息 ...
2019.10.15 21:01:37 INFO  app[][o.s.a.AppFileSystem] Cleaning or creating temp directory /opt/sonarqube-7.8/temp
2019.10.15 21:01:37 INFO  app[][o.s.a.es.EsSettings] Elasticsearch listening on /127.0.0.1:9001
2019.10.15 21:01:37 INFO  app[][o.s.a.ProcessLauncherImpl] Launch process[[key='es', ipcIndex=1, logFilenamePrefix=es]] from [/opt/sonarqube-7.8/elasticsearch]: /opt/sonarqube-7.8/elasticsearch/bin/elasticsearch
2019.10.15 21:01:37 INFO  app[][o.s.a.SchedulerImpl] Waiting for Elasticsearch to be up and running
# ... Elasticsearch 插件加载信息 ...
2019.10.15 21:01:41 WARN  app[][o.s.a.p.AbstractManagedProcess] Process exited with exit value [es]: 1
2019.10.15 21:01:41 INFO  app[][o.s.a.SchedulerImpl] Process[es] is stopped
2019.10.15 21:01:41 INFO  app[][o.s.a.SchedulerImpl] SonarQube is stopped
<-- Wrapper Stopped

线索来了:Process exited with exit value [es]: 1Process[es] is stopped。这里的 es 指的是 Elasticsearch。SonarQube (从某个版本开始) 把 Elasticsearch 作为重要的内置组件,负责索引和搜索。现在是 Elasticsearch 进程启动失败,退出了,连带着整个 SonarQube 服务也停了。

那 Elasticsearch 为啥起不来?得看它的专属日志 es.log (logs/es.log):

2019.10.15 21:01:41 ERROR es[][o.e.b.Bootstrap] Exception
java.lang.RuntimeException: can not run elasticsearch as root
        at org.elasticsearch.bootstrap.Bootstrap.initializeNatives(Bootstrap.java:103) ~[elasticsearch-6.8.0.jar:6.8.0]
        # ... 省略堆栈跟踪 ...
        at org.elasticsearch.bootstrap.Elasticsearch.main(Elasticsearch.java:93) [elasticsearch-6.8.0.jar:6.8.0]

日志异常信息说得明明白白:java.lang.RuntimeException: can not run elasticsearch as root

根本原因:你用 root 用户启动了 SonarQube,而 SonarQube 内置的 Elasticsearch 出于安全考虑,默认禁止使用 root 账户运行。 这是 Elasticsearch 一个重要的安全特性,避免潜在的巨大风险。要是 Elasticsearch 以 root 权限运行,万一有漏洞被利用,攻击者就能拿到整个服务器的最高控制权,后果不堪设想。

怎么解决?安排!

既然找到病根了,对症下药就好。核心思路就是:别用 root 跑 SonarQube!

方案一:创建专用用户(推荐做法)

这是最正规、最安全的解决方案。给 SonarQube 创建一个单独的、非特权的系统用户来运行。

原理与作用:

通过专用用户运行服务,可以限制 SonarQube 进程及其子进程(包括 Elasticsearch)的文件系统访问权限和系统操作权限。就算 SonarQube 或 Elasticsearch 出现安全漏洞,攻击者能造成的破坏范围也被大大限制在这个用户的权限内,不会直接危及整个系统。这是 Linux/Unix 系统上部署服务的标准安全实践。

操作步骤:

  1. 创建用户和组:
    (如果已有合适的非 root 用户,可以跳过此步)
    创建一个名为 sonarqube (或者你喜欢的其他名字) 的用户和同名用户组。

    sudo groupadd sonarqube
    sudo useradd -s /bin/bash -g sonarqube -d /opt/sonarqube -m sonarqube
    # -s /bin/bash: 指定用户的登录 shell
    # -g sonarqube: 将用户加入 sonarqube 组
    # -d /opt/sonarqube: 指定用户的家目录 (可以根据你的 SonarQube 安装位置调整,但通常和安装目录区分开较好)
    # -m: 如果家目录不存在,则创建它
    # sonarqube: 新用户的用户名
    

    你也可以选择不创建家目录 -M 选项,或者指定一个已存在的目录。

  2. 修改 SonarQube 目录权限:
    将 SonarQube 的安装目录、数据目录、日志目录和临时目录的所有权都赋予新创建的 sonarqube 用户。假设你的 SonarQube 安装在 /opt/sonarqube-7.8

    sudo chown -R sonarqube:sonarqube /opt/sonarqube-7.8/
    # -R 表示递归修改,包括子目录和文件
    # sonarqube:sonarqube 表示用户是 sonarqube,组也是 sonarqube
    # /opt/sonarqube-7.8/ 是你的 SonarQube 安装路径,记得替换成你自己的实际路径!
    

    注意: 某些 SonarQube 版本可能还将数据、日志或临时文件放在安装目录之外,请根据 sonar.properties 文件中的 sonar.path.data, sonar.path.logs, sonar.path.temp 配置确认这些路径,并确保 sonarqube 用户对它们有读写权限。默认情况下,7.x 版本通常在安装目录下的 data, logs, temp 子目录。

  3. 切换用户并启动 SonarQube:
    susudo -u 命令切换到 sonarqube 用户,然后再启动 SonarQube。

    # 切换到 sonarqube 用户
    su - sonarqube
    # 或者,如果你不想完全切换 shell,可以用 sudo -u (可能需要配置 sudoers)
    # sudo -u sonarqube bash
    
    # 进入 SonarQube 的启动脚本目录
    cd /opt/sonarqube-7.8/bin/linux-x86-64/
    
    # 启动 SonarQube
    ./sonar.sh start
    
    # 检查状态
    ./sonar.sh status
    # 这次应该会显示 SonarQube is running...
    

安全建议:

  • 务必为 sonarqube 用户设置一个强密码(如果需要登录的话),或者使用 useradd -r 创建系统账户(通常无密码,无法直接登录,更安全)。
  • 严格控制 sonarqube 用户的 sudo 权限,原则上不给它 sudo 权限。
  • 定期审查 SonarQube 目录的权限设置。

进阶使用技巧:

  • 配置 systemd 服务: 为了让 SonarQube 能开机自启,并且总是以正确的用户身份运行,强烈建议配置一个 systemd 服务单元文件。
    创建一个 /etc/systemd/system/sonarqube.service 文件,内容类似这样:

    [Unit]
    Description=SonarQube service
    After=syslog.target network.target
    
    [Service]
    Type=forking
    ExecStart=/opt/sonarqube-7.8/bin/linux-x86-64/sonar.sh start
    ExecStop=/opt/sonarqube-7.8/bin/linux-x86-64/sonar.sh stop
    User=sonarqube
    Group=sonarqube
    Restart=always
    LimitNOFILE=65536 # 增加打开文件符限制
    LimitNPROC=4096  # 增加进程数限制
    
    [Install]
    WantedBy=multi-user.target
    

    重点: User=sonarqubeGroup=sonarqube 指定了运行服务的用户和组。记得修改 ExecStartExecStop 中的路径为你 SonarQube 的实际路径。

    然后启用并启动服务:

    sudo systemctl daemon-reload
    sudo systemctl enable sonarqube.service
    sudo systemctl start sonarqube.service
    sudo systemctl status sonarqube.service
    

    这样管理起来更方便、规范。

方案二:调整 Elasticsearch 配置(强烈不推荐用于生产环境)

如果你只是在本地开发或测试环境,临时想绕过这个限制,可以通过修改 Elasticsearch 的启动参数来实现。但这严重不推荐 在任何正式环境(包括开发、测试、预发布、生产)中使用,因为它会关闭重要的安全检查。

原理与作用:

Elasticsearch 有一个启动检查叫做 Bootstrap Checks,用来确保运行环境满足最低要求(比如不能用 root 运行、系统设置合理等)。通过设置特定的 Java 系统属性,可以强制禁用这些检查。

操作步骤 (以 SonarQube 7.8 为例):

早期 Elasticsearch 版本可能可以通过修改 elasticsearch.yml 实现,但在 6.x 及以后,官方推荐通过 JVM 参数。在 SonarQube 场景下,需要找到 SonarQube 启动 Elasticsearch 时传递的 JVM 参数配置。

  1. 修改 sonar.sh (不推荐,升级易丢失):
    直接编辑 /opt/sonarqube-7.8/bin/linux-x86-64/sonar.sh 脚本。找到启动 Elasticsearch 相关命令行的地方(可能比较隐蔽,或者是在某个调用的子脚本里)。你需要找到给 Elasticsearch JVM 添加参数的地方。这方法比较粗暴,升级 SonarQube 时修改会被覆盖。

  2. 设置环境变量 (相对好一点的方式):
    Elasticsearch 会读取 ES_JAVA_OPTS 环境变量。可以在启动 sonar.sh 之前设置这个环境变量。

    # 在启动前临时设置环境变量
    export ES_JAVA_OPTS="-Des.enforce.bootstrap.checks=false"
    ./sonar.sh start
    

    或者,考虑将这个环境变量设置添加到 sonarqube 用户的 ~/.bashrc/etc/profile.d/ 下的某个脚本中(如果你坚持要用这个方法,并配合方案一的专用用户,但仍然是禁用安全检查)。

    在 SonarQube 自身的配置文件中寻找:
    检查 conf/sonar.properties 或相关 Wrapper 配置文件 (conf/wrapper.conf) 是否有地方可以为 Elasticsearch 子进程添加 JVM 参数。这取决于 SonarQube 版本。对于 7.8,内置 Elasticsearch 的启动参数管理可能不直接暴露在 sonar.properties

    重点参数:
    要禁用的检查的关键 JVM 参数是 -Des.enforce.bootstrap.checks=false

安全警告!安全警告!安全警告!

  • 千万不要在生产环境这样做! 禁用 Bootstrap Checks 会让你的 Elasticsearch 和 SonarQube 暴露在极大的安全风险之下。
  • 即使在开发环境,这也是个坏习惯。最好从一开始就养成使用专用用户的习惯。
  • 如果用了这个方法,SonarQube 的日志里可能还会出现其他关于 Bootstrap Checks 失败的警告信息(比如内存限制、文件符限制等),这些也都是潜在的稳定性和性能问题。

还有哪些可能的问题?顺带检查下

虽然这次明确是 root 用户问题,但有时候 SonarQube 启动失败的原因五花八门。如果用了专用用户还是起不来,可以看看这些地方:

  1. 系统资源限制: Elasticsearch 对系统资源要求比较高。

    • 文件描述符(File Descriptors): Elasticsearch 需要大量的文件句柄。检查 ulimit -n 的值,对运行 SonarQube 的用户来说,这个值通常需要设置到 65536 或更高。可以通过修改 /etc/security/limits.conf 来持久化设置。
    • 虚拟内存(Virtual Memory): Elasticsearch 使用 mmap。检查 vm.max_map_count 的值,通常需要设置到 262144 或更高。可以通过 sysctl -w vm.max_map_count=262144 临时修改,并通过修改 /etc/sysctl.conf 来持久化。
    • 内存(RAM & JVM Heap): 确保服务器有足够的物理内存。检查 sonar.properties 和 Elasticsearch 的 JVM 配置 (config/jvm.options,如果 SonarQube 允许你修改的话),确保分配的堆内存(-Xmx, -Xms)没有超过可用物理内存,并且符合 SonarQube 的推荐值。
      conf/sonar.properties 中调整 SonarQube Web 服务器和 Compute Engine 的内存:
      # sonar.web.javaOpts=-Xmx512m -Xms128m ...
      # sonar.ce.javaOpts=-Xmx512m -Xms128m ...
      
      调整 SonarQube 内置 Elasticsearch 的内存(可能在 elasticsearch/config/jvm.options 或由 SonarQube 动态管理):
      # Example in jvm.options
      -Xms1g
      -Xmx1g
      
      务必保证总内存分配是合理的。
  2. 数据库连接: SonarQube 需要连接数据库(如 PostgreSQL, MySQL, Oracle, SQL Server)。检查 conf/sonar.properties 文件中的数据库连接配置 (sonar.jdbc.url, sonar.jdbc.username, sonar.jdbc.password) 是否正确,数据库服务是否运行,网络是否通畅,用户名密码是否有效,数据库用户权限是否足够。数据库连接问题通常会在 logs/web.loglogs/ce.log 中留下痕迹。

  3. 端口冲突: 检查 SonarQube 需要使用的端口(默认 HTTP 9000,Elasticsearch 通信端口 9001)是否已被其他进程占用。使用 netstat -tulnp | grep -E '9000|9001'ss -tulnp | grep -E '9000|9001' 查看。

  4. 文件系统权限: 再次确认 SonarQube 用户对安装目录、数据目录 (data)、日志目录 (logs)、临时目录 (temp) 及其子目录和文件有完全的读写执行权限。特别是 temp 目录和 data 目录下的 Elasticsearch 相关数据。

  5. 其他日志: 除了 sonar.loges.log,也要检查 logs/web.log (Web服务器日志) 和 logs/ce.log (Compute Engine 日志),它们可能包含启动失败的其他线索。

遇到 SonarQube 启动问题,细心查看日志,特别是 es.log,往往能直击要害。这次的问题就是典型的权限错误,遵循安全最佳实践,使用专用非 root 用户运行服务,基本就能稳妥解决。