☰
PostgreSQL离线安装实战:从依赖编译到远程访问的完整指南
2026/10/13 23:57:50 网站建设 项目流程

简介:这份PostgreSQL离线安装教程,专为在内网或无网络环境下部署数据库的运维人员、数据库管理员与开发者编写,系统整理了依赖包准备、RPM强制安装、CMake编译、源码安装的完整流程,解决离线环境中依赖获取难、安装步骤多的问题。资源以单个Word文档形式提供,大小仅43KB,内容精炼,但覆盖从安装到远程访问配置的关键环节。文档中提供了每一步的具体指令、百度网盘依赖包下载链接,并对adduser无法打开/etc/passwd等常见报错给出了排查思路,能显著提高部署成功率。后续还讲解了通过修改pg_hba.conf与postgresql.conf开启远程访问、初始化数据库、启动服务、创建数据库、修改默认密码等操作,帮助读者快速搭建一套可供远程连接的数据库环境。目前已有795人学习使用,适合作为现场离线实施的实用参考。

1. 离线装 PostgreSQL 到底难在哪:先从一次内网交付说起

做过一次内网数据库交付你就知道,postgresql 离线安装真正的难点不是那几条命令,而是依赖闭环、系统权限和远程访问三层问题叠在一起,稍不留神就在某个细节上翻车。机器没有可用软件源,外网也碰不到,装一个 PostgreSQL 9.5 得先把一堆 RPM 拷进去,手工编译 CMake,再处理 /etc/passwd 被锁、root 不能初始化数据库、改完配置远程连不上这类问题。业务系统之所以选它,很大程度上是看重复杂查询、外键、触发器、多版本并发控制这些特性,而这些特性恰恰要求数据库本身完整装好、配置到位。这篇按我实际跑通的路径,把依赖准备、源码编译、数据库初始化和远程访问完整拆一遍,命令参数和坑位都标注清楚。适合在内网、信创环境做交付的运维和 DBA,也适合第一次在 Linux 上源码装数据库的新手照着走。

2. 离线环境的依赖准备:RPM 批量安装与 CMake 编译

从资源包里把 RPM 依赖包和 PostgreSQL、CMake 源码包一起下载下来,离线部署的第一步不是安装,而是先想清楚依赖怎么闭环。在线环境装软件很简单,yum 会帮你拉齐;离线的麻烦在于没有可用源,只能把依赖包一次拷进服务器,这一步处理不好,后面 configure、make 全都会卡住。这一章把 RPM 批量安装、CMake 编译和依赖自检三件事讲透,这三件做完,环境才算真正就绪。

2.1 RPM 包为什么推荐一把梭:--nodeps --force 的适用范围

原资源里的 rpm -ivh.rpm --nodeps --force 就是为离线场景准备的。拆开看,-i 是安装,-v 显示详细过程,-h 打印进度条,.rpm 匹配当前目录下所有 RPM 包;--nodeps 跳过依赖关系检查,--force 允许覆盖已存在的文件。四个参数组合起来,意思就是“不管缺什么、不管有没有旧文件,先装进去再说”。这套打法适合一次性内网交付,前提是 RPM 包从同版本系统上整体打包过来,机器上也没跑着其他数据库。如果目标机器上已经有基于 libpq 的应用,--force 可能会覆盖旧客户端库,这种场景我就不建议盲加 --force,先单独装缺的包更稳。

# 将所有 RPM 包放到同一目录后批量安装 rpm -ivh *.rpm --nodeps --force # 安装后核对实际装上了什么 rpm -qa | grep -i postgres # 确认主程序可用 pg_config --version

参数上,--nodeps 是双刃剑:安装不会卡在依赖解析上,但某个包如果缺了真正的运行库,问题会推迟到启动阶段才暴露。所以装完一定要做版本核对,不能 install 完就往前走。我在交付时还会顺手记录所有 RPM 包的文件名清单,方便后续在同样系统上复现,这一步在离线环境里等于留了后悔药。如果机器上已经装过 PostgreSQL 的旧版本,先 rpm -qa | grep postgres 看一眼历史痕迹再决定要不要加 --force。

2.2 CMake 源码编译:bootstrap 这一步别跳过

资源里的 CMake 版本是 cmake-3.3.2,属于源码包。为什么要先编译 CMake?因为后续有些 PostgreSQL 扩展和配套组件依赖 CMake 来生成构建文件,离线环境里没有现成的 cmake 二进制,只能自己编译一份。步骤是标准的解压、bootstrap、gmake、gmake install 四段:

