国产服务器操作系统下 PostgreSQL 一键自动化部署方案

追求高稳定性、后续接维方便的技术团队,值得收藏的一套“笔记式”脚本。

1. 业务场景描述

最近我们在一个政务客户现场做数据库交付。客户要求部署一套满足等保2.0的 PostgreSQL 环境,操作系统为龙蜥8.10。原本手动部署:配置 yum 源、安装包、初始化数据库、调内核参数、开防火墙、配 SELinux、建用户、设置开机自启……一套流程走下来,不踩两三个坑几乎不可能。更麻烦的是,接下来还有 5 套类似环境要交付,而且用了三种不同的国产操作系统。手动做一遍,时间翻倍,还容易漏掉安全配置。

于是我们写了一套一键部署脚本,能自动识别操作系统版本,适配主流国产 OS 和 RHEL 系发行版,跑完即可得到一份生产可用的 PostgreSQL 实例。本文记录这套脚本的设计思路与完整实现,希望能帮到同样在多 OS 环境中“救火”的同行。

2. 目标系统信息与适配系统清单

本脚本针对以下服务器操作系统(均为 x86_64 / aarch64 架构)进行适配:

操作系统 版本 包管理器
银河麒麟 V10 V10 (Server) yum / dnf
openEuler 20.03 LTS / 22.03 LTS yum / dnf
CentOS 8.x dnf
Rocky Linux 8.x / 9.x dnf
AlmaLinux 8.x / 9.x dnf
龙蜥 Anolis OS 7.x / 8.x yum / dnf
统信 UOS 服务器版 V20 (1050a/e) yum / dnf

注意:脚本强制使用 yumdnf(自动检测),不依赖 apt。对于已停止维护的 CentOS 8,仍可通过 vault 源或本地镜像完成安装,本脚本已包含基础处理逻辑。

3. 需求分析与痛点识别

在多个国产 OS 上自动化部署 PostgreSQL,主要面临以下痛点:

  • 包名与软件源差异:部分系统缺省未带 PostgreSQL 官方源,有的甚至把 postgresql-server 包名改为了 postgresql-xx-server。直接用 yum install 可能失败。
  • 防火墙与 SELinux:各系统防火墙服务名不一致(firewalld / iptables),SELinux 默认配置也不同。手工敲命令容易漏掉端口放行。
  • 数据目录规划:生产环境通常要求把数据库放在独立挂载点(如 /data),脚本必须支持自定义路径,并处理好目录权限。
  • 多版本兼容:不同项目可能需要 PostgreSQL 13、14、15、16。脚本应支持通过参数指定版本。
  • 接维友好性:部署完成后,后续运维人员需要快速了解数据目录、日志位置、启停命令。不能只装完就消失。

此外,还要考虑幂等性——同一台机器运行两次脚本不应产生错误或重复初始化。

4. 方案设计思路

为了兼顾兼容性、安全性和可维护性,脚本采用以下设计原则:

  1. 操作系统识别
    通过 /etc/os-release 中的 IDVERSION_ID 判断系统类型,按需调整 yum 仓库配置。对于不能直接使用官方 RPM 源的系统(如银河麒麟 V10),自动改用 PostgreSQL 官方提供的 RHEL 兼容源。

  2. 参数校验与交互
    支持命令行参数:-v(版本),-d(数据目录),-p(端口),-m(内存配置,用于调整 shared_buffers)。若不提供,脚本会给出默认值(版本 14,数据目录 /pgsql/data,端口 5432),并提示用户确认。

  3. 幂等性设计

    • 检查 postgres 用户是否已存在,存在则跳过创建。
    • 检查数据目录是否已初始化(PG_VERSION 文件),已存在则不再执行 initdb
    • 检查 systemd 服务文件是否已配置,已存在则只做启停。
    • 每次运行都会重新生成防火墙规则和 SELinux 策略(确保端口放行)。
  4. 日志记录
    所有操作输出同时写入 /var/log/pg_install.log,便于故障回溯。

  5. 自动化生成运维备忘录
    脚本最后自动生成 /root/postgres_运维命令.txt,包含常用命令、路径、端口、连接示例,直接给客户或接维同事。

  6. 网络与主机要求检查

    • 检查 CPU 核心数、内存大小,若低于建议值(2核、4GB)则警告。
    • 检查数据目录所在磁盘挂载点,若为系统根分区(/)则提示风险。
    • 支持内网专用 VIP 配置(仅输出建议,不强制绑定),端口默认 5432。

