简介:Nexus Repository Manager 3.50.0-01 的 Windows 64 位安装包,面向需要搭建 Maven 私服、统一管理构建产物的开发与运维团队,也适合学习制品仓库配置的初、中级工程师。压缩包共 690 个文件,约 240.15MB,以 jar 依赖库、dll 动态库、xml 配置和 exe 启动程序为主,另含 properties、cfg、yml 等运行配置及图标说明文件,呈现完整服务端发行结构。已有 494 人学习或下载。借助它可部署本地仓库服务,实践依赖代理、制品上传与版本归档流程,并通过权限控制和存储检索机制理解私服安全与性能优化;也可对照配置模块梳理 Karaf、JMX、证书等内容,为排错和团队协作提供参考。
1. 从 zip 到内网制品仓库:nexus-3.50.0-01-win64.zip 解压前该想清楚的三件事
很多人拿到nexus-3.50.0-01-win64.zip,第一反应是解压、双击nexus.exe、浏览器打开 8081 看到界面,就觉得装完了。真正让人卡住的是之后的事:服务装成 Windows Service 后改了内存不生效,仓库建好了客户端仍然 401,磁盘半年涨到 200G 才发现没人配清理策略。这个 zip 本身只是一个自带 JVM 启动脚本的 Java Web 应用分发包,它解决的是“在内网留一份可信的依赖与镜像来源”——Maven 每次拉包不再出网、npm 装依赖不再看公网脸色、Docker 镜像有一个自己说了算的地址。适合两类人:要给团队做统一依赖入口的后端和运维,以及只想在本机或小集群里缓存依赖、不想每次都重新下载的开发者。机器内存低于 4G、或者打算把它当公网 CDN 用的,先别急着上手。
2. 解压之后的目录与端口:nexus-3.50.0-01-win64.zip 里哪几个文件要动
2.1 解压后先认清四个目录:bin 是启动器,etc 才是配置
把 zip 解开,看到的目录结构不算复杂,但每个目录的角色差别很大,改错地方是新手最常见的翻车起点。我一般先tree /F看一层,再决定哪些文件要进版本管理、哪些绝对不能碰。
| 目录 | 关键文件 | 作用 | 能不能手动改 |
|---|---|---|---|
bin/ | nexus.exe、nexus.vmoptions | 启动器与 JVM 参数 | nexus.vmoptions必须改,其余别动 |
etc/ | nexus-default.properties、karaf/ | 端口、监听地址、数据目录、日志配置 | 可以改,改完重启生效 |
deploy/ | 空目录 | 放自定义插件 bundle | 不用碰 |
system/、lib/ | 大量 jar | 应用本体 | 绝对不要删改 |
public/ | 静态资源 | 前端页面 | 不要改 |
启动链路是这样的:nexus.exe先读同目录的nexus.vmoptions拿到一堆-D参数,拉起 JVM;JVM 里跑的是 Karaf 容器,容器去etc/读配置;etc/nexus-default.properties里的application-port、application-host、nexus-context-path决定浏览器怎么访问,karaf.data决定数据落在哪个盘。第一次启动会初始化数据目录,这个过程慢,一到三分钟都算正常,别盯着控制台以为卡死了——真正的进度在数据目录下的log/nexus.log里。
etc/nexus-default.properties里我通常会确认这三行:
# 监听所有网卡,否则只有本机能访问 application-host=0.0.0.0 # 端口冲突时改这里,别去改 vmoptions application-port=8081 # 反向代理到子路径时才改,改成 /nexus 后访问地址要带前缀 nexus-context-path=/这里的逻辑很直白:application-host默认是0.0.0.0,但有些同学从别处抄来的配置写成了127.0.0.1,结果本机浏览器能开、同事的机器一律超时,然后开始怀疑防火墙,其实是监听地址的问题。nexus-context-path改了就回不去——已经写进数据库的仓库地址不会跟着变,客户端里散落的 URL 全部要改,所以这一项要么一开始就定好,要么永远别动。
2.2 前台跑通再装服务:nexus.exe /run 与 /install 的区别
我强烈建议第一次启动用前台模式,出问题能直接看到堆栈。先确认本机 JDK 版本对得上,这一步别凭记忆:
# 先看本机 java 版本和 JAVA_HOME java -version $env:JAVA_HOME # 解压到 D 盘,路径里不要带空格和中文 Expand-Archive -Path .\nexus-3.50.0-01-win64.zip -DestinationPath D:\nexus Get-ChildItem D:\nexus路径里带空格是另一类经典事故:某些脚本拼接路径时没加引号,服务装上了但启动参数被截断,日志里只留下一行莫名其妙的 “could not find or load main class”。解压完进bin目录,前台跑:
cd D:\nexus\nexus-3.50.0-01\bin # 前台运行,Ctrl+C 停止,日志直接打屏 .\nexus.exe /run看到Started Sonatype...一类的启动完成日志,浏览器开http://127.0.0.1:8081,能出登录页就说明基础链路通了。默认管理员账号是admin,初始密码不在界面上,而在数据目录的admin.password文件里,登录后系统会强制你改,改完那个文件就自动删掉了——这一步别跳过,也别把新密码只记在脑子里。
前台验证通过,再装服务:
# 装成 Windows 服务,服务名自己定,别用默认的 nexus 撞名 .\nexus.exe /install nexus-repo .\nexus.exe /start nexus-repo .\nexus.exe /status # 卸载流程:先停,再删 .\nexus.exe /stop nexus-repo .\nexus.exe /uninstall nexus-repo/install做的事是把nexus.exe注册成一个由服务管理器托管的进程,并把当前目录记成工作目录。这里有个容易忽略的点:服务装好之后,nexus.exe /run和服务的日志是同一份,但进程环境变量不一样。前台跑的时候用的是你当前 PowerShell 会话里的JAVA_HOME,服务跑的时候用的是系统环境变量,两者不一致会导致“前台能起、服务起不来”。装服务之前,把JAVA_HOME配到系统变量里,别只配在用户变量。
2.3 内存怎么给:nexus.vmoptions 里三个数字的算法
bin/nexus.vmoptions是唯一需要动的手术刀位置。默认的堆是 2703m——这个数字不是随便写的,是给“能跑起来但不保证快”的场景留的余量。对内网十几个人用的仓库,我会直接给到 4G。
-Xms4096m -Xmx4096m -XX:MaxDirectMemorySize=4096m -XX:+UnlockDiagnosticVMOptions -XX:+LogVMOutput -Dkaraf.home=. -Dkaraf.base=. -Dkaraf.etc=etc/karaf # 数据目录挪到大盘,必须在首次启动前改好 -Dkaraf.data=D:/nexus-data -Dkaraf.log=D:/nexus-data/log -Djava.io.tmpdir=D:/nexus-data/tmp # Windows 上不加这行,中文包名和中文属性文件会乱码 -Dfile.encoding=UTF-8 # 内网有自签 CA 时用它,路径相对 bin 目录 -Djavax.net.ssl.trustStore=etc/ssl/truststore.jks -Djavax.net.ssl.trustStorePassword=changeit三个数字的关系要算清楚:-Xmx是 Java 堆,MaxDirectMemorySize是堆外直接内存,Nexus 处理上传下载和大文件校验时堆外吃得不少,再加上元空间、线程栈、JVM 自身的开销,实际占用大概是Xmx + DirectMemory + 1G。所以 16G 的机器给 4G 堆是安全的,8G 的机器给 2G,4G 的机器只能给 1G 并且别指望它扛 CI 全量拉取。把Xmx设成物理内存的 80% 是纯粹的自杀行为:系统开始换页,服务没死但每个请求都慢得像在泥里走,这种“活着但很难用”的状态比直接崩掉更难排查。
还有一条血泪经验:-Dkaraf.data只在首次启动前改有效。如果已经用默认路径跑过一次、生成了数据,再去改这一行,服务会用新目录重新初始化,你会以为“数据丢了”。真要迁移,正确做法是停服务、把整个数据目录拷到新位置、改配置、再启动,顺序不能错。
3. 仓库类型选型:proxy、hosted、group 三者怎么分工
3.1 三类仓库的职责边界与 group 成员顺序
Nexus 的仓库模型只有三种基本类型,理解了这三者的边界,后面所有格式(Maven、npm、Docker、PyPI、raw)都是同一套逻辑换个壳。
| 类型 | 数据从哪来 | 典型用途 | 客户端能不能写 |
|---|---|---|---|
| proxy(代理) | 从上游远程地址按需拉取并缓存 | 缓存中央仓库、缓存 npm 公共源 | 不能 |
| hosted(宿主) | 你自己上传 | 自研 jar、内部 npm 包、私有镜像 | 能 |
| group(分组) | 聚合多个 proxy 和 hosted | 给客户端一个统一入口 | 不能写,只能读 |
选型上没什么玄学:对外部依赖,建 proxy;对自研产物,建 hosted;给客户端,只暴露一个 group。这样开发同学的settings.xml和.npmrc里永远只写一个地址,后面你加减仓库他们完全无感。如果让每个人自己记住“jar 从这里下、自己的包往那里传”,三个月后一定会有人把 snapshot 传到 release 仓库里去。
group 有个特别容易被忽略的参数:成员顺序。group 解析时是自上而下匹配的,排在前面的仓库优先。所以正确的顺序是 hosted 在前、proxy 在后——自研包和公共包同名时(比如内部改过一个开源库),你希望拿到的是自己那份。反过来排,会出现“明明传了新版本,客户端拉到的还是公共仓库的老版本”这种看起来毫无道理的故障。
3.2 用 REST API 批量建仓库:一份 JSON 对应一个仓库
界面点几下就能建仓库,但要做三套环境(开发、测试、生产)就是重复劳动,还容易漏参数。我一般用 REST API 脚本化,把每个仓库写成一个 JSON 文件,建的时候循环提交。
先建 Maven 的代理仓库,maven-central-proxy.json:
{ "name": "maven-central-proxy", "online": true, "storage": { "blobStoreName": "default", "strictContentValidation": true }, "proxy": { "remoteUrl": "https://repo1.maven.org/maven2/", "contentMaxAge": 1440, "metadataMaxAge": 1440 }, "negativeCache": { "enabled": true, "timeToLive": 1440 }, "httpClient": { "blocked": false, "autoBlock": true, "connection": { "retries": 3, "timeout": 60, "enableCircularRedirects": false, "enableCookies": false } }, "maven": { "versionPolicy": "RELEASE", "layoutPolicy": "STRICT" } }| 参数 | 含义 | 怎么定 |
|---|---|---|
remoteUrl | 上游地址 | Maven 填中央仓库根路径,注意结尾斜杠 |
contentMaxAge | 已缓存构件的有效期(分钟) | 1440,一天; jar 基本不变,可以更长 |
metadataMaxAge | 元数据有效期(分钟) | 1440,太短会频繁回源拖慢构建 |
negativeCache.timeToLive | 找不到的构件缓存多久(分钟) | 1440;调太小会把“不存在的包”反复回源 |
autoBlock | 上游连续失败后自动熔断 | 保持 true,防止上游挂了拖死自己 |
strictContentValidation | 内容校验 | 保持 true,能挡掉一批投毒包 |
提交:
# 用户名密码走 basic auth,建议用专门的服务账号而不是 admin curl -u admin:YourPassword -X POST \ "http://127.0.0.1:8081/service/rest/v1/repositories/maven/proxy" \ -H "Content-Type: application/json" \ -d @maven-central-proxy.jsonWindows 上不想装 curl,用 PowerShell 等价写法,注意-InFile传的是文件路径:
$cred = Get-Credential Invoke-RestMethod -Uri "http://127.0.0.1:8081/service/rest/v1/repositories/maven/proxy" ` -Method Post -Credential $cred -ContentType "application/json" ` -InFile .\maven-central-proxy.jsonhosted 仓库的 body 短很多,关键在writePolicy:
{ "name": "maven-releases", "online": true, "storage": { "blobStoreName": "default", "strictContentValidation": true, "writePolicy": "ALLOW_ONCE" }, "maven": { "versionPolicy": "RELEASE", "layoutPolicy": "STRICT" } }writePolicy取值里ALLOW_ONCE表示同一个路径只允许写一次,这是 release 仓库该有的约束——版本一旦发出去就不该被悄悄替换,否则线上问题追溯时你根本不知道跑的是哪份包。snapshot 仓库则要用ALLOW,允许覆盖。很多人图省事全设成ALLOW,半年后遇到“同样的 1.2.0 在两个环境行为不一致”,那就是纯粹的后悔药没处买。
group 仓库最后建,body 里指定成员顺序:
{ "name": "maven-public", "online": true, "storage": { "blobStoreName": "default", "strictContentValidation": true }, "group": { "memberNames": ["maven-releases", "maven-snapshots", "maven-central-proxy"] } }memberNames的数组顺序就是解析优先级,自研在前、代理在后,和上面说的是同一件事。
3.3 两个必须提前打开的 realm:npm Bearer Token 与 Docker Bearer Token
这一条是纯踩坑换来的:仓库建好了、账号权限也给了,npm publish和docker push死活 401,日志里写着 token 校验失败,人就开始怀疑人生。
原因是 Nexus 默认只启用基础的认证 realm,npm 和 Docker 这两种协议用的令牌认证机制默认是关闭的。去Security → Realms,把npm Bearer Token Realm和Docker Bearer Token Realm从 Available 挪到 Active,保存。注意顺序:基础的NexusAuthenticatingRealm必须留在列表最上面,挪到下面会导致所有账号登录失败。
改完不用重启,但已经登录的客户端要重新登录一次,本地的 token 缓存不会自动失效。npm logout再npm login,docker logout再docker login,这两步别省,否则你会以为配置没生效。
4. 客户端接入实战:settings.xml、.npmrc 和 docker 私有端口的配置
4.1 Maven:mirrorOf 写错,插件下载全走公网
~/.m2/settings.xml里两处配置最容易混:<mirrors>管下载走哪,<servers>管认证凭据。它们靠id关联,但关联的不是同一个东西。
<settings> <mirrors> <mirror> <!-- id 随便取,但下面 server 里要有一份同名的 --> <id>nexus</id> <!-- external:* 表示除 localhost 和 file:// 之外全部走镜像 --> <mirrorOf>external:*</mirrorOf> <url>http://nexus.internal:8081/repository/maven-public/</url> </mirror> </mirrors> <servers> <server> <id>nexus</id> <username>deployer</username> <password>明文密码,生产环境用 mvn -ep 加密后填这里</password> </server> <server> <id>nexus-releases</id> <username>deployer</username> <password>同上</password> </server> <server> <id>nexus-snapshots</id> <username>deployer</username> <password>同上</password> </server> </servers> </settings>mirrorOf的值决定了代理范围,这几种写法的差别很实在:
| 写法 | 效果 | 适用场景 |
|---|---|---|
* | 所有仓库请求都走 Nexus | 完全隔离的内网,最省事 |
external:* | 除 localhost 和 file 协议外都走 Nexus | 推荐,本地私服调试不受影响 |
central | 只代理中央仓库 | 项目里还有别的私服时用 |
*,!internal-repo | 除指定仓库外全代理 | 需要保留个别直连时用 |
写成central是最常见的误用:pom 里声明的第三方仓库(比如某个中间件厂商的仓库)不会被镜像,依然直连公网,在隔离环境里直接构建失败,报错信息是“Could not resolve dependencies”,看不出是镜像没覆盖到。
上传则要在 pom 里写distributionManagement,这里的id必须和servers里的id一一对应,跟 mirror 的id没关系:
<distributionManagement> <repository> <id>nexus-releases</id> <url>http://nexus.internal:8081/repository/maven-releases/</url> </repository> <snapshotRepository> <id>nexus-snapshots</id> <url>http://nexus.internal:8081/repository/maven-snapshots/</url> </snapshotRepository> </distributionManagement>mvn deploy时如果报 401,先看这里的id拼写,九成是两边对不上。
4.2 npm:一条 .npmrc 把读和写分开
npm 的坑在于读和写是两个地址。读走 group(能同时看到公共源和内部包),写只能走 hosted(group 不可写)。这两件事用一条.npmrc说清楚:
# 默认读:走 group registry=http://nexus.internal:8081/repository/npm-group/ # 内部作用域的包也走 group @internal:registry=http://nexus.internal:8081/repository/npm-group/ # 两个地址各自的 token,路径要和上面严格对应 //nexus.internal:8081/repository/npm-group/:_authToken=NpmToken.xxxxxxxx //nexus.internal:8081/repository/npm-hosted/:_authToken=NpmToken.xxxxxxxx # 内网 http 协议,必须关掉严格 ssl 校验 strict-ssl=false always-auth=true几个细节值得单独说。第一,_authToken前面那一串不是域名,是“协议 + 主机 + 端口 + 仓库路径”,写错一个字符就等于没配,而且不会报错,只会 401。第二,strict-ssl=false只在纯内网 http 场景下用,如果 Nexus 前面挂了 https 反向代理,这一行要删掉,否则等于自己给自己降级。第三,always-auth=true保证每次请求都带凭据,避免缓存过期后偶发的 401。
发布时显式指定仓库,别指望 registry 自动切换:
# 登录一次,凭据会被写进 .npmrc npm login --registry http://nexus.internal:8081/repository/npm-hosted/ # 发布必须显式指向 hosted npm publish --registry http://nexus.internal:8081/repository/npm-hosted/如果这台机器同时连着多个 Registry,加--registry参数是最稳的做法,比改全局配置靠谱得多。
4.3 Docker:connector 端口、insecure-registries 与 docker login
Docker 仓库和别的格式有个根本差别:它必须占一个独立端口。不能复用 8081,因为 Docker Registry 协议对 URL 路径结构有硬性要求。建 docker hosted 仓库时,在仓库设置里勾上 HTTP 的 connector,填一个空闲端口,比如 8082,并在Allow anonymous docker pull上按需选择。
建完之后,客户端这台机器要告诉 Docker 守护进程“这个地址是走明文的”:
{ "insecure-registries": ["nexus.internal:8082"], "registry-mirrors": [] }改完daemon.json要重启 Docker 服务才生效,Windows 上在 Docker Desktop 的设置里改更省事。然后:
docker login nexus.internal:8082 -u deployer docker tag app:1.0 nexus.internal:8082/app:1.0 docker push nexus.internal:8082/app:1.0 docker pull nexus.internal:8082/app:1.0docker push时报http: server gave HTTP response to HTTPS client,就是insecure-registries没生效或者拼写不一致(端口漏了也算不一致)。报unauthorized: authentication required,先回去检查 3.3 节说的 Docker Bearer Token Realm 开没开。
如果想让客户端只记一个地址,就建一个 docker group 仓库,把 hosted 和 proxy 加进去,group 自己绑一个端口。代价是 group 里的成员仓库如果各自也绑了端口,客户端可能要从不同端口登录,凭据不通用——所以规范的做法是:group 只绑一个对外端口,成员仓库不绑端口,全部通过 group 访问。
5. 排查与避坑:Windows 上跑 Nexus 最容易翻车的 5 个现场
5.1 服务显示 running,8081 死活连不上
现象:nexus.exe /start返回成功,/status显示服务在跑,但浏览器和 curl 一律超时,任务管理器里能看到 java 进程,CPU 占用接近零。
原因:服务托管层只负责拉起进程,进程自己因为 JVM 参数不合法(最常见是-Xmx超过物理内存,或者-Dkaraf.data指向一个没权限的路径)启动到一半就退出了,托管层还没来得及更新状态。真正的原因全在数据目录的log/nexus.log尾部。
解决:别在服务模式里瞎猜,直接nexus.exe /stop然后用nexus.exe /run前台跑一次,异常堆栈会直接打在控制台。同时确认三件事:JAVA_HOME配在系统变量而不是用户变量;数据目录所在盘有写权限(服务默认以 LocalSystem 跑,网络盘和某些同步盘目录会失败);nexus.vmoptions里的路径用的是正斜杠D:/nexus-data,用反斜杠在某些版本里会被当成转义符。
5.2 上传 jar 报 400,提示仓库不允许更新
现象:mvn deploy失败,返回 400,错误信息里带Repository does not allow updating assets之类的字样。
原因:往maven-releases这个 hosted 仓库重复部署了同一个版本号。release 仓库的writePolicy设的是ALLOW_ONCE,这是设计上的约束而不是 bug——发出去的版本就该不可变。
解决:正规做法是升版本号重发。如果确实是发错了要补救,在界面上对该构件执行删除再重发,但这属于破坏性操作,删之前确认没有别的项目已经依赖它。想避免这类来回,团队里约定一条:日常联调用 snapshot,只有准备上线的版本才进 release。
5.3 npm 装包卡住几十秒然后超时
现象:npm install每条依赖都要等很久,最后报ETIMEDOUT或ECONNRESET,但浏览器访问上游地址是通的。
原因:Nexus 作为代理去拉上游时用的是 JVM 自己的证书链和网络栈,Windows 上常见两种情况:企业内网有自签 CA,JDK 的cacerts里没有;或者上游对某些请求做了限流、需要走代理。
解决:拿到内网根证书,导入 Nexus 用的那个 JDK 的信任库,或者用 2.3 节里的-Djavax.net.ssl.trustStore指向一个独立的 truststore:
keytool -importcert -noprompt -alias corp-root-ca \ -file corp-root-ca.crt \ -keystore etc/ssl/truststore.jks \ -storepass changeit同时在仓库设置里把HTTP request settings的连接超时和读取超时调大(默认值对慢链路偏紧),retries给到 3。排查阶段最有效的一招是看log/nexus.log里带Remote storage的行,那里会写清楚到底是 DNS 解析失败、TLS 握手失败还是 407。
5.4 磁盘半年涨到 200G,删了包空间也不回来
现象:D 盘报警,仓库里明明删了很多构件,可用空间几乎没变化。
原因:Nexus 的存储是 blob store 加数据库索引两层。界面上删除只是把索引标记成不可见,物理 blob 文件还在;没有配 cleanup policy 的代理仓库会把上游拉过的每个版本都永久留着,CI 每天全量拉一次,缓存只会单向往上涨。
解决:分三步走。先建 cleanup policy(Repository → Cleanup Policies),按格式选 maven2 或 npm,条件一般设“最后下载超过 90 天”加“保留最近 N 个版本”;再把 policy 关联到代理仓库和 snapshot 仓库;最后手动跑两个任务:Admin - Cleanup repositories using their associated policies清索引,Admin - Compact blob store真正回收磁盘。第二步不做,第一步等于白干。
5.5 备份只拷了 blob store,恢复后元数据全丢
现象:机器重装,把 blob store 目录拷回来,启动后仓库列表是空的,或者仓库在但里面的构件全部显示不可用。
原因:只备份了文件,没备份数据库。仓库名、权限、构件与 blob 的映射关系全在数据目录的数据库文件里,blob 只是一堆没有名字的二进制。
解决:备份必须包含数据目录下的数据库文件和 blob store 两部分,并且要在停机状态下做,或者用内置的Admin - Export databases for backup任务导出一致性快照。热拷贝正在写入的数据库,恢复出来的索引大概率是坏的——这一点上省的那几分钟停机,后面要用几个小时来还。
6. 备份、清理与一次恢复演练:把仓库养到第二年
仓库这类基础设施的通病是:上线那天所有人都在用,之后就没人再看它,直到某天磁盘满或者数据坏了。我一般在上线第一周就把备份和清理定下来,不给自己留后悔的余地。
备份对象其实就两块,列清楚比记在脑子里可靠:
| 备份对象 | 位置 | 方式 | 恢复要点 |
|---|---|---|---|
| 数据库与配置 | 数据目录下的数据库文件、etc/ | 停服务冷备,或用 export 任务导出 | 必须与 blob 同批次 |
| 构件本体 | blob store 目录 | 文件级增量同步 | 权限和属主保持一致 |
清理策略的参数不要拍脑袋。我的经验值是:代理仓库的“最后下载超过 90 天”就可以清,因为超过三个月没人拉的版本,大概率下次也不会有人拉;snapshot 仓库按“保留最近 10 个版本”加“超过 30 天未更新”双条件,防止某个长期不动的快照被误留;release 仓库原则上不清,它本来就是只增不改的。跑完 cleanup 一定要接着跑 compact,否则空间只是从“可见”变成“不可见”。
验证比配置更重要。我习惯在每次变更后跑一条固定命令,比对状态码和字节数,比打开网页点两下靠谱得多:
# 状态码 200 且 size 大于 0 才算这条链路是通的 curl -s -o /dev/null -w "%{http_code} %{size_download}\n" \ http://nexus.internal:8081/repository/maven-public/org/springframework/spring-core/5.3.30/spring-core-5.3.30.jar真要做恢复演练,别在生产上试。找一台空机器,装一个同版本的nexus-3.50.0-01-win64.zip,把备份的数据目录和 blob store 按原路径放回去,启动后随机抽三个仓库各拉一个构件、推一个构件。这套演练我做过两次,第二次才发现备份脚本漏了etc/目录——恢复出来的实例仓库都在,但所有仓库的上游地址和认证配置全丢了,等于要重配一遍。教训很朴素:备份不验证,等于没备份;配置文件和数据一样重要。希望帮到你。
本文还有配套的精品资源,点击获取