# 解压 CMake 源码包 tar xzvf cmake-3.3.2.tar.gz # 进入目录,执行 bootstrap 生成 Makefile cd cmake-3.3.2 ./bootstrap # 编译并安装 gmake gmake install

./bootstrap 的作用类似于 PostgreSQL 的 configure,它会检查当前环境里的编译器,并生成对应平台的 Makefile。这一步不能跳过,直接 gmake 会报找不到 Makefile。gmake 是 GNU make,在 Linux 上一般等价于 make,但很多开源项目为了兼容性会在编译说明里明确要求 gmake。安装完成后默认路径是 /usr/local/bin,我一般会先执行 cmake --version 确认版本号再往下走。如果后续编译 PostgreSQL 时仍然提示找不到 cmake,多半是 PATH 里没带 /usr/local/bin,排查时先看这里。

提示:如果目标机器已经装过 cmake,或者你确定后续用不到需要 CMake 的扩展组件,这一节完全可以跳过。资源里保留它,是为了覆盖那些连 cmake 也没有的最小化系统。

2.3 依赖自检清单:configure 之前先做一次核对

编译 PostgreSQL 源码前,最怕的是 configure 跑一半报缺库。我在内网机器上最常见的缺失是 readline-devel、zlib-devel、bison/flex。readline 负责 psql 的历史命令和行编辑,zlib 负责 pg_dump 等工具的数据压缩,bison 和 flex 参与解析器生成。缺任何一个,configure 都会直接退出,而且不会告诉你该装什么包,只会给一堆 error。所以在编译之前先做一次自检:

# 一次性检查关键编译依赖 rpm -qa | grep -E 'readline-devel|zlib-devel|bison|flex|gcc|make|openssl-devel' # 如果某个包缺失,从资源包的依赖目录里找到对应 RPM 安装 rpm -ivh readline-devel*.rpm zlib-devel*.rpm

下面这张表是 CentOS 7.9 这类系统上源码编译 PostgreSQL 9.5 的常用依赖,供离线环境核对使用:

依赖包缺失时的典型表现对应安装包
readline-develconfigure 报 readline library not foundreadline-devel-*.rpm
zlib-develconfigure 报 zlib library not foundzlib-devel-*.rpm
bisonmake 阶段报语法生成失败,指向 .y 文件bison-*.rpm
flex同上,词法生成失败,指向 .l 文件flex-*.rpm
gccconfigure 报 no acceptable C compilergcc-*.rpm
openssl-devel开启 SSL 支持时缺头文件openssl-devel-*.rpm

检查时别看漏了 gcc 和 make,最小化安装的系统经常连编译器都没有。漏掉 bison 和 flex 更隐蔽,因为 configure 能过,等到 make world 才炸,而且报错信息指向的是一堆 .y 和 .l 文件,对不熟悉构建流程的人来说很容易误判成源码问题。我的习惯是先把这张表在目标机器上跑一遍,缺哪个补哪个,再开始 configure,能省掉后面一半的排查时间。

3. 源码编译安装 PostgreSQL:从 configure 到 initdb 的完整链路

依赖就位之后,进入本体安装。这一章覆盖从解压源码包到数据库能建库、能进库、能改密码的全过程。和网上常见的安装教程比,我会重点讲清楚 prefix 路径为什么一次定死、make world 比 make install 多装了什么、initdb 和 pg_ctl 的参数细节,这些都是实际交付时最容易出问题的位置。

3.1 解压与 configure:prefix 路径一次定死

拿到 PostgreSQL 源码包之后,先根据压缩格式选解压命令。资源里给了 .bz2 和 .gz 两种格式的对应写法:.tar.bz2 用 xjvf(j 代表 bzip2 解压),.tar.gz 用 zxvf(z 代表 gzip 解压)。解压完成后进入源码目录,最关键的一步是 configure:

# 解压源码包 tar xjvf postgresql-9.5.tar.bz2 # 如果是 .gz 格式,则使用: # tar zxvf postgresql-9.5.tar.gz # 进入源码目录并指定安装路径 cd postgresql-9.5 ./configure --prefix=/opt/pgsql

