Nexus Repository Manager 启动失败排查全记录

某天早上收到告警,Nexus 制品仓库无法访问。登录服务器检查,systemd 报告服务状态正常,实则 Java 进程根本不存在,端口未监听。本文记录完整的排查与修复过程。

背景

$ systemctl status nexus
Active: active (exited) # 假正常

$ ps aux | grep java | grep nexus
# 空,Java 进程不存在

$ ss -tlnp | grep 8081
# 空,端口未监听

$ curl -s -o /dev/null -w "%{http_code}" http://localhost:8081
000 # 连接拒绝

active (exited) 是 init.d 风格的 SysV 脚本包装下的常见假象——启动脚本执行完就退出了,但它拉起的 Java 进程随后悄悄崩溃,systemd 毫无感知。


排查过程

第一步:定位真实安装路径

Nexus 并未安装在默认路径,需要先找到实际位置:

cat /etc/rc.d/init.d/nexus | grep -E 'NEXUS_HOME|data-dir|work'
find / -name "sonatype-work" -type d 2>/dev/null

确认路径:

  • 程序目录:/opt/nexus/nexus-3.19.1-01
  • 数据目录:/data/nexus/sonatype-work/nexus3

第二步:查看应用日志

tail -n 100 /data/nexus/sonatype-work/nexus3/log/nexus.log

日志只有 WARN 级别的 SSL 错误,全是 maven-osgeo 代理仓库的 SSLHandshakeException,没有 ERROR 或启动失败的痕迹。说明这次崩溃发生在日志系统初始化之后但写入之前,或者是更深层的问题。

第三步:前台运行,直接看报错

su - nexus -s /bin/bash -c "/opt/nexus/nexus-3.19.1-01/bin/nexus run" 2>&1 | head -50

终端立即出现关键错误:

ERROR - java.io.FileNotFoundException:
/data/nexus/sonatype-work/nexus3/db/component/component.24003.wal
(Permission denied)

ERROR - Cannot open local storage '/data/nexus/sonatype-work/nexus3/db/component' with mode=rw

根因找到:OrientDB 的 WAL(Write-Ahead Log)文件权限异常,nexus 用户无法写入。

第四步:验证权限问题

ls -la /data/nexus/sonatype-work/nexus3/db/component/*.wal
# -rw-r--r-- 1 nexus nexus ... ← 644,nexus 用户只有读权限

ls -la /data/nexus/sonatype-work/nexus3/db/config/*.wal
# -rw-r--r-- 1 nexus nexus ... ← 同样是 644

OrientDB 需要对 WAL 文件有写权限才能以 rw 模式打开存储。


根本原因分析

三个问题叠加导致服务无法启动:

# 问题 根因
1 WAL 文件 Permission Denied 某次 root 用户直接操作了 db 目录(备份、手动修复等),导致文件归属或权限被改写
2 lock / karaf.pid 残留 上次异常退出未正常清理锁文件,Nexus 启动时认为实例已运行,直接退出
3 systemd 无法追踪进程 使用 Type=forking + PIDFile,但 Nexus 写 PID 文件有延迟,systemd 判定启动失败并触发 Restart 循环

解决方案

修复一:恢复数据库文件权限

# 递归修复所有文件归属
chown -R nexus:nexus /data/nexus/sonatype-work/nexus3/

# 修复目录和文件权限
find /data/nexus/sonatype-work/nexus3/db -type d -exec chmod 755 {} \;
find /data/nexus/sonatype-work/nexus3/db -type f -exec chmod 664 {} \;

修复二:清理残留锁文件

rm -f /data/nexus/sonatype-work/nexus3/lock
rm -f /data/nexus/sonatype-work/nexus3/karaf.pid
rm -f /data/nexus/sonatype-work/nexus3/port

修复三:重写为原生 systemd 服务

原来的 init.d 包装脚本有两个核心缺陷:

  • systemd 无法感知实际的 Java 进程状态
  • Type=forking 依赖 PID 文件时序,不稳定

正确做法:使用 Type=simple + nexus run(前台模式),让 systemd 直接管理 Java 进程。

# 禁用旧的 init.d 服务
chkconfig nexus off

# 创建原生 systemd unit 文件
cat > /etc/systemd/system/nexus.service << 'EOF'
[Unit]
Description=Sonatype Nexus Repository Manager
After=network.target

[Service]
Type=simple
LimitNOFILE=65536
User=nexus
Group=nexus
Environment=JAVA_HOME=/opt/jdk1.8.0_74

# 每次启动前自动清理残留锁文件
ExecStartPre=/bin/bash -c "rm -f /data/nexus/sonatype-work/nexus3/lock \
/data/nexus/sonatype-work/nexus3/karaf.pid \
/data/nexus/sonatype-work/nexus3/port"

# 使用 run 以前台方式运行,systemd 可直接追踪进程
ExecStart=/opt/nexus/nexus-3.19.1-01/bin/nexus run
ExecStop=/opt/nexus/nexus-3.19.1-01/bin/nexus stop

# 异常退出后自动重启
Restart=on-failure
RestartSec=30
TimeoutStartSec=300
TimeoutStopSec=120

[Install]
WantedBy=multi-user.target
EOF

# 重载并启动
systemctl daemon-reload
systemctl enable nexus # 开机自启
systemctl start nexus

验证结果

$ systemctl status nexus
● nexus.service - Sonatype Nexus Repository Manager
Active: active (running) since Thu 2026-05-07 11:06:19 CST
Main PID: 28549 (java) # 真实 Java 进程
Memory: 3.1G

$ ss -tlnp | grep 8081
LISTEN 0 50 *:8081 *:* users:(("java",pid=28549,fd=953))

$ curl -s -o /dev/null -w "%{http_code}" http://localhost:8081
200

遗留优化:SSL 证书问题

服务恢复后,日志中仍持续出现 maven-osgeo 代理仓库的 SSL 错误:

SSLHandshakeException: PKIX path building failed
→ unable to find valid certification path to requested target

原因是 JDK 1.8.0_74(2016年构建)的信任链中没有 repo.osgeo.org 的新证书。

方案 A(推荐):在 Web UI 中将 maven-osgeo 的 Remote URL 替换为可用镜像,或直接禁用该仓库。

方案 B:手动将证书导入 JDK 信任库:

openssl s_client -connect repo.osgeo.org:443 -showcerts </dev/null 2>/dev/null \
| openssl x509 -outform PEM > /tmp/osgeo.crt

/opt/jdk1.8.0_74/bin/keytool -import \
-alias osgeo-cert \
-keystore /opt/jdk1.8.0_74/jre/lib/security/cacerts \
-file /tmp/osgeo.crt \
-storepass changeit -noprompt

systemctl restart nexus

经验总结

排查思路

  1. active (exited) ≠ 服务正常,必须验证实际进程和端口
  2. 应用日志没有新内容时,用前台运行模式(run)直接看终端输出
  3. Permission Denied 类错误优先检查文件归属,而非权限位

防御措施

  • 任何对 Nexus 数据目录的运维操作,完成后必须执行 chown -R nexus:nexus
  • 将 SysV init.d 服务迁移为原生 systemd unit,获得真实的进程生命周期管理
  • ExecStartPre 自动清理锁文件,消除异常重启后的残留问题
  • 定期检查 systemctl status nexus 是否真的有 Main PID

排查日期:2026-05-07
环境:CentOS 7.6 / Nexus OSS 3.19.1-01 / JDK 1.8.0_74