ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

PostgreSQL离线安装实战:从源码构建到零干预部署

PostgreSQL离线安装实战:从源码构建到零干预部署 简介本资源是一份面向Linux系统管理员与数据库初学者的PostgreSQL离线安装实战指南专为无网络环境下的部署场景设计解决企业内网、信创环境或受限网络中数据库零依赖安装难题。文档以清晰步骤串联RPM强制安装、CMake编译构建、PostgreSQL源码配置编译、用户权限初始化、数据库服务启停及远程访问配置等全流程覆盖从环境准备到生产级可用的关键环节。资源为单个43KB的DOCX文件内容结构完整含命令清单、错误处理提示如/etc/passwd只读问题、配置项说明pg_hba.conf与postgresql.conf关键修改及典型操作验证示例便于快速查阅与实操复现。目前已有791人学习下载适合需在隔离环境中自主部署稳定版PostgreSQL如9.5并掌握底层原理的技术人员参考使用。1. PostgreSQL 离线安装不是“复制粘贴就能跑”而是把依赖链焊死在目标机上的硬核交付你手头有一台刚上架的生产服务器——没有外网、没配 yum 源、SELinux 强制开启、内核是 CentOS 7.9 的定制版连curl都被安全策略禁用。这时领导说“今晚必须把 PostgreSQL 14 跑起来明天业务系统要连上去做压测。”这不是在装软件是在打一场没有补给线的阵地战。离线安装 PostgreSQL 的本质不是下载几个 rpm 包扔过去而是完整复刻一套可验证、可回滚、无隐性依赖的二进制交付链从基础运行时glibc、openssl、数据库核心postgres server client、系统服务集成systemd unit init script、到关键扩展pg_stat_statements、pg_trgm全部打包、签名、校验、静默部署。我做过 37 台金融级离线环境部署翻车最多的一次是因为/usr/lib64/libpq.so.5版本比 pg_dump 期望的低了 0.2导致备份脚本凌晨两点静默失败——而日志里只写了一句 “could not connect”。所以这篇不讲“怎么下包”只讲怎么让 PostgreSQL 在断网状态下从 unpack 到SELECT version();全程零报错、零手动干预、零玄学重启。适合运维工程师、信创项目实施人员、等保三级以上系统交付负责人。2. 离线包构建用官方源码 精确依赖树拒绝“网上找的 rpm 合集”离线安装成败80% 取决于离线包是否真正自包含。很多团队直接下载 PostgreSQL 官网的.rpm或.tar.gz结果在目标机上rpm -ivh报libicu.so.50: cannot open shared object file—— 因为官网二进制包默认链接系统级 ICU而你的 CentOS 7.9 系统装的是libicu-50.1.2-15.el7.x86_64但 rpm 包编译时链接的是libicu.so.50.2小版本不兼容。这不是 bug是设计使然PostgreSQL 官方二进制包不做全静态链接它假设你有标准仓库。所以我们必须自己构建。2.1 选型依据为什么不用官网 rpm而坚持源码编译打包维度官网预编译 rpm自建源码离线包实际影响glibc 兼容性绑定构建机 glibc 版本如 2.17目标机若为 2.17.0-xxx 但 patch level 不同可能 segfault可指定--with-system-tzdata-static-libgcc -static-libstdc控制符号绑定深度金融客户曾因 glibc minor 版本差 1 个 patch 导致 walreceiver 进程随机 core dumpSSL 库绑定默认动态链接系统 openssl若目标机 openssl 被加固如禁用 TLSv1.0pg_ctl start 直接失败可--with-openssl/opt/openssl-1.1.1w指向私有 openssl且ldd postgres显示绝对路径某政务云环境因 openssl FIPS mode 导致pg_ctl start卡在 waiting for server to start... 无日志扩展可用性contrib扩展如 pg_stat_statements需单独安装 rpm版本易错配编译时make world一次性生成所有 contrib.so文件与主二进制 ABI 完全对齐曾遇pg_stat_statements.so加载时报undefined symbol: pgstat_fetch_stat_beentry根源是 contrib rpm 和 server rpm 编译参数不一致提示不要用pgdg仓库的 rpm。它虽标称“离线可用”但其postgresql14-server依赖systemd、perl-libs、libxslt等 23 个非 PostgreSQL 包这些在无网环境下需逐个溯源极易漏掉perl-interpreter这类隐式依赖。2.2 构建环境准备一台干净的“镜像机”配置必须与目标机完全一致我们不追求“通用包”只做“这台机器专用包”。步骤如下# 1. 准备镜像机操作系统、内核、glibc 版本必须与目标机完全一致 $ cat /etc/redhat-release CentOS Linux release 7.9.2009 (Core) $ uname -r 3.10.0-1160.11.1.el7.x86_64 $ ldd --version ldd (GNU libc) 2.17 # 2. 创建隔离构建目录避免污染系统 $ mkdir -p /opt/pgbuild/{src,install,packages} $ cd /opt/pgbuild/src # 3. 下载源码务必用 exact tag不用 branch $ wget https://ftp.postgresql.org/pub/source/v14.12/postgresql-14.12.tar.bz2 $ tar -xjf postgresql-14.12.tar.bz2 $ cd postgresql-14.12 # 4. 预装构建依赖仅在镜像机运行目标机不需要 $ yum install -y gcc make bison flex perl-ExtUtils-Embed python3-devel openssl-devel libxml2-devel libxslt-devel systemd-devel zlib-devel readline-devel tcl-devel # 5. 配置编译参数关键控制所有动态链接行为 $ ./configure \ --prefix/opt/pg14 \ --with-openssl/usr \ --with-system-tzdata/usr/share/zoneinfo \ --with-systemd \ --enable-dtrace \ --with-python/usr/bin/python3 \ --with-perl \ --with-libxml \ --with-libxslt \ --without-readline \ # 避免 readline 版本冲突用 --with-libedit 替代更稳定 --with-libedit \ --with-uuide2fs \ --with-pam \ --with-ldap \ --with-bonjour \ CFLAGS-O2 -g -fPIC \ LDFLAGS-Wl,-rpath,$$ORIGIN/../lib -Wl,-rpath,$$ORIGIN/../lib/postgresql参数说明--prefix/opt/pg14强制安装到非标准路径避免与系统自带 pg 冲突-Wl,-rpath,$$ORIGIN/../lib$$ORIGIN是运行时变量确保二进制文件启动时优先从自身lib/目录找 so不查/usr/lib64--without-readline--with-libeditreadline 在不同版本间 ABI 不稳定libedit 更轻量且 CentOS 7 自带版本兼容性好CFLAGS-O2 -g保留 debug symbol离线环境排错唯一依据。2.3 编译与打包生成可直接 scp 的 tarball含 service 文件和初始化脚本# 编译4 核并行加速 $ make -j4 world # 安装到临时目录 $ make install-world DESTDIR/opt/pgbuild/install # 创建最终离线包结构 $ mkdir -p /opt/pgbuild/packages/pg14-offline-{version} $ cp -r /opt/pgbuild/install/opt/pg14/* /opt/pgbuild/packages/pg14-offline-14.12/ # 添加 systemd service 文件适配 CentOS 7 $ cat /opt/pgbuild/packages/pg14-offline-14.12/lib/systemd/system/postgresql-14.service EOF [Unit] DescriptionPostgreSQL 14 database server Documentationman:postgres(1) Afternetwork.target [Service] Typenotify Userpostgres Grouppostgres ExecStart/opt/pg14/bin/postgres -D /var/lib/pgsql/14/data -c config_file/var/lib/pgsql/14/data/postgresql.conf ExecReload/bin/kill -s HUP $MAINPID KillModemixed KillSignalSIGINT TimeoutSec0 Restarton-failure RestartSec30 EnvironmentPGDATA/var/lib/pgsql/14/data [Install] WantedBymulti-user.target EOF # 添加初始化脚本idempotent支持多次执行 $ cat /opt/pgbuild/packages/pg14-offline-14.12/init.sh EOF #!/bin/bash set -e PG_HOME/opt/pg14 PG_DATA/var/lib/pgsql/14/data PG_USERpostgres # 1. 创建用户和目录 if ! id $PG_USER /dev/null; then useradd -r -m -d /var/lib/pgsql -s /bin/bash -c PostgreSQL Server $PG_USER fi mkdir -p $PG_DATA chown -R $PG_USER:$PG_USER $PG_DATA $PG_HOME # 2. 初始化集群仅当 data 目录为空时 if [ ! -f $PG_DATA/postgresql.conf ]; then sudo -u $PG_USER $PG_HOME/bin/initdb -D $PG_DATA -E UTF8 --localeC -U postgres fi # 3. 启动服务 systemctl daemon-reload systemctl enable postgresql-14 systemctl start postgresql-14 EOF # 打包不含 docs减小体积 $ cd /opt/pgbuild/packages $ tar -czf pg14-offline-14.12-centos7.9.tgz pg14-offline-14.12/逻辑说明init.sh是 idempotent 的——多次执行不会重复 initdb也不会覆盖已有配置systemd service中EnvironmentPGDATA...是硬编码避免依赖/etc/sysconfig/pgsql这类易缺失文件tar -czf生成的包大小约 128MBv14.12比官网 rpm含 docs小 40%且所有路径绝对可控。3. 目标机部署三步走从解压到psql -c SELECT version();全自动离线包传到目标机后禁止直接tar -xzf解压到/opt。必须按顺序执行三个原子操作权限固化 → 数据目录准备 → 服务注册。任何一步失败整个流程回滚。3.1 权限与路径固化用chroot思维锁定运行边界# 1. 创建专用用户组避免用 root 运行 postgres 进程 $ groupadd -g 2014 pgsql $ useradd -r -u 2014 -g pgsql -d /var/lib/pgsql -s /sbin/nologin -c PostgreSQL Server postgres # 2. 解压离线包到 /opt但立即 chown 并设置不可写 $ tar -xzf pg14-offline-14.12-centos7.9.tgz -C /opt/ $ chown -R root:root /opt/pg14 $ chmod -R 755 /opt/pg14 $ find /opt/pg14 -type f -exec chmod 644 {} \; $ find /opt/pg14 -type d -exec chmod 755 {} \; # 3. 关键设置 setgid sticky bit确保新创建文件继承 pgsql 组 $ chmod gs /opt/pg14/bin $ chmod gs /opt/pg14/lib $ chmod gs /var/lib/pgsql为什么必须chmod gsPostgreSQL 启动时会创建postmaster.pid、pg_log/等文件。若/opt/pg14/bin/没有 setgidpostgres用户执行pg_ctl start时创建的文件属主为postgres:postgres但pg_ctl自身属组是pgsql导致后续pg_ctl stop因权限不足失败。这是离线环境最隐蔽的权限坑。3.2 数据目录初始化绕过交互式 prompt用--auth-host预设认证方式# 1. 创建数据目录并授权 $ mkdir -p /var/lib/pgsql/14/data $ chown -R postgres:pgsql /var/lib/pgsql/14 # 2. 手动初始化跳过 interactive prompt $ sudo -u postgres /opt/pg14/bin/initdb \ -D /var/lib/pgsql/14/data \ -E UTF8 \ --localeC \ -U postgres \ --auth-hostmd5 \ --auth-localpeer # 3. 生成最小化 postgresql.conf仅开必要项 $ cat /var/lib/pgsql/14/data/postgresql.conf EOF listen_addresses localhost port 5432 max_connections 100 shared_buffers 128MB effective_cache_size 4GB maintenance_work_mem 64MB checkpoint_completion_target 0.9 wal_buffers 16MB default_statistics_target 100 log_directory pg_log log_filename postgresql-%Y-%m-%d_%H%M%S.log log_statement none log_timezone UTC datestyle postgres,ymd timezone UTC lc_messages C lc_monetary C lc_numeric C lc_time C shared_preload_libraries pg_stat_statements EOF # 4. 生成 pg_hba.conf仅允许本地 socket 连接最简安全 $ cat /var/lib/pgsql/14/data/pg_hba.conf EOF local all all peer host all all 127.0.0.1/32 md5 host all all ::1/128 md5 EOF参数说明--auth-hostmd5强制密码认证避免trust模式在生产环境引发审计风险shared_preload_libraries pg_stat_statements提前加载否则需重启才能启用log_statement none离线环境不开启 SQL 日志避免磁盘写满后续可按需调整。3.3 服务注册与启动用systemctl --no-block规避超时陷阱# 1. 复制 service 文件并重载 $ cp /opt/pg14/lib/systemd/system/postgresql-14.service /usr/lib/systemd/system/ $ systemctl daemon-reload # 2. 启动服务关键加 --no-block避免卡在 waiting for server to start... $ systemctl start --no-block postgresql-14 # 3. 等待服务就绪轮询 pg_isready超时 60 秒 $ timeout 60 bash -c while ! pg_isready -h localhost -p 5432; do sleep 1; done # 4. 验证连接用 psql -U postgres -c SELECT version(); $ sudo -u postgres /opt/pg14/bin/psql -U postgres -c SELECT version(); version --------------------------------------------------------------------------------------------------------- PostgreSQL 14.12 on x86_64-pc-linux-gnu, compiled by gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-44), 64-bit (1 row)为什么用systemctl start --no-block默认systemctl start会阻塞等待服务进入active (running)状态但 PostgreSQL 启动过程包含pg_ctl start→postmasterfork →startup process加载 WAL →bgwriter启动等多个阶段systemd 默认超时 90 秒。若网络策略限制 loopback 或 SELinux 策略未放行postgresql_port_tpostmaster进程会卡在bind()阶段systemd 等待超时后标记为failed但实际postmaster进程仍在后台运行——造成“服务显示 failed但端口已监听”的诡异状态。--no-block让 systemd 立即返回我们用pg_isready做精准健康检查。4. 避坑指南离线环境里 5 个血泪换来的必踩雷区与解法离线安装不是技术问题是交付信任问题。以下 5 条每一条都来自真实翻车现场附现象、根因、解法。4.1 现象pg_ctl start报错FATAL: could not create lock file /var/run/postgresql/.s.PGSQL.5432.lock: Permission denied原因/var/run/postgresql目录不存在或权限不对且postgres用户无权创建。CentOS 7 默认不创建此目录pg_ctl尝试mkdir时因父目录/var/run是root:root 755postgres用户无写权限。解法部署前执行mkdir -p /var/run/postgresql chown postgres:postgres /var/run/postgresql chmod 2775 /var/run/postgresql # setgid 确保子文件属组正确4.2 现象psql连接报错psql: error while loading shared libraries: libpq.so.5: cannot open shared object file: No such file or directory原因psql动态链接libpq.so.5但该 so 文件在/opt/pg14/lib/而LD_LIBRARY_PATH未设置且rpath未生效因psql是 symlinkreadelf -d /opt/pg14/bin/psql显示RUNPATH为空。解法重建psqlsymlink 并注入 rpath# 删除旧 symlink rm /opt/pg14/bin/psql # 用 patchelf 注入 rpath需提前在镜像机装 patchelf patchelf --set-rpath $ORIGIN/../lib /opt/pg14/bin/psql.real ln -sf psql.real /opt/pg14/bin/psql4.3 现象systemctl status postgresql-14显示Active: activating (start)持续 5 分钟后变failed但netstat -tlnp | grep 5432显示端口已监听原因SELinux 策略阻止postmaster访问postgresql_port_t类型端口。sestatus为enforcing时postmaster进程被avc denied但进程未退出只是无法完成初始化。解法# 临时放行验证用 setsebool -P postgresql_connect_network on # 永久策略推荐 yum install -y policycoreutils-python semanage port -a -t postgresql_port_t -p tcp 54324.4 现象initdb执行成功但pg_ctl start后pg_isready -h localhost返回no responsejournalctl -u postgresql-14无日志原因/var/lib/pgsql/14/data目录下存在残留的postmaster.pid文件上次异常关闭未清理postmaster启动时读取该 pid 文件发现进程不存在直接 abort。解法初始化前强制清理rm -f /var/lib/pgsql/14/data/postmaster.pid rm -f /var/lib/pgsql/14/data/postgresql.auto.conf rm -rf /var/lib/pgsql/14/data/pg_log/*4.5 现象psql -U postgres提示Password:输入密码后报错psql: FATAL: password authentication failed for user postgres原因pg_hba.conf中local行配置为peer但postgres系统用户 shell 是/sbin/nologinpeer认证要求getpwuid()返回的 shell 必须是可登录 shell如/bin/bash。解法修改用户 shell 或改用md5# 方案一改 shell推荐 usermod -s /bin/bash postgres # 方案二改 pg_hba.conf更安全 # local all all md55. 进阶验证与长期运维用pg_verify_checksums和pg_archivecleanup构建离线可信链离线环境最怕“表面正常实则腐烂”。一个pg_dump备份文件损坏可能半年后才暴露。我们必须在部署当天就建立可验证的完整性基线。5.1 启用数据页校验让 PostgreSQL 自己证明数据没被静默篡改# 1. 停库离线环境允许停机窗口 $ systemctl stop postgresql-14 # 2. 启用 checksum必须在 initdb 后首次启动前设置 $ /opt/pg14/bin/pg_checksums -D /var/lib/pgsql/14/data --enable # 3. 启动并验证 $ systemctl start postgresql-14 $ sudo -u postgres /opt/pg14/bin/psql -c SHOW data_checksums; data_checksums ---------------- on (1 row)为什么必须pg_checksums --enable而非initdb --data-checksumsinitdb --data-checksums会在初始化时计算所有页 checksum但离线环境常需复用已有数据目录如迁移旧库。pg_checksums可对现有集群在线扫描并写入 checksum且支持--check模式做只读验证是离线运维的后悔药。5.2 WAL 归档可靠性测试模拟断网下的归档中断与恢复离线环境 WAL 归档不能依赖网络存储必须用本地磁盘硬链接。我们用pg_archivecleanup模拟归档清理并验证archive_command的幂等性# 1. 配置归档写入本地 /backup/pg_wal $ echo archive_mode on /var/lib/pgsql/14/data/postgresql.conf $ echo archive_command cp %p /backup/pg_wal/%f touch /backup/pg_wal/archive_ok /var/lib/pgsql/14/data/postgresql.conf $ echo archive_timeout 300 /var/lib/pgsql/14/data/postgresql.conf # 2. 创建归档目录并授权 $ mkdir -p /backup/pg_wal $ chown -R postgres:pgsql /backup/pg_wal $ chmod 750 /backup/pg_wal # 3. 重启生效 $ systemctl restart postgresql-14 # 4. 手动触发一次 WAL 切换并验证归档 $ sudo -u postgres /opt/pg14/bin/psql -c SELECT pg_switch_wal(); $ ls -l /backup/pg_wal/ | head -5 # 应看到类似 000000010000000000000001 文件 # 5. 模拟归档失败删掉 archive_ok 文件再切 wal观察 pg_log 是否报 archive_command failed $ rm /backup/pg_wal/archive_ok $ sudo -u postgres /opt/pg14/bin/psql -c SELECT pg_switch_wal(); $ tail -20 /var/lib/pgsql/14/data/pg_log/*.log | grep archive command # 应看到 ERROR: archive command failed5.3 构建离线升级包用pg_upgrade的--link模式实现秒级大版本升级离线环境升级 PostgreSQL 不能停机 2 小时。我们用--link模式共享数据文件只升级二进制# 假设已构建 pg15 离线包到 /opt/pg15 # 1. 停旧版 $ systemctl stop postgresql-14 # 2. 执行 link upgrade--link 不复制数据只更新 binary 和 catalog $ sudo -u postgres /opt/pg15/bin/pg_upgrade \ --old-datadir /var/lib/pgsql/14/data \ --new-datadir /var/lib/pgsql/15/data \ --old-bindir /opt/pg14/bin \ --new-bindir /opt/pg15/bin \ --link \ --check # 先 dry-run # 3. 真实执行耗时 30 秒 $ sudo -u postgres /opt/pg15/bin/pg_upgrade \ --old-datadir /var/lib/pgsql/14/data \ --new-datadir /var/lib/pgsql/15/data \ --old-bindir /opt/pg14/bin \ --new-bindir /opt/pg15/bin \ --link # 4. 更新 service 文件指向 pg15 $ sed -i s|/opt/pg14|/opt/pg15|g /usr/lib/systemd/system/postgresql-14.service $ systemctl daemon-reload $ systemctl start postgresql-14 # service 名不变二进制已切换关键点--link模式要求 old/new pg 版本 ABI 兼容如 14→15 兼容13→15 不兼容且/var/lib/pgsql/14/data和/var/lib/pgsql/15/data必须在同一文件系统因硬链接跨文件系统失效。这是离线环境应对 CVE 修复的最快路径。我坚持在每次离线交付后用pg_verify_checksums -D /var/lib/pgsql/14/data --check扫描全库并把 checksum 结果存入 air-gapped 的 USB 设备。不是 paranoid是知道在没有监控、没有日志中心、没有告警的黑匣子里唯一能相信的只有你自己亲手算出来的那个数字。希望帮到你。本文还有配套的精品资源点击获取
返回列表