--prefix=/opt/pgsql 决定了 PostgreSQL 最终安装的根目录,编译出来的 bin、lib、share 目录全部挂在它下面。这个路径第一次 configure 定了,后续 initdb 和 pg_ctl 的路径都按它来,中途改会很麻烦,所以我在交付文档里会特意强调:prefix 先想清楚再写。除了 prefix,常用的还有 --with-pgport=5432 指定默认端口、--with-openssl 开启 SSL 支持、--with-perl 和 --with-python 预编译 PL/Perl 和 PL/Python 过程语言。

configure 跑完会输出一大段配置摘要,重点看最后有没有 configure: error。最常见的报错就是前面列的 readline 和 zlib 缺失,按 2.3 的自检清单补齐依赖后重新执行 configure 即可。注意 configure 是一次性的,但它可以被重复执行,所以缺依赖后不需要重头再来,补包之后回到源码目录再跑一次就行。

3.2 make world 和 make install-world:为什么不直接 make install

很多从网上找的教程到这一步都是 make && make install,但这套流程装完会发现 /opt/pgsql/share/extension 目录里少了很多官方扩展。PostgreSQL 自带了一批 contrib 模块,比如 pg_stat_statements(性能统计)、uuid-ossp(UUID 生成)、postgres_fdw(外部数据表),它们默认不会随主程序一起编译,要单独用 make world 一并构建。

# 编译主服务器和所有 contrib 扩展 make world # 安装主服务器和所有 contrib 扩展 make install-world

make world 和 install-world 比普通 make 多编译了 contrib 目录下的所有扩展模块。那为什么不用普通 make?因为 install-world 一次就能把扩展的 .so 和 .sql 控制文件装齐,省得后面要用 pg_stat_statements 时再回来补编译。内网 4 核机器上编译 9.5 大约要二三十分钟,期间不要中断终端会话,我一般习惯用 make world 2>&1 | tee build.log 把完整日志留底,出问题时能回头查是哪一步失败的。

注意:make world 2>&1 | tee build.log 里的 tee 命令会把完整输出同时写到终端和文件,编译失败时这个文件就是排错依据,别省这一步。

排错要点:编译中途报错,滚动到最后 20 行找 error 关键字,不要从头读日志。bison 或 flex 缺失导致的语法生成失败,错误信息会指向 parser 相关的 .y 文件,这种直接装依赖回来重新 make,不需要清掉已有产物,make 会增量编译。

3.3 创建 postgres 系统用户与数据目录:权限模型的起点

PostgreSQL 从设计上就不允许 root 用户初始化或启动数据库,因为数据库一旦被攻破,root 权限意味着整个系统沦陷。所以源码安装后要做两件事:创建一个专用的 postgres 系统用户,再把数据目录的属主切给它。

# 创建系统用户 adduser postgres # 给 postgres 用户设置密码 passwd postgres # 创建数据库数据目录并授权 mkdir /opt/pgsql/data chown -R postgres:postgres /opt/pgsql/data

adduser 失败时,先检查 /etc/passwd 是不是被 chattr 加锁了,这个坑我放第四章细说。passwd postgres 设置的密码是 Linux 系统登录密码,它和后面数据库里 postgres 超级用户的密码是两回事,别混。mkdir 创建的数据目录名字是 data,这里 chown -R 只针对这一层,initdb 之后会在 data 下生成 base、global、pg_wal 等子目录,文件属主都会继承 postgres,所以初始化之前把这一层赋权搞定就很关键。常见翻车点是把 /opt/pgsql 整体 chown 给 postgres,这会连带把 bin、lib 等执行文件的属主也改了,并不必要,我一般只授权 data 目录。

3.4 initdb 初始化与首次启动:-D 和日志文件的细节

数据目录和权限都就位后,切换到 postgres 用户执行初始化。这里用 su - postgres 而不是 su postgres,区别在于前者会重新加载 postgres 用户的环境变量和 PATH,后者只是切换用户 ID,环境变量还是 root 的,后面执行 psql、createdb 时容易遇到命令找不到的诡异问题。

# 切换用户,注意中间的空格和横杠 su - postgres # 初始化数据库实例 /opt/pgsql/bin/initdb -D /opt/pgsql/data # 启动数据库,日志写入文件 /opt/pgsql/bin/pg_ctl -D /opt/pgsql/data -l /opt/pgsql/data/logfile start

