简介这是一份面向运维人员与初学者的 PostgreSQL 离线安装教程适用于无网络或内网隔离环境下的数据库部署场景。内容以 PostgreSQL 9.5 版本为例完整覆盖依赖包准备、RPM 强制安装、CMake 插件编译、源码安装、创建 postgres 用户与数据目录、初始化数据库、启动服务及创建数据库等核心步骤并详细说明了通过 pg_hba.conf 与 postgresql.conf 配置远程访问权限的方法。资源为 1 个 docx 文档压缩包大小 43KB当前已有 795 人学习下载。文档以命令清单和配置说明为主结构紧凑、可直接对照执行省去了自行查找依赖和排查配置细节的时间适合需要在内网环境中快速完成 PostgreSQL 部署的读者作为操作参考。1. 离线安装 postgresql真正的难点不在 PG 本身而在依赖和包源接到一个内网服务器的数据库需求第一反应往往是“把 PG 装上就行”结果卡在 yum 源连不通、apt 源超时、依赖缺一个装一个的泥潭里。这套方案的定位是 postgresql 离线安装目标是让一台完全不能访问外网的机器从零装出能连、能建库、能安全重启的 PostgreSQL。它适合做内网交付的运维、在隔离环境里搭库的研发以及要批量复制数据库环境的人。先把反直觉的结论摆出来PG 自己的安装包反而是最好准备的真正烧时间的是 readline、zlib、icu 这些编译和运行依赖把依赖清单理清比装 PG 本身更值钱。2. 装前准备先把版本和依赖定死再动手2.1 PostgreSQL 16 还是 15离线场景怎么选版本每次群里看到“postgresql 下载哪个版本”这种问题离线场景的答案从来不是“最新”而是“你的包源里稳定存在哪个”。我一般会选 PostgreSQL 16。它不是最新但在 RPM 与源码两条路径上都被验证得足够多官方 yum 仓库对 RHEL 7/8/9 都提供 postgresql16-serverCentOS 7.9 这种还在大量服役的内网机器可以直接用source tarball 在 gcc 4.8 的环境下也能编过。PG 15 也行它的 rpm 包在老旧发行版里更常见如果你所在的内网已经有团队在用 15跟着存量版本走别在新项目里另起 16省得以后备份恢复还要跨大版本折腾。选版本还要看目标机的系统。如果一个内网里混着 CentOS 7 和 Rocky 9我建议统一选同一个大版本比如都是 16介质里只放 16 的包。跨版本混装后期会带来两个麻烦一是 pg_upgrade 只能就近往上升二是 16 和 15 的 data 目录格式不兼容谁都不想在内网里做一次数据迁移。另外要确认目标机磁盘PG 16 完整安装加 contrib 约占用 300MB 左右源码编译则要预留 1GB 以上的临时空间——内网机器经常磁盘很小这个提前量必须算进去。对架构也要看一眼x86_64 的 rpm 直接在官方源里拿如果是 ARM 或国产 CPUrpm 常常拿不到直接走源码编译第 4 章。源码编译对 GCC 版本不挑到很离谱CentOS 7 自带的 gcc 4.8.5 编 PG 16 没问题但 configure 时会卡在缺头文件所以编译依赖要按 4.1 的清单一次拉全不要到了目标机才一个个试。2.2 依赖清单readline、zlib、icu 一个都不能少离线安装的翻车点八成在依赖。RPM 方式下依赖会被包管理器自动解析前提是依赖包本身在本地仓库里源码方式下 configure 会逐个检查头文件和库缺哪个就停在哪一个。下面这张表是我每次装之前都要对照的清单依赖包RHEL 系 / Debian 系作用缺了会怎样postgresql16-libs / postgresql-16运行库包含 libpq.so.5rpm 装 server 时直接报缺 libpq.so.5readline-devel / libreadline-devpsql 的行编辑与命令历史源码 configure 卡在 checking for readlinezlib-devel / zlib1g-devpg_dump 压缩备份、WAL 压缩备份体积变大甚至备份功能异常libicu-devel / libicu-devICU 排序规则与国际化PG 16 默认偏好 ICU 排序缺了只能退回 libcopenssl-devel / libssl-devSSL 连接与加密configure 检查 openssl 失败只能 --without-opensslsystemd-devel / libsystemd-dev生成 systemd 通知支持rpm 装在 systemd 系统上一般会需要llvm / clang可选JIT 即时编译缺了不是致命错误configure 加 --without-llvm 即可这里解释一下为什么这几样是刚需。readline 管着 psql 的上下键历史没有它 psql 用起来非常痛苦zlib 关系到备份压缩离线环境里备份几乎是唯一的后悔药不能省icu 在 PG 16 里是排序规则的首选实现你不装它数据库也能初始化但排序和大小写行为可能和线上用 yum 装出来的实例不一致以后做数据对比会对不上。还有一类依赖容易被忽略rpm 方式会自动拉入 systemd-libs 这类基础库源码方式则要自己准备。如果你走源码编译编译期的 -devel 包列表以 4.1 为准如果你走 rpm放心交给包管理器前提是 repotrack 时把整个依赖树拉全。2.3 安装介质从哪来rpm 包和源码包两条路离线安装本质上就是把在线安装时“联网拉包”的动作提前做完。常见做法有两套按目标机情况二选一。第一套是先找一台和 target 同样系统大版本、同样 CPU 架构的能联网机器配好 PG 官方 yum 源再用 yum 的 repotrack 把指定包和它们的依赖全部拉下来打成 tar 包传进内网做成本地 yum 源。命令如下mkdir -p /opt/pg-rpms cd /opt/pg-rpms yum install -y yum-utils createrepo repotrack -a x86_64 postgresql16-server postgresql16-contrib createrepo /opt/pg-rpms tar czf /opt/pg16-rpms.tar.gz /opt/pg-rpmsrepotrack 和 yumdownloader 的区别要说明一下yumdownloader 只会拉你指定的那一个包不拉依赖repotrack 会把依赖递归拉全。离线场景最怕的不是主包缺而是装到一半发现个没见过的依赖所以一定要用 repotrack 或类似工具。-a x86_64 是显式指定架构防止在 x86_64 的机器上下出 noarch 或 i686 的混包。之后把 pg16-rpms.tar.gz 传到内网目标机解压即可。第二套是直接拿源码 tarball 进内网编译适合没有现成 rpm 的架构或国产化系统。源码方式的准备工作在第 4 章展开原则是一样的不只是主源码包编译期的 -devel 依赖也要提前用 repotrack 拉全。两条路在动手前都要先确认目标机有没有 yum/apt 之外的包管理工具能用如果连 rpm 都没有那基本只能是源码编译一条路了。3. 用 RPM 离线安装 PostgreSQL 16下载、传包、初始化一条线走通3.1 在内网目标机上搭建本地 yum 源把上一步打的 tar 包解压到目标机后先做一件事把目录变成 yum 能认的本地仓库。解压后 /opt/pg-rpms 下会有一堆 rpm 包和 repodata 目录如果 repodata 没生成就在目标机上重新执行一次 createrepo。然后写一个只指向本地目录的 repo 文件cd /opt/pg-rpms createrepo . cat /etc/yum.repos.d/pg-local.repo EOF [pg-local] namePostgreSQL Local RPMs baseurlfile:///opt/pg-rpms enabled1 gpgcheck0 EOF yum clean all yum makecache这里有两处值得解释。gpgcheck0 是因为离线内网通常没有 PG 官方 GPG key先把签名校验关掉如果你们内网有密钥分发机制建议保留 gpgcheck1 并把 RPM-GPG-KEY 放到 /etc/pki/rpm-gpg否则以后审计会找你麻烦。第二处是 baseurl 用 file:// 指向本机路径yum 对本地目录的权限要求不高但目录和 rpm 文件不能被 root 之外的人改写成奇怪的权限否则 makecache 会静默失败现象就是 yum 列表里看不到任何包——这个在第 5 章会展开。检查源是否生效用 yum repolist 看 pg-local 是否在列表里正常会显示 repo id 和包数量。如果显示 0 packages先检查 repodata 目录是否存在、repomd.xml 是不是空文件这两个是最常见的静默失败点。3.2 用 yum 的互斥参数装主套件本地源建好后安装命令要刻意避开外网源。我一般会写死两个互斥参数防止 yum 因为某个未禁用的官方源去连外网yum install -y postgresql16-server postgresql16-contrib \ --disablerepo* --enablerepopg-local--disablerepo* 把所有仓库禁用--enablerepopg-local 只放行本地仓库。顺序是先禁后放这样即使机器上还有 dl.fedoraproject.org 之类的残留源也不会去连。contrib 包建议一起装pg_stat_statements、uuid-ossp、postgres_fdw 这些常用扩展都在里面离线环境里再想补一个包要重新走一遍拉包流程代价很大。装完验证一下rpm -qa | grep postgresql正常情况下会看到 postgresql16-server、postgresql16-libs、postgresql16-contrib 等包。如果 rpm 输出为空先看 yum 是否真的走了 pg-local 源可以用 yum history 或查看 /var/log/yum.log 确认而不是直接放弃重装。另外用 rpm -qi postgresql16-server 看一眼 Version 字段确认拉到的确实是 16 而不是 15版本锁错在内网很常见。3.3 initdb 初始化数据目录与 systemd 启动包装完不代表能用还要初始化数据目录。PG 官方 rpm 会提供一个初始化脚本以 postgres 用户执行 initdb/usr/pgsql-16/bin/postgresql-16-setup initdb systemctl enable --now postgresql-16 systemctl status postgresql-16postgresql-16-setup 这个脚本本质上是“用 postgres 用户跑 initdb -D /var/lib/pgsql/16/data”并且会自动处理数据目录的属主权限。如果你装完直接 systemctl start大概率会看到服务起来了但日志里全是权限报错因为 rpm 包不会帮你初始化数据目录。这一步不要用 root 去手动执行 initdb否则后面所有配置文件属主都会乱掉。接着改密码和允许局域网访问。PG 16 默认的 pg_hba.conf 里本地 socket 是 trusthost 只有 127.0.0.1/32 和 ::1/128远程机器根本连不上。先连接本地实例改密码sudo -u postgres psql -c ALTER USER postgres PASSWORD 你的强密码;然后改两处文件。第一处 /var/lib/pgsql/16/data/postgresql.conf 里把 listen_addresses 从 localhost 改成实际监听地址内网常用 * 监听所有网卡第二处 /var/lib/pgsql/16/data/pg_hba.conf 增加一条 host 规则例如host all all 192.168.1.0/24 scram-sha-256listen_addresses 的修改必须重启才生效pg_hba.conf 执行 reload 即可。如果 sudo -u postgres psql 时报 could not connect to socket先看 /tmp/.s.PGSQL.5432 是否存在socket 文件被清理或权限不对都会导致本地连不上。最后确认防火墙没有挡 5432 端口CentOS 7 常见做法是 systemctl stop firewalld 或 firewall-cmd --add-port5432/tcp --permanent。到这里一个 RPM 方式的离线安装就算通了后面第 5 章会补几个最容易在这条链路里翻车的地方。4. 源码编译离线安装没有现成 rpm 时的完整路径4.1 上游源码与编译依赖要一起打包当目标机是 ARM 架构、国产化系统或者你拿不到任何现成 rpm 时源码编译几乎是唯一出路。离线源码编译的第一步还是在有网的机器上准备三样东西PG 源码 tarball、编译工具链、-devel 头文件。源码包从 PostgreSQL 官网下载文件名类似 postgresql-16.x.tar.gz你直接搜对应版本就能找到。下载后做一件事比对 sha256sum防止 U 盘拷贝或 FTP 传输把包弄坏离线环境里介质损坏非常常见校验这一步能省掉后面大量玄学问题。编译工具链和依赖用 repotrack 一次拉全我的习惯是全部拉到同一个目录再一起打包mkdir -p /opt/pg-build-deps cd /opt/pg-build-deps repotrack -a x86_64 gcc make bison flex readline-devel zlib-devel libicu-devel openssl-devel tar czf /opt/pg-build-deps.tar.gz /opt/pg-build-deps这里为什么要 bison 和 flexPG 的语法解析器源码在编译时需要用 bison 生成 parser 文件flex 生成词法分析器缺了它们 make 会直接报错而且报错信息很隐晦经常是“bison: command not found”这种看起来没头没尾的一句话。gcc 和 make 是编译基础readline/zlib/icu/openssl 的 -devel 包决定 configure 的检查结果。如果你确定内网机器已经装了 gcc可以省掉但多带没坏处——离线环境里补一个包的成本你跑过一次现场就懂。4.2 configure 与 make 编译参数怎么设源码包传到目标机后解压进入目录开始配置。configure 的核心作用是把“缺依赖”的问题集中在第一步暴露出来而不是等到 make 到一半才崩tar xzf postgresql-16*.tar.gz cd postgresql-16* ./configure --prefix/usr/local/pgsql \ --with-icu --with-openssl --without-llvm--prefix 指定安装目录我习惯用 /usr/local/pgsql这样和官方 rpm 装的 /usr/pgsql-16 在视觉上就能区分开避免后期运维搞混。--with-icu 启用 ICU 排序--with-openssl 编译 SSL 支持两者都依赖对应的 -devel 包如果你在 4.1 里没拉全configure 会在这里退出。--without-llvm 是刻意关掉 JIT原因很现实内网机器通常不需要 JIT 提升那一点性能而且 LLVM 工具链又大又难凑齐关了反而让编译链路更短。如果你后面要用 pg_stat_statements 这类扩展记得 configure 阶段不要加 --without-contrib默认会带上 contrib 子目录。configure 挂掉的时候别只盯着终端最后一行。它会生成一个 config.log里面记录了每个检查项的具体失败原因。用 grep error config.log 往往能直接看到“readline.h: No such file”这类关键信息这比在黑匣子里反复猜测快得多。这也是源码安装和 rpm 安装最大的体验差异没有依赖解析器兜底每一步都显式暴露。configure 完成后执行编译。make 的并行数按 CPU 核数走内网机器的核数可能不高但 -j$(nproc) 仍然比单线程快很多make -j$(nproc) make installmake install 只装主程序contrib 里的扩展还要单独进目录编一次cd contrib make -j$(nproc) make install编译期间如果报错先看 make 停在哪一步。比较常见的是缺头文件、缺 bison/flex、磁盘空间不足三种前两种回到 4.1 补包第三种则要给目标机清理临时空间。4.3 用 postgres 用户 initdb、配置环境变量与启动源码安装不会自动创建 postgres 用户也不会生成 systemd 服务这些都是手工活。我一般按下面顺序做useradd -m postgres mkdir -p /data/pgsql chown -R postgres:postgres /data/pgsql sudo -u postgres /usr/local/pgsql/bin/initdb \ -D /data/pgsql --encodingUTF8 --localeen_US.UTF-8initdb 一定用 postgres 用户跑这是源码安装和 rpm 安装都要遵守的规矩否则数据文件属主变成 root后面启动服务会因为权限问题直接失败。--encodingUTF8 是生产环境标配中文场景尤其要显式指定避免默认编码和客户端的 UTF-8 不一致导致乱码。--locale 用 en_US.UTF-8如果目标机没有这个 locale可以先用 localedef -i en_US -f UTF-8 en_US.UTF-8 生成或者干脆用 --localeC代价是排序行为更接近二进制比较中文排序会不那么符合直觉。启动时先手动拉起一次确认没有配置错误sudo -u postgres /usr/local/pgsql/bin/pg_ctl -D /data/pgsql \ -l /data/pgsql/logfile start手动能起来之后立刻把 systemd unit 文件补上否则机器一重启PG 又变成没装过的状态。unit 文件写到 /etc/systemd/system/postgresql.servicecat /etc/systemd/system/postgresql.service EOF [Unit] DescriptionPostgreSQL database server Afternetwork.target [Service] Userpostgres ExecStart/usr/local/pgsql/bin/postgres -D /data/pgsql ExecReload/usr/local/pgsql/bin/pg_ctl -D /data/pgsql reload [Install] WantedBymulti-user.target EOF systemctl daemon-reload systemctl enable --now postgresql注意 ExecStart 用的是 postgres 这个可执行文件而不是 pg_ctl因为前者是前台主进程适合交给 systemd 托管。最后把 psql 等客户端工具加进 PATH避免每次都要写全路径echo export PATH/usr/local/pgsql/bin:$PATH /etc/profile.d/pgsql.sh source /etc/profile.d/pgsql.sh到这里源码方式的离线安装就闭环了。相比 rpm 方式源码安装多出来的工作主要集中在依赖准备和系统服务托管两件事上其余行为和 rpm 实例没有本质区别。5. 离线安装避坑5 个高频故障的现象、原因与解决5.1 yum 装 server 时报缺 libpq.so.5装到一半就停现象yum install postgresql16-server 时提示需要 libpq.so.5()(64bit)但本地仓库里似乎有这个包却仍然装不上。原因本地仓库里缺 postgresql16-libs或者显式装的是 PostgreSQL 15 的 libs。libpq.so.5 是 PostgreSQL 16 的客户端库它由 postgresql16-libs 提供如果 repotrack 只拉了 server 和 contrib没有把 libs 一起拉进来依赖解析就不可能通过。解决回到有网机器上重新 repotrack postgresql16-libs并放在同一个本地仓库目录里。也可以用 rpm -ivh postgresql16-libs-*.rpm 先单独装上再装 server但这样绕过了 yum 的依赖记录之后重装会很乱不推荐。最稳妥的做法是本地仓库里 server、libs、contrib 三类包齐全一次 yum install 全部解决。5.2 root 手动跑 initdb报 Permission denied现象手动执行 initdb -D /var/lib/pgsql/16/data 时提示 could not create directory ... Permission denied但目录明明存在。原因官方 rpm 的初始化脚本 postgresql-16-setup 内部是以 postgres 用户身份跑 initdb 的如果排查时图快用 root 去跑数据目录的属主就被写成 rootinitdb 会尝试在属于 postgres 的父目录下建文件权限对不上就报错了。解决所有 initdb 操作统一用 sudo -u postgres 执行。如果已经用 root 初始化过删掉数据目录里的内容重新用 postgres 用户初始化不要手动 chown 修补因为修补出来的文件权限可能有遗漏。顺便检查一下数据目录的父目录属主比如 /var/lib/pgsql 目录本身要是 postgres 的。5.3 源码 configure 卡在 checking for readline... no现象执行 ./configure 后输出 checking for readline... no然后整个配置流程退出没有给出更具体的错误。原因readline-devel 没装。configure 的这个检查是黑匣子它同时检查头文件和库文件只要 dev 包缺失就直接 no不会告诉你缺的是 readline.h 还是 libreadline.so。解决装 readline-devel 后重新 configure。注意 configure 脚本是有缓存的重新执行前最好 make distclean 清一次现场或者直接解压新目录再编。如果你实在找不到 readline-devel可以用 --without-readline 绕过但这样 psql 会失去命令历史和行编辑功能内网排查问题时非常难受我一般只在极端情况下才这么干。5.4 systemd 启动后服务反复重启日志里提示找不到配置文件现象systemctl start postgresql-16 后服务一直处于 activatingjournalctl -u postgresql-16 显示 could not find configuration file ... postgresql.conf。原因数据目录没有 initdb或者 initdb 的 -D 路径和 systemd unit 文件里的 ExecStart 路径不一致。rpm 安装后如果跳过了 postgresql-16-setup initdb/var/lib/pgsql/16/data 根本不存在服务自然起不来。解决rpm 方式先跑 postgresql-16-setup initdb源码方式先确认 initdb -D 用的路径和 unit 文件 ExecStart 里的 -D 完全一致。改完路径要 systemctl daemon-reload 再 start否则 systemd 还在用旧的 unit 缓存。这个坑我早期踩得最多一次 path 打错排查半小时起步。5.5 局域网客户端连不上连接超时或被拒绝现象网络通的从另一台机器 psql -h 192.168.1.x -U postgres 连接超时或者报 no pg_hba.conf entry for host。原因listen_addresses 还是默认的 localhostpg_hba.conf 没有对应网段的 host 规则或者 5432 端口被防火墙挡了。这三件事经常是叠加的只看一个配置很容易漏。解决按 3.3 的顺序来postgresql.conf 里 listen_addresses 改为 *pg_hba.conf 增加 host all all 网段 scram-sha-256重启服务使监听地址生效再放行 5432 端口。验证时优先用 pg_isready -h 目标机IP -p 5432 看端口层通不通通了再谈 psql 能不能连这样能把问题切成两段排查。6. 装完怎么验收写一个健康检查脚本把离线安装的成果固化下来安装流程走完不能以“psql 能连”作为唯一验收标准尤其是离线环境补一次依赖代价太高。我习惯在交付前跑一遍自制的健康检查脚本把端口、版本、进程、磁盘、备份能力五项一次验完#!/bin/bash # pg_healthcheck.sh —— 离线安装后的最小验收脚本 PGHOST${PGHOST:-127.0.0.1} PGPORT${PGPORT:-5432} PGUSER${PGUSER:-postgres} export PGPASSWORD${PGPASSWORD:-postgres} echo 1. pg_isready /usr/pgsql-16/bin/pg_isready -h $PGHOST -p $PGPORT -U $PGUSER || exit 1 echo 2. 版本与基础查询 /usr/pgsql-16/bin/psql -h $PGHOST -p $PGPORT -U $PGUSER -d postgres \ -c select version(); echo 3. 进程与数据目录空间 ps -ef | grep [p]ostgres | head -5 df -h /var/lib/pgsql/16/data | tail -1 echo 4. 备份可用性 /usr/pgsql-16/bin/pg_dump -h $PGHOST -p $PGPORT -U $PGUSER \ -d postgres -Fc -f /tmp/pg_health_$$.dump \ ls -lh /tmp/pg_health_$$.dump \ rm -f /tmp/pg_health_$$.dump脚本里所有连接参数都支持环境变量覆盖密码不写死在代码里。前三步分别验证端口层可达、数据库层可查询、进程与磁盘空间正常第四步 pg_dump 用 -Fc 输出 custom 格式备份这一步是对 zlib 依赖和备份能力最直接的验证比单纯 select 1 靠谱得多。如果你用的是源码安装把脚本里的 /usr/pgsql-16/bin 换成 /usr/local/pgsql/bin 即可。提示PGPASSWORD 环境变量在 psql 里是明文的内网测试环境用没问题生产环境建议改用 ~/.pgpass 文件或换用其它认证方式。这套脚本我每次离线交付都跑一遍。早年有一次图省事psql 能连就当装完了后来第一次做 pg_dump 时才发现 zlib 没编进去备份文件打出来是坏的在内网里补依赖又折腾了一整天。从那以后备份可用性一定进验收清单宁可验证多花五分钟不要事后跑一趟现场。离线环境每一步都走得比在线慢但每一步都可以提前验证把这条安装和验收流程固化下来后面再装第二台、第三台机器就是复制粘贴的活了。希望帮到你。本文还有配套的精品资源点击获取