5. 脚本核心代码节选

以下为脚本中的关键函数片段(完整脚本附在文末)。

5.1 操作系统检测

detect_os() {
    if [ -f /etc/os-release ]; then
        . /etc/os-release
        OS_ID=$ID
        OS_VERSION=$VERSION_ID
    else
        echo "无法识别操作系统,退出"
        exit 1
    fi
    
    case $OS_ID in
        centos|rocky|almalinux|anolis|openEuler|kylin|uos)
            PKG_MGR="dnf"
            command -v dnf &>/dev/null || PKG_MGR="yum"
            ;;
        *)
            echo "不支持的操作系统: $OS_ID"
            exit 1
    esac
}

5.2 PostgreSQL 官方源配置

setup_pg_repo() {
    local pg_version=$1
    local repo_url="https://download.postgresql.org/pub/repos/yum/reporpms/EL-8-x86_64/pgdg-redhat-repo-latest.noarch.rpm"
    # 对于 aarch64 或其他系统,会动态调整 URL
    if [[ $(uname -m) == "aarch64" ]]; then
        repo_url="https://download.postgresql.org/pub/repos/yum/reporpms/EL-8-aarch64/pgdg-redhat-repo-latest.noarch.rpm"
    fi
    
    # 检查是否已安装
    rpm -q pgdg-redhat-repo &>/dev/null || $PKG_MGR install -y $repo_url
    # 禁用默认的 postgresql 模块(针对 EL8 系统)
    if $PKG_MGR list installed module*postgresql &>/dev/null; then
        $PKG_MGR module disable -y postgresql 2>/dev/null || true
    fi
    $PKG_MGR install -y postgresql${pg_version//./} postgresql${pg_version//./}-server
}

5.3 数据库初始化与 systemd 服务

init_database() {
    local PGDATA=$1
    local PGVERSION=$2
    
    # 创建数据目录并设置权限
    mkdir -p $PGDATA
    chown postgres:postgres $PGDATA
    chmod 750 $PGDATA
    
    # 初始化(如果未初始化)
    if [ ! -f "$PGDATA/PG_VERSION" ]; then
        sudo -u postgres /usr/pgsql-$PGVERSION/bin/initdb -D $PGDATA
    fi
    
    # 调整 postgresql.conf
    cat >> $PGDATA/postgresql.conf << EOF
listen_addresses = '*'
port = $PGPORT
shared_buffers = $SHARED_BUFFERS
log_directory = '/var/log/postgresql'
log_filename = 'postgresql-%a.log'
log_statement = 'ddl'
EOF
    mkdir -p /var/log/postgresql
    chown postgres:postgres /var/log/postgresql
    
    # systemd 服务文件
    cat > /etc/systemd/system/postgresql-$PGVERSION.service << EOF
[Unit]
Description=PostgreSQL $PGVERSION database server
After=network.target

[Service]
Type=forking
User=postgres
Group=postgres
Environment=PGDATA=$PGDATA
ExecStart=/usr/pgsql-$PGVERSION/bin/pg_ctl start -D $PGDATA -s
ExecStop=/usr/pgsql-$PGVERSION/bin/pg_ctl stop -D $PGDATA -s
ExecReload=/usr/pgsql-$PGVERSION/bin/pg_ctl reload -D $PGDATA -s
PIDFile=$PGDATA/postmaster.pid

[Install]
WantedBy=multi-user.target
EOF
    systemctl daemon-reload
    systemctl enable postgresql-$PGVERSION
    systemctl start postgresql-$PGVERSION
}

5.4 生成运维命令备忘文件

generate_ops_note() {
    cat > /root/postgres_运维命令.txt << EOF
========================================
PostgreSQL 运维备忘录
========================================
部署时间   : $(date)
版本       : PostgreSQL $PG_VERSION
数据目录   : $PGDATA
监听端口   : $PGPORT
日志目录   : /var/log/postgresql

--- 常用命令 ---
启动: systemctl start postgresql-$PG_VERSION
停止: systemctl stop postgresql-$PG_VERSION
重启: systemctl restart postgresql-$PG_VERSION
查看状态: systemctl status postgresql-$PG_VERSION

--- 连接数据库 ---
本地: sudo -u postgres psql -p $PGPORT
远程: psql -h <服务器IP> -p $PGPORT -U postgres -d postgres

--- 防火墙已放行端口 $PGPORT (如有firewalld) ---
# 检查防火墙规则: firewall-cmd --list-all

--- SELinux 上下文已设置 ---
# 若自定义数据目录,已执行 semanage fcontext 和 restorecon

--- 每日备份建议(示例)---
# 使用 pg_dump 或 pg_basebackup,建议配合 crontab
# 0 2 * * * /usr/pgsql-$PG_VERSION/bin/pg_dump -U postgres -p $PGPORT yourdb > /backup/db_\$(date +\%Y\%m\%d).sql

--- 慢SQL分析 ---
# 开启日志: 已在 postgresql.conf 中设置 log_min_duration_statement = 1000 (毫秒)
# 查看慢查询: grep "duration" /var/log/postgresql/postgresql-*.log

--- pg_hba.conf 安全加固建议 ---
# 当前文件位置: $PGDATA/pg_hba.conf
# 生产环境请勿使用 "host all all 0.0.0.0/0 md5",应限制具体 IP 段
========================================
EOF
}

6. 部署效果演示

银河麒麟 V10 服务器上执行脚本(假设已准备好 root 环境):

[root@kylin ~]# bash install_postgres.sh -v 15 -d /data/pgsql -p 5432

模拟终端输出如下:

[2026-05-05 10:22:15] [INFO] ===== PostgreSQL 一键部署脚本启动 =====
[2026-05-05 10:22:15] [INFO] 检测到操作系统: anolis (8.10)
[2026-05-05 10:22:15] [INFO] 包管理器: dnf
[2026-05-05 10:22:15] [INFO] 主机硬件: CPU=4核, 内存=7892MB, 磁盘=/data 挂载点独立
[2026-05-05 10:22:15] [WARN] 建议内存不低于 4GB,当前满足。
[2026-05-05 10:22:15] [INFO] 配置 PostgreSQL 15 官方源...
[2026-05-05 10:22:35] [INFO] 安装 PostgreSQL 15 软件包...
[2026-05-05 10:23:02] [INFO] 初始化数据库目录 /data/pgsql ...
[2026-05-05 10:23:05] [INFO] 配置防火墙:放行 5432/tcp (永久)
[2026-05-05 10:23:06] [INFO] 配置 SELinux: 允许 postgresql 读写 /data/pgsql
[2026-05-05 10:23:06] [INFO] 启动 systemd 服务 postgresql-15 ...
[2026-05-05 10:23:08] [INFO] 设置 postgres 用户密码并生成运维命令文件...
[2026-05-05 10:23:08] [INFO] ========== 部署完成 ==========
[2026-05-05 10:23:08] [INFO] 配置摘要:
  数据目录: /data/pgsql
  监听端口: 5432
  日志路径: /var/log/postgresql/postgresql-*.log
  连接命令: sudo -u postgres psql -p 5432
  运维备忘: /root/postgres_运维命令.txt
[2026-05-05 10:23:08] [INFO] 已自动执行: systemctl status postgresql-15 (active)

生成的 /root/postgres_运维命令.txt 内容展示:

========================================
PostgreSQL 运维备忘录
========================================
部署时间   : 2026-05-05 10:23:08
版本       : PostgreSQL 15
数据目录   : /data/pgsql
监听端口   : 5432
日志目录   : /var/log/postgresql

--- 常用命令 ---
启动: systemctl start postgresql-15
停止: systemctl stop postgresql-15
重启: systemctl restart postgresql-15
查看状态: systemctl status postgresql-15

--- 连接数据库 ---
本地: sudo -u postgres psql -p 5432
远程: psql -h <服务器IP> -p 5432 -U postgres -d postgres

--- 防火墙已放行端口 5432 (如有firewalld) ---
# 检查防火墙规则: firewall-cmd --list-all

--- SELinux 上下文已设置 ---
# 若自定义数据目录,已执行 semanage fcontext 和 restorecon

--- 每日备份建议(示例)---
# 使用 pg_dump 或 pg_basebackup,建议配合 crontab
# 0 2 * * * /usr/pgsql-15/bin/pg_dump -U postgres -p 5432 yourdb > /backup/db_$(date +\%Y\%m\%d).sql

--- 慢SQL分析 ---
# 开启日志: 已在 postgresql.conf 中设置 log_min_duration_statement = 1000 (毫秒)
# 查看慢查询: grep "duration" /var/log/postgresql/postgresql-*.log

--- pg_hba.conf 安全加固建议 ---
# 当前文件位置: /data/pgsql/pg_hba.conf
# 生产环境请勿使用 "host all all 0.0.0.0/0 md5",应限制具体 IP 段
========================================

在这里插入图片描述

在这里插入图片描述

7. 后期维护建议

脚本部署完成后,日常运维请注意以下几点:

  • 日常启停:一律使用 systemd 命令(systemctl start/stop/restart postgresql-<版本>),不要直接调用 pg_ctl,否则 systemd 状态可能不同步。
  • 慢SQL分析:脚本已在 postgresql.conf 中加入 log_min_duration_statement = 1000(执行时间超过1秒的SQL会被记录),日志目录 /var/log/postgresql。定期使用 grep 'duration' /var/log/postgresql/postgresql-*.log 分析。
  • 备份建议
    • 逻辑备份:pg_dump 适合中小库,可写 crontab 每天凌晨执行。
    • 物理备份:使用 pg_basebackup 搭配 rsync 做流复制,或者使用 barman 等工具。
  • pg_hba.conf 安全加固
    脚本默认生成的认证规则较宽松(本地 trust,远程 md5)。生产环境务必修改
    # 示例:仅允许内网 /24 网段使用 md5 密码连接
    echo "host all all 192.168.1.0/24 md5" >> /data/pgsql/pg_hba.conf
    systemctl reload postgresql-15
    
  • 监控与告警:建议接入 Prometheus + postgres_exporter,关注连接数、复制延迟、死锁等指标。

8. 制作单位信息

阜阳云动科技技术团队
我们专注于国产基础软件环境下的自动化运维与数据库交付。如有疑问或需要定制化脚本,欢迎通过技术社区与我们交流。


如何获取完整脚本:私信回复(PostgreSQL一键部署)

将以下内容保存为 install_postgres.sh,在目标服务器上以 root 用户执行。

使用方式

chmod +x install_postgres.sh
./install_postgres.sh -v 15 -d /data/pgsql -p 5432 -i 192.168.100.100

脚本运行完毕后,请立即修改 /root/postgres_运维命令.txt 中保存的临时密码,并根据实际安全要求收紧 pg_hba.conf

希望这份笔记能帮你省下几个小时的调试时间。有问题欢迎反馈给阜阳云动科技技术团队。

Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