initdb -D 指定数据目录,这一条必不可少。建议在初始化时带 -E UTF8 -U postgres -W 三个参数:-E 指定数据库默认编码为 UTF8,-U 指定超级用户名,-W 强制要求为超级用户设置密码。不带 -W 的话,postgres 用户默认是空密码,虽然本地 Unix socket 连接不受影响,但后面配远程访问时密码认证会直接失败。pg_ctl 的 -l 参数指定日志文件路径,原教程写的是 logfile 相对路径,实际执行时如果当前目录不在 postgres 有写权限的位置,启动会报日志文件打不开。我在下面的命令里直接写绝对路径,这个细节至少能避免一个坑。

注意:initdb 完成后会提示 You can now start the database server,看到这段说明数据目录初始化成功,再执行 pg_ctl 才有意义。

启动成功后,用 pg_ctl -D /opt/pgsql/data status 看进程状态,或者直接看日志最后几行有没有 “database system is ready to accept connections”。

3.5 建库、进库、修改超级用户密码:一条命令接一条命令排查

数据库起来之后,剩下就是建库、进库、改密码三步。原教程里的 created xwgh 是笔误,PostgreSQL 的命令是 createdb xwgh。进库后执行 ALTER USER 修改超级用户密码,这一步绕不开:因为远程访问配置里要采用密码认证,没有密码的超级用户等于白配。

# 创建名为 xwgh 的数据库 /opt/pgsql/bin/createdb xwgh # 进入该数据库 /opt/pgsql/bin/psql xwgh # 在 psql 中修改 postgres 超级用户密码 xwgh=# ALTER USER postgres WITH PASSWORD 'postgres'; # 查看当前版本,验证安装结果 xwgh=# SELECT version();

psql 进入数据库后,提示符会变成 库名=#,说明当前是超级用户身份。# 和 = 的区别在于是否在事务块中,这个不用刻意记,看到 # 就知道有管理员权限。ALTER USER 语句要带分号结尾,否则 psql 会一直等待输入。密码建议换成自己的强密码,这里的 postgres 只是演示。执行 SELECT version(); 能看到 PostgreSQL 9.5.x 的版本输出,到这一步,本机安装链路就算完整闭环了。

4. 离线安装避坑:我在内网环境里踩过的那几个坑

这章列的问题我都实际踩过,有的是血泪经验,有的回头想就是一行命令的事。每条按现象、原因、解决三部分写,建议把这一章截图存下来,装机器的时候对照着看,能省掉不少排查时间。

4.1 adduser 报 cannot open /etc/passwd:文件被锁住了

现象:执行 adduser postgres 时直接报 adduser: cannot open /etc/passwd,看起来像是权限不足,但当前明明是 root。

原因:部分加固过的系统或容器镜像对 /etc/passwd 加了 immutable 属性,用 chattr +i 锁住了文件,任何写入操作都会被拒绝,这和权限位无关。

解决:先解除锁定,再创建用户:

chattr -i /etc/passwd adduser postgres

如果创建用户后要设置密码,/etc/shadow 也可能被锁,按同样方式 chattr -i /etc/shadow 处理。操作完成后,如果这台机器是生产环境,建议 chattr +i /etc/passwd 把保护恢复回去。这个坑我翻过一次车,当时在加锁的容器里卡了十几分钟,最后才发现是文件属性问题,lsattr 一下就能看出来。

4.2 initdb 拒绝 root:su 和 su - 是两回事

现象:直接在 root shell 下执行 /opt/pgsql/bin/initdb -D /opt/pgsql/data,报 initdb: cannot be run as root,拒绝执行。

原因:PostgreSQL 出于安全设计,禁止 root 初始化数据库。root 的权限范围太大,一旦数据库被攻破,攻击者能拿到整个系统的控制权,所以它强制要求用普通用户运行。

解决:先创建 postgres 用户和数据目录,再 su - postgres 切换后执行 initdb。这里用 su - 而不是 su,是为了让 PATH、HOME 完整切换到 postgres 的环境,避免后面 createdb、psql 命令找不到,或者日志文件写到没权限的目录里。从那以后我涉及 PostgreSQL 的操作统一写 su -,不写 su。

4.3 pg_ctl 启动失败:日志文件要么没权限要么找不到

现象:pg_ctl -D /opt/pgsql/data -l logfile start 启动报 could not open log file "logfile": Permission denied,或者提示找不到日志文件。

