Linux生产环境Oracle 19c安装配置实战:从规划到交付
上周刚帮一个项目组处理完一套生产环境 Linux 服务器上的 Oracle 19c 部署。系统装完、Oracle 软件也装完、库也建起来了,结果应用连不上。排查到最后,问题出在安装阶段选库型时少勾了一个选项。虽然十分钟就能改,但要是按项目交付计划来算,这十分钟往往就变成加班两小时,新上线的系统顶着压力,所有人都在旁边盯着。
FGMT02 这个专题我想写很久了,就是围绕生产环境里 Linux + Oracle19c 从选型、系统准备、软件安装、建库到项目实战验证的完整过程。内容不绕弯,直接讲安装配置里那些真正影响交付的点,同时也会结合一些项目实战环节,说说装完之后不能直接甩手走的原因。
这篇东西适合三类人看:一是刚从测试环境转入生产环境的运维实施,二是开发环境自己搭库的应用开发,三是刚接手 Oracle 维护任务、需要快速建立整体认知的初级 DBA。不管你是打算用图形界面一步步点,还是想用静默安装把所有过程脚本化,这篇文章都会覆盖到。
1. 为什么要把安装配置单独做成 FGMT02:生产环境不是测试环境加几个核
1.1 测试环境装十分钟,生产环境为什么可能装一天
很多人在自己电脑或者测试服务器上安装过 Oracle:虚拟机一开,走一遍图形安装向导,中间跳过各种警告,最后看到 Database Configuration Assistant 建库进度条走完,就以为大功告成。但生产环境完全不是这个套路。
生产环境有三个测试环境不会暴露的问题:第一是稳定性和可维护性要求极高,装错一个参数,当时可能没事,运行三个月后爆发问题,到时候再排查代价极高;第二是故障窗口有限,项目上线时间定了,安装配置必须在窗口内完成,没有反复试错的机会;第三是交付物不止是一个数据库,还包括备份策略、监控接入、连接配置、上线检查记录。
所以我在 FGMT02 里一直强调的是:安装配置不是“跑完安装向导”就行,而是要在动手之前把版本、目录、内存、文件系统、备份空间全部规划好。一个人在测试环境装好库是熟练工,一个人在生产环境装好库还能让后续运维不踩坑,才是真本事。
1.2 版本基线:先确定你要装的是 19.3 还是最新 Release Update
Oracle 19c 是很多生产系统现在的主力版本,理由很简单:它是长期支持版本,补丁更新节奏稳定,不像 21c 这种创新版本,很多生产团队根本不把它纳入选型。但在实际安装时,你手里拿到的可能是一套最原始的 19.3 安装介质,也可能是一套已经集成补丁的安装包。
这里有一个实践中的建议:新装生产库,不要直接用最原始介质装完就交付。正确做法是安装完软件后,马上把补丁基线提升到当前最近的 Release Update(RU),然后运行 datapatch 把数据库字典也升级到对应版本。如果项目对补丁版本有内部要求,就按变更管理流程确定一个具体 RU 编号。
判断当前补丁情况的方法很直接。在 Oracle 软件安装目录下执行:
如果输出为空或者只能看到 19.3 的基线补丁编号,说明这个环境还是“裸”的,需要补丁操作。补丁的顺序有讲究:先打 OPatch 工具本身,再打数据库补丁,最后用 datapatch -verbose 把 SQL 变更应用到数据库。我在实际项目中见过不少人打完补丁忘了跑 datapatch,结果数据库版本显示正常,但运行一些动态视图时报错或者行为异常,这种问题很隐蔽。
1.3 部署前必须写进方案的规划清单
每次做生产部署,我都会先在方案里列一张表,把下面这些项目逐一填完,才允许实际操作:
| 规划项 | 需要确认的内容 | 备注 |
|---|---|---|
| 操作系统版本 | RHEL/CentOS/Oracle Linux/麒麟的版本与内核 | 必须与 Oracle 官方支持矩阵对照 |
| 主机名和 IP | 固定 IP、主机名、域名、静态解析 | 动态 IP 在集群和监听里容易出问题 |
| 存储挂载方案 | /u01 挂载点、数据文件路径、恢复区路径 |
根分区不要和数据库文件抢空间 |
| 目录规划 | ORACLE_BASE、ORACLE_HOME、oraInventory | 避免装到 /opt 或 /home 下 |
| 实例与库型 | 实例名、服务名、CDB/PDB 还是 non-CDB | 建库后改动成本极高 |
| 字符集时区 | AL32UTF8、时区、国家字符集 | 字符集建库后修改非常麻烦 |
| 内存规划 | SGA/PGA、MEMORY_TARGET、HugePages | 取决于物理内存和并发量 |
| 备份空间 | 快速恢复区大小、归档空间保留天数 | 不提前规划,上线后必出事 |
这张表看着繁琐,但每一项都对应着实际踩过的坑。比如主机名没提前固定,安装过程中改了主机名,监听器启动后注册的是旧名字,应用拿新名字连就是连不上;再比如恢复区空间只给了 10G,一个周末跑完就满了,数据库直接罢工。生产环境安装配置,本质上就是把这些琐碎决策在动手前全部定死。
2. Linux 侧准备:真正让人栽跟头的是这些参数
2.1 操作系统版本与依赖包准备
Oracle 19c 对操作系统版本有明确的支持列表,通常集中在 Red Hat Enterprise Linux 7/8、Oracle Linux 7/8 这类发行版上。现在也有不少人在麒麟操作系统 v10 上装单机,基本思路一致,但需要手动做更多准备工作,因为很多 Oracle 预安装包没有现成 RPM 可以直接用。
在常规 Linux 上,最简单的方式是安装 oracle-database-preinstall 这个 RPM。它会把后续 Oracle 安装所需的系统包、用户、内核参数一次配好。但生产环境里我仍然建议逐步过一遍,因为实际交付时你总要给客户解释每一处配置的作用。
如果手动安装依赖包,可以参考下面这组包列表:
这个列表并不算特别长,但有两个容易漏掉的地方。第一个是 compat-libstdc++-33,在较新的 Linux 版本上已经不是默认安装,少它会导致安装程序的环境检查直接失败。第二个是 libXp 相关库,图形安装时如果 DISPLAY 设置好了但界面就是弹不出来,经常就是缺少 X11 相关的几个库。
另外,Oracle 客户端的 Instant Client 或者应用中如果用到 ODBC,还需要保证 unixODBC 版本和位数一致。64 位环境和 32 位库混用的问题,在安装阶段通常不明显,但后续开发人员来连库时会出现各种莫名其妙的错误。
2.2 内核参数、资源限制和透明大页
内存和内核参数的配置是 Linux 侧最容易出问题的部分,也是很多安装警告的来源。Oracle 19c 的安装向导会检查好多项内核参数,但那些参数并不是“凑够检查”就结束了,它们直接影响数据库运行时的内存分配。
常用的一组内核参数参考如下:
很多人对 kernel.shmmax 有误解。早期版本里经常要求它大于内存的一半,但在 19c 里,只要使用共享内存文件系统和自动内存管理,shmmax 的值并不需要盲目调到极大。真正的关键是 kernel.shmmni 信号量数量和各进程的资源限制。
资源限制文件 /etc/security/limits.conf 里,至少要给 oracle 用户配置下面几项:
这里最容易被忽略的是 nproc。如果它没配好,数据库正常连接数一多,操作系统层面就开始不给 oracle 用户分配新进程,应用侧表现为连接池爆满,但数据库告警日志里却看不到明显报错。我第一次碰到这个问题时排查了大半天,最后才想到是系统资源限制导致的。
透明大页(Transparent HugePages,THP)在数据库服务器上也是建议关闭的。Oracle 官方和大量生产实践都表明,THP 会在数据库分配大量共享内存时造成性能抖动。关闭方法有两种,最彻底的是在 GRUB 内核启动参数里追加 transparent_hugepage=never,然后重启;如果暂时不能重启,可以临时执行:
重启后可以通过 /sys/kernel/mm/transparent_hugepage/enabled 里的方括号位置确认当前状态。方括号在 never 上才说明已经生效。
2.3 用户、目录和权限
Oracle 软件不建议用 root 用户运行安装程序。生产环境里几乎都是创建独立的 oracle 用户,并指定两个组:oinstall 作为软件 Inventory 所有者,dba 作为 DBA 管理组。
创建用户和目录的典型步骤:
这里有一个细节:/u01/app/oracle 的属主必须是 oracle,但安装过程中的 oraInventory 目录默认会放在 /u01/app/oraInventory。如果你的安装用户对 /u01/app 只有读权限,执行到 Inventory 创建时就会失败。所以在初始化目录时,最好把 /u01/app 的属主也规划好,或者直接使用响应文件指定 INVENTORY_LOCATION。
oracle 用户的环境变量在安装前就要配好,至少包括:
注意 ORACLE_HOME 在安装前也可以先不建目录,但环境变量里的路径要和安装时填写的路径完全一致。很多人在 sqlplus 启动时报找不到共享库,就是环境变量和实际安装路径不一致导致的。
3. 软件安装:图形安装与静默安装两条路径的实战对比
3.1 图形安装的关键流程
如果现场允许图形桌面或者可以配置 X 转发,用图形安装是最直观的方法。但这并不意味着可以无脑下一步。
安装介质解压后,用 oracle 用户进入 database 目录,先确认 DISPLAY 环境变量被正确设置。如果是远程 X11 转发,本地要运行 X Server,同时确认 SSH 的 X 转发没有禁用。图形界面迟迟不弹出来时,大多数情况不是安装程序的问题,而是 X11 转发链路断了。
进入安装向导后,有一个关键选择:选择“仅安装数据库软件”还是“安装软件并建库”。我建议生产环境第一次部署时,选择仅安装数据库软件,把建库动作交给下一步的 DBCA 单独执行。原因很简单:安装向导里的建库选项默认配置不一定符合项目的表空间和字符集要求,等到后面发现不符合,重新建库的代价远高于现在多花十分钟手动配置。
执行到安装过程结尾时,安装程序会提示用 root 执行两个脚本:/u01/app/oraInventory/orainstRoot.sh 和 $ORACLE_HOME/root.sh。这里必须先执行 orainstRoot.sh 再执行 root.sh,顺序不能反。root.sh 执行时会读取环境变量 ORACLE_HOME,如果通过 su 切换到 root 后环境变量丢失,执行会报错。可以用 su - root 后手动 export 一次 ORACLE_HOME,再执行。
3.2 静默安装:响应文件才是效率关键
生产环境的服务器很多时候是无桌面的,这时更实用的方式是静默安装。它的核心是一个 responseFile,也就是响应文件,里面包含了图形向导中的所有选项。
一条典型的静默安装命令:
其中 -waitforcompletion 表示安装程序会等待安装结束才返回命令行。如果不加这个参数,安装进程会放到后台,响应文件里的错误需要看日志才能发现。对于脚本化部署来说,建议加上。
响应文件里几个核心配置项如下:
注意 DECLINE_SECURITY_UPDATES 必须明确设为 true,除非你真的会在安装时填写 My Oracle Support 账号。否则安装程序会卡在安全检查阶段,响应文件跑完一堆前置检查后直接退出,日志里也没有特别明确的报错。
还有一点:-ignorePrereqFailure 这个参数不要滥用。它只是在某些已知风险可控时用来跳过环境检查,比如缺少某个系统包但你确定不会影响当前功能。生产环境里如果把所有前置检查都粗暴跳过,后面 Oracle 进程大概率会在启动时报缺少动态库,到那时候定位问题比现在装依赖包麻烦得多。
3.3 root.sh 执行与安装日志排查
静默安装执行完成后,命令行会输出需要以 root 执行的脚本提示。如果没有看到类似 [WARNING] 或 [FATAL] 的日志,就可以用 root 执行脚本。
安装过程中日志文件通常位于:
/tmp/InstallActions日期时间/installActions日期时间.log$ORACLE_HOME/cfgtoollogs/u01/app/oraInventory/logs
排查时先用 tail -n 200 看最后一个报错位置,不要从头翻。最常见的失败点集中在依赖包缺失和权限不足两类。依赖包缺失会直接告诉你哪个 .so 文件 not found,权限不足会在日志里出现 Permission denied。
root.sh 执行失败时,处理思路是:先看日志定位是哪一步失败,再根据失败点决定是修复环境后重新执行,还是恢复原样再执行。root.sh 不是每次重新跑都会造成破坏,但在集群环境和 RAC 部署里,反复执行 root.sh 可能重复写入配置项,所以不能盲目重跑。本文章节聚焦单机版,相对风险小,但依然建议每次执行前先备份 /etc/oratab 等文件。
4. 建库环节的核心取舍:CDB/PDB、初始化参数和字符集
4.1 容器数据库还是非容器数据库
软件安装完成后,下一步就是建库。Oracle 19c 里最大的架构分叉是 CDB/PDB 和传统 non-CDB。
很多从 11g 转过来的人第一次看到 CDB/PDB 会有点懵。简单理解:容器数据库 CDB 像一个独立的数据库引擎,里面可以装多个 PDB,每个 PDB 对外看起来就像一个独立数据库,有自己的数据字典和业务数据,但底层共享一套数据库进程和内存结构。
在当前行业实践里,新项目默认应该选择 CDB/PDB 模式。有几个实际原因:一是以后打补丁更方便,很多补丁可以在 CDB 层面操作,多个 PDB 一起受益;二是数据库归档和备份策略可以在容器层面统一管理,省事很多;三是 19c 之后的版本对非容器数据库的支持会持续收缩,没必要在架构起点上给自己留隐患。
不过 CDB/PDB 也有一个需要适应的点:应用连接时必须使用服务名(Service Name)连接 PDB,而不是像以前那样一个实例名走天下。如果项目方习惯了旧的连接方式,建库后要专门在连接串文档里写清楚 jdbc:oracle:thin:@//host:1521/ORCLPDB 这种格式,而不是 jdbc:oracle:thin:@host:1521:ORCL。
4.2 DBCA 建库参数与一条实测过的命令行
如果只是建一个库,用 dbca 带图形界面也很方便,但生产环境自动化程度更高时,我更推荐用命令行静默建库。下面是一组比较典型的参数:
这里要解释几个容易被忽略的参数。-useLocalUndoForPDBs true 表示每个 PDB 使用自己的本地 undo 表空间,这是 12.2 之后推荐的做法,能避免 PDB 间 undo 争用。-memoryPercentage 30 表示把可用内存的 30% 分配给 Oracle 内存结构,如果物理内存是 32G,那么数据库可用内存大约是 9.6G 左右。这个值不是越大越好,因为操作系统层面、监听进程和其他应用也要留内存余量。
建库过程中的 -recoveryAreaSize 是快速恢复区大小,单位是 MB,上面写 40960 就是 40G。这里必须考虑实际磁盘空间。如果磁盘紧张,可以把恢复区建到独立挂载点上,不要和数据文件抢同一块盘的 IOPS 和空间。
建库完成后,建议立刻确认 CDB 和 PDB 的状态。用 sqlplus / as sysdba 登录后执行:
能看到类似下面的输出,说明 PDB 是正常的:
如果 PDB 状态是 MOUNTED,就需要手动执行 ALTER PLUGGABLE DATABASE ORCLPDB OPEN; 并设置保存状态,否则以后每次数据库重启,PDB 都是关闭状态,应用就会连不上。
4.3 字符集、时区和新建业务用户
字符集是建库时最不能反悔的参数之一。建库完成后虽然技术上可以改,但改字符集的步骤复杂,风险也大。现在新做的项目我基本都建议用 AL32UTF8,因为大多数人要用到中文和其他多语言字符,AL32UTF8 是兼容性最好的选择之一。
具体到业务用户,生产库一般不要直接用 sys 或 system 跑业务 SQL,而是应该为应用单独建用户和表空间。这里有一个比较简洁的 SQL 流程:
在 CDB 环境下,执行这条语句前要先切换到对应的 PDB:
很多人在 PDB 里创建用户时报 ORA-65096: invalid common user or role name,就是因为忘了切容器,以为还是在根容器下操作。还有一点:在 CDB 根容器里创建的普通用户如果不带 C## 前缀会直接报错,这是 12c 以后的规划,实际业务账号应该放在 PDB 里创建。
时区方面,数据库时区和操作系统时区不一定完全同步。如果应用服务器、中间件和数据库各用一个时区,业务上记录的时间可能会差好几个小时。建议确认 SELECT dbtimezone FROM dual; 的结果是否符合业务要求,如果不合适,可以在建库时通过参数指定。
5. 数据库能用不代表交付:项目实战中的初始化、验证和运维基线
5.1 开启归档模式并验证备份恢复
新装的 Oracle 数据库默认可能是非归档模式,这对生产环境来说绝对不行。没有归档模式,数据文件损坏后就只能恢复到上次备份点,丢失的数据量完全不可控。所以在项目实战交付里,我通常把归档模式开启放在所有初始化工作的最前面。
开启归档模式的典型过程:
执行完成后检查:
输出中 Database log mode 应该显示 Archive Mode,Automatic archival 显示 Enabled。
归档模式开启只是第一步,还要做一次实际备份验证。用 RMAN 执行:
第一次全量备份可以慢一点,但必须确认能成功生成备份集。有些团队因为磁盘空间紧张,备份脚本里没写删除策略,连续备份几次后恢复区就满了,数据库自动挂起。所以备份策略里要加上 DELETE OBSOLETE 或设置 DB_FLASHBACK_RETENTION_TARGET 之类的保留策略,避免备份空间失控。
5.2 监听器、告警日志和各类初始化检查
数据库安装完成后,监听器可能已经在建库时自动创建,但生产环境里仍然建议手动确认一遍。
常用命令:
lsnrctl services 会显示出当前注册到监听的服务名。如果你发现某个 PDB 的服务名没有出现在列表里,业务连接就会报 ORA-12514: listener does not currently know of service requested in connect descriptor。这时要先确认 PDB 是否打开,再检查 service_names 参数和 local_listener 参数。
告警日志是数据库运行状态的第一手记录。19c 的告警日志默认路径可以通过以下 SQL 获取:
路径看起来类似:
生产环境建议把这个路径加到日常巡检脚本里,重点关注 ORA-00600、ORA-07445、ORA-01555、表空间满、归档日志无法写入这些信息。不要等到系统挂了才去翻日志。
初始化检查里还有一块容易被忽略的是控制文件多路复用。如果数据库控制文件只放了一份,万一该磁盘损坏,整个数据库实例基本就废了。可以在初始化参数里给 control_files 配置多个路径,比如:
这种做法并不能替代备份,但能提升单点故障的容错能力。生产环境的文件分布原则永远是:控制文件、在线日志、数据文件别堆在同一块物理盘上。
5.3 从一个业务应用连接数据库的完整验证
交付前,我习惯用最接近生产的方式做一次全链路验证。这里的核心不是 SQL 能跑通,而是应用侧通过 JDBC、服务名、业务账号,通过真实网络访问到 PDB。
先在 tnsnames.ora 里配置好服务名:
然后用业务账号测试:
能正常进入 SQL 命令行后,再执行一个简单业务查询,比如:
这里我要多说一句:尽量避免用 sysdba 去业务连接。很多安装文档里最后都是 sqlplus / as sysdba 测试,但这只能证明数据库进程活着,不能证明应用账号和网络路径是通的。我曾经遇到一个项目,归档模式开了,表空间建了,一切看起来都正常,结果开发同事用业务账号连数据库时报密码错误,最后发现是 DBA 在创建用户时多复制了一个空格进去。这种问题就是接项目实战验证里最容易暴露的。
6. 安装配置中的高频故障与排查链路
6.1 ORA-00845、ORA-27102 等内存相关故障
启动数据库时最常见的报错之一是:
这个错误的本质是 MEMORY_TARGET 或 SGA_TARGET 的值超过了 /dev/shm 的大小。Oracle 自动内存管理需要把内存段映射到共享内存文件系统。检查方法:
如果 /dev/shm 远小于数据库配置的内存,解决思路有两个:一是增大 /dev/shm,修改 /etc/fstab 中对应 tmpfs 挂载项;二是调低数据库的 MEMORY_TARGET。对于生产环境,我不建议为了迁就内存参数而无限调大 /dev/shm,因为 tmpfs 会占用真实物理内存,给操作系统留的余量太少,其他进程可能被 OOM Killer 杀掉。
还有一种是 ORA-27102: out of memory。这种情况可能和 HugePages 配置有关。如果启用了大页,但 /proc/meminfo 里的 HugePages_Free 不足以容纳 SGA,就会触发该报错。排查时先看:
如果 HugePages_Total 是 0,说明大页没有配置;如果 HugePages_Free 很低,说明大页都被占用了。加大 /etc/sysctl.conf 里的 vm.nr_hugepages 后重新生效即可。这里还要注意一个细节:大页模式通常需要同时设置 memlock 资源限制,否则数据库用户无法锁定大页内存。
6.2 磁盘空间、inode 和随时可能出现的隐藏空间占用者
安装 Oracle 时明明 df -h 显示还有几十 G,但安装程序报磁盘空间不足,这种情况我遇到过好几次。原因往往不是“真的没有空间”,而是 /tmp 分区太小,或者文件系统 inode 耗尽了。
df -h 看的是容量,df -i 看的是 inode。当文件系统里小文件特别多时,即使容量剩余很多,也可能新建不了文件。Oracle 安装过程中会生成大量临时文件,所以检查空间时一定要两个命令一起看:
还有一种更隐蔽的情况:文件已经被删除,但某个进程还持有该文件的句柄,导致磁盘空间没有真正释放。这时可以通过 lsof +L1 找到被删除但仍被占用的文件,进而定位是哪个进程一直没退出。数据库定期清理归档日志时如果使用的是 rm,而进程又恰好通过 NFS 或其他方式打开残留句柄,就很容易出现“删了但空间没释放”的怪现象。
安装阶段还要注意 /tmp 目录不能以 noexec 方式挂载,否则 root.sh 或 runInstaller 执行时会报“Permission denied”,因为安装程序会在 /tmp 下生成很多可执行脚本。
6.3 包缺失、权限问题和 root.sh 反复失败
如果安装时跳过了依赖检查,后续启动 lsnrctl 或 sqlplus 时可能会出现找不到共享库的报错,比如:
这类问题的排查思路是先确认 ORACLE_HOME/lib 路径是否正确,再确认动态库搜索路径 LD_LIBRARY_PATH 是否包含它。也可以针对性使用:
如果输出里出现 not found,就说明缺了某个系统库,回溯去装对应依赖包即可。
root.sh 反复失败时,有一个容易忽略的点是 ORACLE_HOME 环境变量没有传递到 root shell。比如用 su oracle -c 执行脚本后再 su - root 执行 root.sh,但 root 环境里没有设置 ORACLE_HOME,脚本就会尝试读取一个空路径然后报错。正确做法是执行前明确:
或者直接在 root.sh 前把环境变量写进 /etc/profile 里临时生效。
权限方面,检查 /u01/app/oraInventory 目录的属主。如果它是 root 所有,oracle 用户执行后续操作时就会出现写不进去的问题。正常情况下 oraInventory 应该属于 oinstall 组,并且组内可写。
6.4 网络和监听器相关故障
业务连不上数据库,监听器是重点排查对象。先看监听进程状态:
如果端口没有监听,看监听日志或者直接重启监听:
如果监听端口有监听,但应用连接报 ORA-12514,说明服务名没注册到监听。这时候执行 lsnrctl services,看看监听里有没有对应 PDB 的 service。没有的话,多半要检查 local_listener 参数:
在 19c 的 CDB 环境下,PDB 的服务名只会注册到监听,前提是这个 PDB 处于 OPEN 状态。如果 PDB 没打开,监听里自然看不到,应用也就连不上。这就是我前文反复提“别忘了把 PDB 设为保存启动状态”的原因。
还有一种情况是云服务器环境,安全组虽然放行了 1521,但操作系统自带防火墙没有放行,或者反过来。这时候用 telnet 主机 1521 或 nc -vz 主机 1521 做端口测试,就能快速定位是网络层问题还是数据库监听层问题。
7. 结合项目实操的几点补充建议
这期把 Linux 生产环境安装配置 Oracle 19c 的主流程走完,后面其实还能继续往下延伸。每次做完一套真实环境,我都会把部署过程中的所有命令和检查点整理成一个文本清单,下次再遇到类似项目时先按清单走一遍,再针对现场情况微调。
我个人在反复操作后的体会是:生产环境安装数据库,最大的风险从来不是某个命令不会敲,而是流程顺序不对。比如先建库再开归档,先改字符集再建表空间,这些顺序问题在小型测试环境可能一次两次看不出后果,但在生产环境就是实打实的故障。
最后分享一个很实用的小动作:在交付前,把所有涉及密码、端口、服务名的信息整理成一份简明的环境信息表,单独发给项目组保管,一定不要只存在某个 DBA 的个人笔记里。数据库安装配置完成只是开始,后面系统运维、应用排障、备份恢复都要靠这份基础信息表定位问题。很多线上事故处理慢,并不是处理手段不行,而是信息散落各处,定位环境本身就要花掉大量时间。这份文档,比安装过程本身更值得花时间做好。