1. 部署前想清楚的三件事:版本、方式、目录
PostgreSQL 12.0是2019年10月发布的版本,放在今天看并不算新,最新社区版已经迭代到17甚至更高。但现实中需要部署它的项目一点不少:很多国产化数据库改造项目、存量业务系统的迁移验收、以及技术方案里明确写着“数据库版本采用PostgreSQL 12.0”的场景,都得老老实实把这套版本装起来。这篇文章不是纯理论讲解,而是我最近在一台CentOS 7.9服务器上做Linux下PostgreSQL 12.0安装部署的完整复盘,把每一步命令、参数含义、踩过的坑都摊开讲清楚。
如果你是运维工程师、DBA,或者是需要自己搭建数据库环境的后端开发,这篇内容可以直接拿来当操作手册。即使你用的是Ubuntu、Debian等系统,整体思路也完全通用,差异只在依赖安装命令和个别路径上。
1.1 为什么12.0这个版本值得单独梳理
PostgreSQL 12.0最大的变化是引入了原生分区表改进、并行查询增强、通用表达式(CTE)的性能优化等,当时社区的反馈是“大版本里综合体验提升最明显的一代”。对生产环境来说,它最大的价值在于稳定性和兼容性:很多业务系统在12.0上跑了好多年,应用层和中间件的适配早就完成,项目组自然不会为了追新版本去承担回归风险。
我实际接触过的情况是,甲方验收文档明确写了数据库版本范围,部署方没得选,只能按指定版本执行。所以这篇文章虽然以12.0为例,里面的部署思路、配置参数、排错手法,对PostgreSQL其他版本同样适用。学会这一套,往后换版本只是换源码包的事情。
另外多说一句,如果你没有版本锁定需求,直接用当前最新的稳定版通常更合适,毕竟新版本的性能和安全性都在提升。但如果是“非12.0不可”的项目,这篇文章能帮你少走很多弯路。
1.2 三种安装方式怎么选:源码编译、RPM包、Docker
部署PostgreSQL的方式大致有三种,我通常这样取舍:
| 方式 | 优点 | 缺点 | 适合场景 |
|---|---|---|---|
| 源码编译 | 可自定义编译参数、指定安装路径,适用于任意Linux发行版,便于后续扩展模块 | 步骤多、编译耗时长,依赖需要手动解决 | 内网服务器、指定版本、生产环境可控性要求高 |
| RPM/Yum安装 | 安装快、依赖自动处理,系统服务管理方便 | 版本通常不是最新的,源里没有就麻烦,和操作系统发行版绑定 | 标准环境、对版本没有特殊要求 |
| Docker容器 | 一条命令启动,隔离性好,开发环境切换版本最快 | 生产环境要额外维护容器运行,网络和存储映射需要规划,性能有一定损耗 | 本地开发、测试环境、快速体验 |
这次部署我选的是源码编译,原因很实际:服务器在内网,无法直接访问外网Yum源;项目还锁定了12.0这个具体版本,官方Yum源里维护的版本未必正好匹配;后续可能还要编译contrib扩展,源码编译的方式最灵活。
而且说实话,源码编译并没有想象中那么耗时,在四核服务器上大概三五分钟就能编完,生产服务器的性能完全够用。编译安装看起来多敲几条命令,但每一步都在掌握之中,对数据库二进制文件的位置、依赖关系也更清楚。
2. 准备工作:先看清楚机器,再动手装依赖
很多部署失败,问题不是出在安装命令本身,而是准备工作没做扎实。我习惯在动任何安装包之前,先把系统状态摸清楚,再安装编译依赖。
2.1 四条命令确认系统状态
部署之前,我一般会依次执行这几条命令:
cat /etc/os-release # 查看系统发行版和版本号 uname -m # 查看CPU架构,通常是x86_64 free -g # 查看内存总量,规划shared_buffers时要参考 df -h /data # 确认数据目录所在分区的剩余空间为什么先做这一步?因为操作系统发行版不同,依赖安装命令完全不同:CentOS/RHEL用yum,Ubuntu/Debian用apt,如果不看系统类型就去装依赖,很可能第一步就卡住。另外,PostgreSQL的数据目录建议放在单独挂载的磁盘上,不要和系统盘挤在一起,至少预留几十GB的空间,因为后续还有WAL日志、归档文件需要占用空间。
我这次的环境是CentOS 7.9,x86_64架构,机器内存4GB,/data分区剩余200GB左右,足够承载一个中型业务库的初始部署。磁盘空间这点多说一句,很多人部署初期觉得够用就行,结果跑了大半年才发现空间告急,再迁移数据就非常痛苦。
2.2 编译依赖到底需要哪些包
源码编译PostgreSQL时,最关键的是这几个依赖包:
- gcc:编译C代码的编译器,没有它什么都编不了
- make:执行Makefile构建流程的工具
- readline-devel:psql命令行交互、上下翻历史、Tab补全都依赖readline库,不装的话psql用起来非常难受
- zlib-devel:数据库备份和恢复时的压缩功能依赖zlib,不装的话相关功能会有编译限制
- flex、bison:用于生成SQL语法解析器,缺了它们会在编译阶段报错
在CentOS 7.9上安装这些依赖就一条命令:
yum install -y gcc make readline-devel zlib-devel flex bison如果是在内网离线环境,需要提前准备好这些RPM包或是本地Yum仓库,否则第一次configure就会因为找不到readline报错。我遇到过几次“configure: error: readline library not found”的情况,基本都是因为依赖没装全,补上readline-devel就顺利通过了。
还有一点值得说明:如果你计划使用PL/Perl、PL/Python这类过程语言扩展,需要额外安装对应的开发包,比如perl-ExtUtils-Embed、python3-devel。这部分不在基础依赖里,等确实需要时再按项目需求补装即可,一是减少不必要的编译负担,二是避免无用的Python/Perl环境被系统安全扫描判定为多余组件。
2.3 创建专用用户和目录结构
PostgreSQL出于安全设计,不允许以root身份运行数据库服务,必须使用独立的系统用户。这一步很多人会忘,或者嫌麻烦直接用root启动,结果系统日志里一堆权限警告。标准做法是创建postgres用户:
useradd postgres然后规划目录结构。我习惯把数据目录、日志目录、归档目录分开:
mkdir -p /data/pgdata # 数据库数据文件主目录 mkdir -p /data/pglog # 服务运行日志目录 mkdir -p /data/archived # WAL归档目录,后续做备份时用 chown -R postgres:postgres /data/目录属主这一步极其关键,如果不把/data目录的属主改成postgres,initdb初始化时会出现“could not change permissions of directory”这类报错。因为initdb会检查数据目录的权限和属主,不允许其他用户拥有数据目录,这是PostgreSQL默认的安全机制。
我之前踩过一个坑:只创建了目录,忘了chown,然后以postgres用户执行initdb,结果一直报目录权限问题,浪费了大概十分钟才反应过来。目录结构建议一开始就规划好,不要图省事全堆在/var/lib/pgsql下面,宁可多敲几条命令,后面维护时省心得多。
3. 源码编译:configure参数怎么选、踩了哪些坑
依赖装好、用户建好之后,就进入正题:下载源码包并编译安装PostgreSQL 12.0。这一步是整个部署流程的核心,也是网上各种教程最容易写得含糊的地方。
3.1 下载源码包并校验完整性
我一般把源码包下载到/usr/local/src目录,方便统一管理:
cd /usr/local/src wget https://ftp.postgresql.org/pub/source/v12.0/postgresql-12.0.tar.gz如果服务器无法访问外网,可以在本地电脑下载后通过scp或内网传输工具上传到服务器,再用sha256校验一下文件完整性:
sha256sum postgresql-12.0.tar.gz校验这个步骤不是形式主义,源码包下载中断或者文件损坏后,后续编译会出现各种莫名其妙的报错,而且很难定位。确认校验值无误后解压:
tar -xzf postgresql-12.0.tar.gz cd postgresql-12.0顺便说一句,内网环境很多团队选择搭个本地HTTP/FTP源或者直接拷包分发,这都很常见。关键是别跳过后面的校验步骤。
3.2 configure参数逐条拆解
进入源码目录后,最重要的一步就是执行configure。我这次的配置命令是:
./configure --prefix=/usr/local/pgsql12 \ --with-pgport=5432 \ --with-perl \ --with-python \ --enable-nls每个参数都需要理解用途再决定加不加,不要照着别人的文档无脑复制:
- --prefix=/usr/local/pgsql12:指定安装路径。我习惯带上版本号作为子目录,这样同一台机器上如果还有PostgreSQL 14或16,二进制文件不会相互覆盖,升级回滚也方便。
- --with-pgport=5432:指定编译进数据库的默认端口号。PostgreSQL默认就是5432,显式写出来的意义在于把端口定死,避免有人后续误改编译默认值。
- --with-perl和--with-python:启用PL/Perl和PL/Python过程语言支持。不确定项目是否会用到这些存储过程语言时,我建议先加上,成本很低且不影响日常使用。
- --enable-nls:启用国际化消息翻译,让PostgreSQL的错误提示支持多语言。对于国内项目,这个参数按需添加,其实默认英文日志反而更容易在网上搜到解决方案。
configure过程中最常见的报错就是缺少依赖库,比如找不到readline、zlib等。如果遇到这类报错,不要慌,看报错信息里明确提示缺什么包,装好之后重新configure就行。configure成功后会输出一长串配置摘要,包括“config.status: creating GNUmakefile”等字样,看到这个就说明配置阶段通过了。
3.3 编译安装:make -j参数怎么定
configure通过后,执行编译:
make -j$(nproc)-nproc参数会自动把并发编译数设置成机器的CPU核数,能明显缩短编译时间。如果机器内存特别小,比如1GB内存还开了8核并发,有可能把内存占满导致编译失败,这时候保守一点,直接用make不加-j参数,虽然慢一些但很稳妥。
编译完成后再执行:
make install这条命令会把二进制文件、库文件、头文件、文档安装到--prefix指定的目录下。安装完成后确认一下bin目录内容:
ls /usr/local/pgsql12/bin/正常情况下,能看到initdb、pg_ctl、psql、pg_dump、pg_basebackup等核心工具都齐了。这套源码包的基础安装就算完成。
如果后续需要用PostgreSQL自带的contrib扩展模块,比如pg_stat_statements、postgres_fdw等,还可以在源码目录下执行make world和make install-world。我一般不会一次性全安装,等确实需要哪个扩展时再进入源码目录单独编译,这样安装目录更干净。
3.4 环境变量配置:LD_LIBRARY_PATH的坑
安装完成后,还需要配置环境变量,否则postgres用户执行psql时找不到命令,initdb时也可能因为找不到动态库而报错。我给postgres用户的~/.bash_profile添加了以下内容:
export PATH=/usr/local/pgsql12/bin:$PATH export LD_LIBRARY_PATH=/usr/local/pgsql12/lib:$LD_LIBRARY_PATH配置PATH的目的很直观:让initdb、psql等命令可以直接执行,不需要每次敲完整路径。LD_LIBRARY_PATH则是为了告诉系统去哪里找PostgreSQL自带动态库,比如libpq.so.5。
我见过最典型的一个报错就是:initdb执行时提示“error while loading shared libraries: libpq.so.5: cannot open shared object file”,受影响的机器往往就是没设置LD_LIBRARY_PATH。设置完成后重新登录postgres用户或者执行source ~/.bash_profile,让环境变量生效。
这里有个小技巧:环境变量最好只写在postgres用户下,不要写到全局的/etc/profile里,避免影响系统其他软件对动态库的加载顺序。一些PostgreSQL版本自带的动态库名字和系统其他软件重复,全局LD_LIBRARY_PATH容易引发不必要的冲突。
4. 初始化数据目录和第一次启动
编译安装只是把可执行文件放到了服务器上,真正让数据库“有数据可存”的步骤是initdb。这一步相当于给数据库划分一块干净的数据地盘,生成初始的系统表、配置文件、事务日志等。
4.1 initdb参数详解和初始化原理
先切换到postgres用户,再执行初始化:
su - postgres initdb -D /data/pgdata -E UTF8 --locale=en_US.UTF-8 -U postgres --auth=scram-sha-256每个参数都有明确作用,我逐个说一下:
- -D /data/pgdata:指定数据目录。这里必须和前面创建目录时保持一致。
- -E UTF8:指定数据库默认字符集。国内业务系统基本都用UTF8,避免中文乱码问题。
- --locale=en_US.UTF-8:指定本地化规则。选择UTF8的locale是为了让字符串排序和大小写处理符合通用习惯,如果不需要本地化规则,也可以直接用--locale=C。
- -U postgres:指定数据库超级用户的用户名。这里沿用系统账号的名字,方便记忆,也符合常见运维习惯。
- --auth=scram-sha-256:指定本地socket连接的默认认证方式,这个参数很重要,下面单独展开。
initdb执行过程中会创建三个初始数据库:template0、template1和postgres,还会生成核心配置文件postgresql.conf和pg_hba.conf。这一步的本质是把PostgreSQL内置的初始数据填充到我们指定的数据目录中,让数据库系统具备启动条件。执行成功后,末尾会明确显示“Success. You can now start the database server”这行提示,看到它才算初始化成功。
4.2 认证方式:scram-sha-256还是md5
PostgreSQL 12.0开始,默认的密码认证方式已经从md5切换为scram-sha-256。这是安全性上的重要升级:scram-sha-256比md5更抗暴力破解和重放攻击,连接过程中的密码传输不易被截获还原。
我在规划认证方式时的原则是:只要客户端和中间件支持scram-sha-256,就用它,不倒退回md5。但如果遇到很老的应用客户端只支持md5协议,连接时报认证失败,再针对性调整。调整方式是把pg_hba.conf里对应的认证方法改成md5,然后重置一次用户密码,让数据库里存的是md5加密的密码。
不过要提醒一点:从scram-sha-256切换回md5属于兼容性妥协,除非项目强约束,不建议长期在生产环境使用md5。
4.3 用pg_ctl启动并确认进程
初始化和配置完成后,可以手动启动数据库:
mkdir -p /data/pglog && chown postgres:postgres /data/pglog pg_ctl -D /data/pgdata -l /data/pglog/server.log start-l参数指定了运行日志的输出文件。这一步有个容易被忽略的细节:日志文件路径的目录必须让postgres用户有写权限,否则启动会直接失败,错误信息还比较隐晦。启动后,我习惯用下面两条命令确认状态:
ps -ef | grep postgres pg_isreadyps的输出会显示postmaster主进程以及一堆辅助子进程,比如background writer、walwriter、checkpointer、stats collector等。看到这些进程,就说明数据库核心进程已经正常起来了。pg_isready如果显示“accepting connections”,说明数据库正在监听连接请求。
5. 核心配置调整、systemd注册和远程访问
数据库能启动只是第一步,生产使用还需要调整内存参数、配置远程访问权限、注册开机自启。这步骤做不好,前期的安装工作就白费了一半。
5.1 postgresql.conf里的关键参数怎么调
编辑配置文件:
vi /data/pgdata/postgresql.conf我通常会优先调整这几个参数:
listen_addresses = '*' port = 5432 shared_buffers = 1GB max_connections = 200 max_prepared_transactions = 0 wal_level = replica effective_cache_size = 3GB- listen_addresses:默认值是localhost,意味着只能本机访问数据库。如果应用服务器和数据库服务器是分开的,必须改成
*或者指定内网IP,否则从其他机器永远连不上。 - shared_buffers:PostgreSQL的内存缓冲区大小,官方建议设为物理内存的25%左右。这台机器是4GB内存,所以设1GB比较合理。这个参数不是越大越好,给操作系统留足内存做文件缓存,整体性能反而更好。生活里类比一下,shared_buffers就像餐厅的前厅,前厅堆了太多菜,后厨就没地方干活了。
- max_connections:最大连接数。默认值是100,小业务够用,如果并发量高要提前调大。注意这个参数改得太大也会占用更多共享内存。
- wal_level:WAL日志级别。默认replica即可,能支持热备和归档。如果没有特殊需求不需要改成logical。
- effective_cache_size:这个值告诉优化器系统可用缓存有多大,一般设为物理内存的50%~75%,4GB内存的机器设3GB没什么问题。它不做真正的缓存分配,只影响查询执行计划的选择。
修改完postgresql.conf后,需要区分一下哪些参数只需要reload就能生效,哪些必须重启。像listen_addresses、max_connections这些参数需要重启,shared_buffers更是必须重启,wal_level也需要重启。如果不想中断业务,可以先执行pg_ctl reload让部分参数生效,再在维护窗口重启让全部参数生效。
5.2 pg_hba.conf的访问控制规则
数据库的网关注册文件是pg_hba.conf,它决定了谁可以通过什么方式连接数据库。打开这个文件,常见配置如下:
# TYPE DATABASE USER ADDRESS METHOD local all all scram-sha-256 host all all 127.0.0.1/32 scram-sha-256 host all all 0.0.0.0/0 scram-sha-256格式从左到右依次是:连接类型、数据库名、用户名、客户端地址、认证方法。含义分别是:
- local:本地Unix域套接字连接,只适用于本机psql连接。
- host:TCP/IP连接。127.0.0.1/32表示仅允许本机回环地址连接;0.0.0.0/0表示允许任意IP连接,生产环境如果这么写会暴露在风险中,建议改成业务网段,比如192.168.1.0/24。
认证方法建议统一用scram-sha-256,不要用trust。trust意味着不需要密码就能登录,这在数据库场景基本等于把数据裸奔在局域网里。如果只是内部开发环境,临时用trust调试可以,上线前一定要改回来。
修改pg_hba.conf后不需要重启数据库,执行pd_ctl reload或者运行SQL语句SELECT pg_reload_conf();即可让配置生效。
5.3 用systemd管理PostgreSQL服务
手动启动数据库的方式适合首次安装验证,生产环境还是得注册成systemd服务,这样开机自动启动、宕机自动拉起、运维统一管理。我在/etc/systemd/system/目录下新建了一个unit文件postgresql-12.service:
[Unit] Description=PostgreSQL 12 database server After=network.target [Service] Type=forking User=postgres Group=postgres Environment=PGDATA=/data/pgdata ExecStart=/usr/local/pgsql12/bin/pg_ctl start -D ${PGDATA} -l /data/pglog/server.log ExecStop=/usr/local/pgsql12/bin/pg_ctl stop -D ${PGDATA} -m fast ExecReload=/usr/local/pgsql12/bin/pg_ctl reload -D ${PGDATA} TimeoutSec=120 [Install] WantedBy=multi-user.target解释一下几个关键点:
- Type=forking:因为pg_ctl启动时,postmaster进程会fork出后台进程并返回,systemd通过这个模式来判定服务已经成功启动。
- ExecStop里的-m fast:表示快速关闭模式,会回滚未完成的事务并断开连接。如果需要更平滑的关闭,可以用smart模式,它会让数据库等当前连接都结束后再关闭,适合计划维护场景。
- TimeoutSec=120:防止大库关闭时间过长被systemd误判为超时杀掉。
注册并启用服务:
systemctl daemon-reload systemctl enable --now postgresql-12执行后确认状态:
systemctl status postgresql-12看到“Active: active (running)”字样就说明服务已经被systemd管起来了,开机自动启动的配置也全部到位。如果你所在环境必须用sysVinit,也可以使用源码包里contrib/start-scripts/linux脚本,但能上systemd还是上systemd,日志聚合和服务管理都方便得多。
5.4 防火墙放行和远程连通测试
内网机器通常开着firewalld,如果不放行5432端口,即使数据库监听了一切地址,其他机器也连不进来。CentOS 7.9上放行端口:
firewall-cmd --permanent --add-port=5432/tcp firewall-cmd --reload然后查看监听状态:
ss -lntp | grep 5432看到LISTEN状态的5432端口,说明TCP监听已经建立。再从另一台机器测试连接:
psql -h 192.168.1.10 -p 5432 -U postgres -d postgres输入密码后能进入SQL命令行,整个部署流程就算真正打通了。如果这一步连不上,优先检查三处:数据库监听地址是否包含目标IP、pg_hba.conf是否允许该来源IP、防火墙是否放行。排查顺序打乱反而容易越整越乱。
6. 常见问题与排查技巧实录
部署过程中总会遇到或大或小的问题。我把实际操作中频率最高的故障整理成了一张速查表,按照“现象-原因-处理”的思路来走,处理效率会高很多。
6.1 高频故障对照速查表
| 现象 | 根本原因 | 排查与处理 |
|---|---|---|
| initdb报libpq.so.5找不到 | LD_LIBRARY_PATH环境变量未设置 | 在postgres用户的bash_profile中添加export LD_LIBRARY_PATH=/usr/local/pgsql12/lib,然后重新source |
| psql连接提示role “root” does not exist | 用root用户直接执行psql,PostgreSQL不知道root这个角色 | 先切换su - postgres,再执行psql |
| 远程连接超时或拒绝连接 | 防火墙未放行5432端口,或postgresql.conf未监听指定IP | 检查ss -lntp确认监听,再firewall-cmd放行端口,最后用pg_hba.conf确认来源IP是否被允许 |
| 密码认证失败FATAL: password authentication failed | 密码错误,或者客户端认证方式与pg_hba.conf不一致 | 重置用户密码:ALTER USER postgres PASSWORD '新密码',并将pg_hba.conf认证方法对齐为scram-sha-256 |
| 启动时提示could not bind to address | 端口被占用,通常是装了其他数据库或旧版PostgreSQL | 用ss -lntp查看谁占用5432,要么停掉占用进程,要么改当前数据库端口 |
| 数据目录权限报错 | 目录属主不是postgres用户 | 检查ls -ld /data/pgdata,执行chown -R postgres:postgres /data/ |
这些问题是初学者到进阶使用者最容易卡的几关,尤其是认证失败和防火墙问题,占了部署咨询量的一半以上。
6.2 排错先看日志,不要瞎猜和乱重启
我的排错习惯始终是:一切以运行日志为准,先看日志再做判断。PostgreSQL的运行日志在初始化时通过-l参数指定,也就是/data/pglog/server.log。用下面的命令跟踪最新日志:
tail -f /data/pglog/server.log日志里会明确写出启动失败的具体原因。比如权限不足、端口占用、数据目录损坏、认证错误等,大多数时候日志已经告诉我们答案,就差静下心来读一行。
配合日志,再做两个快速检查:
pg_isready -h 127.0.0.1 -p 5432 ss -lntp | grep 5432pg_isready负责确认数据库进程是否在接受连接,ss负责确认端口监听状态。这两个命令加起来,能快速判断问题出在“数据库没启动”还是“网络不可达”。切忌一上来就执行systemctl restart或者pg_ctl restart,重启只会掩盖现象,并不能解决根因,重度业务数据库更不能随意重启。
6.3 容易被忽略的权限与路径细节
有几个细节在常规文档里不会专门强调,但实际部署中非常容易踩,我总结一下:
- 数据目录所在的父目录,各级都要有足够权限让postgres用户进入。比如/data目录如果属主是root且权限是700,postgres用户即使能操作/data/pgdata也会被父目录挡住。
- 使用相对路径执行initdb时,如果环境变量没生效,会提示command not found。要么用绝对路径/usr/local/pgsql12/bin/initdb,要么先确认PATH变量包含安装目录。
- 修改postgresql.conf后,shared_buffers这类参数不会因为reload而生效,必须在维护窗口重启数据库。很多人改完配置执行了reload就以为参数生效了,实际并没有。
- systemd服务文件如果命名不当或者包含语法错误,systemctl daemon-reload会报错。写完后可以先执行systemd-analyze verify postgresql-12.service检查一下语法,避免反复调试。
- 如果不是用root安装,编译tar包时产生的源码目录属主是root,后续想用postgres用户再次编译contrib扩展会没权限,直接chown -R postgres:postgres源码目录即可。
6.4 几个提升效率的小技巧
最后分享几个实际使用中的小技巧,都是常规文档不会写的内容:
第一,部署完成后立刻给postgres用户设置一个可靠的密码。初始化数据库时虽然指定了超级用户名,但并没有设置密码,如果不设置,连接时会因为密码为空而无法通过认证。用ALTER USER postgres PASSWORD '强密码';在psql里执行一次,这一步一定不要忘。
第二,把常用命令包装成shell别名,比如alias pgstart='systemctl start postgresql-12'、alias pglog='tail -f /data/pglog/server.log',放到root和postgres用户的环境变量中。数据库运维虽然不算复杂,但高频操作能少敲几下键盘,心情也会好很多。
第三,备份配置文件是运维的基本素养。我习惯在配置完成后执行一次cp /data/pgdata/postgresql.conf /data/pgdata/postgresql.conf.bak,无论后面参数怎么调,都能快速回滚。同理,pg_hba.conf也建议留一份原始备份。
最后再说一个习惯:每次部署完成后,我都会把安装过程中用到的命令、参数改动和关键截图整理成一份部署记录,存到团队的运维文档里。很多操作当时觉得清清楚楚,过半年再看就全忘光了,尤其是initdb那几条参数,不同项目之间变来变去,没有记录就是隐患。这套流程在CentOS 7.9、Ubuntu 18.04上都实测跑过,逻辑完全一致,区别只是依赖安装把yum换成apt。如果你在部署中遇到这篇文章没覆盖到的问题,不妨按“日志→权限→端口→参数”的顺序排查,绝大多数问题都能快速定位到根因。