原因:-l 后面是相对路径,执行时当前目录如果是在 /root 下,而 postgres 用户对 /root 没有写权限,日志文件创建不出来,启动直接失败。

解决:日志路径改成 postgres 有权限的绝对路径,比如 /opt/pgsql/data/logfile。启动失败后第一件事就是看日志尾部:tail -100 /opt/pgsql/data/logfile,绝大多数启动报错的根因都在最后 20 行内。我把这条命令当成启动数据库的默认动作,一条 start 接一条 tail,习惯养成了能省大量排查时间。

4.4 本地能连、远程连不上:两个配置改一个都白搭

现象:psql 在服务器本机能正常连接,但用 pgAdmin 或另一台机器的 psql 连接时超时,或者报 Connection refused。

原因:两处配置没有同步。第一处是 postgresql.conf 里的 listen_addresses 默认是 localhost,只监听本机回环地址,外部请求根本到不了数据库;第二处是 pg_hba.conf 里没有允许外部网段连接的规则,即使监听地址放开了,认证阶段也会被直接拒绝。

解决:两个文件一起改,先改监听地址:

# 编辑 /opt/pgsql/data/postgresql.conf listen_addresses = '*'

再改 pg_hba.conf,在 IPv4 连接配置区追加一条:

host all all 0.0.0.0/0 password

然后重启数据库。改完用 netstat -anp | grep 5432 确认监听地址从 127.0.0.1 变成了 0.0.0.0,再用另一台机器实测连接,两个条件缺一个都不通。我把“先监听、后认证、最后重启”当成远程排障的固定顺序,基本没有失手过。

4.5 password 认证的明文传输问题:内网也要知道这个边界

现象:pg_hba.conf 里配了 password 认证,远程能连上了,但抓包发现密码是明文传输的。

原因:password 认证方式本身不加密密码。PostgreSQL 9.5 的加密认证方式是 md5,PG 10 之后才有 scram-sha-256。原教程给的是 password,好处是简单、兼容性好,代价是密码会暴露在同网段里。

解决:内网环境把 password 改成 md5,同时把 postgres 用户密码重新设置一次,因为认证方式变了,密码哈希需要刷新。命令是把 pg_hba.conf 里那行改成:

host all all 0.0.0.0/0 md5

改完一定要重启数据库并重新设置密码。如果要求更高,可以在 configure 时加 --with-openssl,然后在 postgresql.conf 里开启 SSL。这个细节对纯内网部署不一定需要,但跨网段环境我一般不会把 password 直接暴露。

5. 远程访问的验证闭环:改完配置后 30 秒确认一次

远程访问配置表面上是改两个文件,实际上是一个验证闭环:改监听、改认证、重启、验证监听、远程实测,五步缺一步都不算完成。先把 postgresql.conf 里的 listen_addresses 改成 '*',再把 pg_hba.conf 里加一条 host all all 0.0.0.0/0 md5,然后执行:

# 切换到 postgres 用户后重启 su - postgres /opt/pgsql/bin/pg_ctl -D /opt/pgsql/data -l /opt/pgsql/data/logfile restart # 验证监听端口 netstat -anp | grep 5432

看到 0.0.0.0:5432 的监听记录,说明网络层已经开放。再从另一台机器实测连接:

# 从远程机器连接 psql -h 192.168.1.100 -p 5432 -U postgres -d xwgh

如果本地能连、远程还是失败,按顺序查三件事:防火墙有没有放行 5432 端口(CentOS 7 用 firewall-cmd --add-port=5432/tcp --permanent 后 reload);pg_hba.conf 里的规则顺序,PostgreSQL 按文件顺序取第一条匹配规则,不要把 0.0.0.0/0 放在 reject 规则前面;最后才是看数据库日志。认证失败和连接超时的日志表现不一样:连接超时通常在网络层,认证失败会明确提示 password authentication failed。

还有一个容易被忽略的细节:reload 会重新读取 postgresql.conf 和 pg_hba.conf,但 listen_addresses 属于启动参数,必须重启数据库才生效;pg_hba.conf 则 reload 即可。最省事的做法就是 restart,一次全生效。

从那以后我每次离线部署 PostgreSQL,都会在 configure 之前把依赖清单贴到终端跑一遍核对,再在启动数据库前把日志路径写成绝对路径,最后把监听和认证两个文件一次改完才重启。这套顺序帮我少熬了不少夜,希望帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询