# 编译源码安装Postgresql和PostGIS（17.4和3.5.2）

> wandoubaba / 2025-04-23

## 介绍

Postgresql简称Postgres或者PG，是开源免费的关系型数据库，各方面指标都可以平替Mysql，甚至可以替代商业数据库产品。

PostGIS是PG的一个可以支持地理信息数据的扩展。

目前笔者刚开始学习GIS领域的知识，需要用到GIS数据库，由于对PG比较了解，所以就自然选择了PostGIS。

## 环境

学习任何技术都要先从环境开始，本来Docker已经很流行了，在hub.docker.com上也有PostGIS的官方镜像，但是为了学习，我决定先从编译安装开始，下面我将记录整个过程。

本指南的环境如下：

|环境项|版本|
|---|---|
|操作系统|Debian 12 Arm64|
|Postgres|17.4|
|PostGIS|3.5.2|

## 安装

### 创建postgres用户和组

```sh
sudo groupadd postgres
sudo useradd -g postgres -m postgres
```

### 安装依赖

```sh
sudo apt-get install -y \
    bzip2 \
    build-essential \
    git wget curl \
    libicu-dev \
    pkg-config \
    bison \
    flex \
    libreadline-dev \
    zlib1g-dev \
    libsystemd-dev \
    libxml2-utils
```

### 下载源码

```sh
curl -O https://ftp.postgresql.org/pub/source/v17.4/postgresql-17.4.tar.bz2
curl -O https://postgis.net/stuff/postgis-3.5.2.tar.gz
```

### 编译安装Postgres

#### 编译

由于安装后我打算通过systemctl设置系统服务，所以加上`--with-systemd`参数

```sh
tar jxvf postgresql-17.4.tar.bz2
cd postgresql-17.4
./configure --with-systemd
```

#### 构建并安装

```sh
make all
make install
```

#### 配置环境

```sh
echo 'export PATH=/usr/local/pgsql/bin:$PATH' >> /etc/profile.d/postgres.sh
echo 'export LD_LIBRARY_PATH=/usr/local/pgsql/lib:$LD_LIBRARY_PATH' >>  /etc/profile.d/postgres.sh
source /etc/profile.d/postgres.sh
```

这里可以验证一下

```sh
psql --version
```

应该可以看到结果

```sh
psql (PostgreSQL) 17.4
```

#### 初始化数据库

```sh
sudo mkdir -p /usr/local/pgsql/data
sudo chown -R postgres:postgres /usr/local/pgsql/data
sudo su - postgres -c 'initdb -D /usr/local/pgsql/data'
```

最后一句执行后应该可以看到类似下面的结果

```sh
su: warning: cannot change directory to /home/postgres: No such file or directory
The files belonging to this database system will be owned by user "postgres".
This user must also own the server process.

The database cluster will be initialized with locale "en_US.UTF-8".
The default database encoding has accordingly been set to "UTF8".
The default text search configuration will be set to "english".

Data page checksums are disabled.

fixing permissions on existing directory /usr/local/pgsql/data ... ok
creating subdirectories ... ok
selecting dynamic shared memory implementation ... posix
selecting default "max_connections" ... 100
selecting default "shared_buffers" ... 128MB
selecting default time zone ... Asia/Shanghai
creating configuration files ... ok
running bootstrap script ... ok
performing post-bootstrap initialization ... ok
syncing data to disk ... ok

initdb: warning: enabling "trust" authentication for local connections
initdb: hint: You can change this by editing pg_hba.conf or using the option -A, or --auth-local and --auth-host, the next time you run initdb.

Success. You can now start the database server using:

    pg_ctl -D /usr/local/pgsql/data -l logfile start

```

#### 首次启动postgres服务

```sh
sudo su - postgres -c 'pg_ctl -D /usr/local/pgsql/data -l /usr/local/pgsql/data/logfile start'
```

应该看到类似下面的消息

```sh
waiting for server to start.... done
server started
```

#### 修改配置

编辑`postgresql.conf`

```ini
# 监听IP地址设置为*表示允许其他主机连接
listen_addresses = '*'
# 端口号
port = 5432
```

编辑`pg_hba.conf`，添加下面这一行表示信任来自本地局域网的连接（根据实际情况编写IP地址）

```ini
# IPv4 LAN connections:
host	all		all		192.168.156.0/24	trust
```

#### 重启postgres服务

```sh
sudo su - postgres -c 'pg_ctl -D /usr/local/pgsql/data -l /usr/local/pgsql/data/logfile restart'
```

#### 配置systemd服务

这个时候通过数据库客户端试着连接这个数据库服务，使用用户名`postgres`，密码空，默认数据库`postgres`，端口号`5432`，应该可以连接成功。

接下来我们配置一下`systemd`系统服务：

```sh
vim /etc/systemd/system/postgres.service
```

编辑如下内容

```ini
[Unit]
Description=PostgreSQL database server
Documentation=man:postgres(1)
After=network-online.target
Wants=network-online.target

[Service]
Type=notify
User=postgres
ExecStart=/usr/local/pgsql/bin/postgres -D /usr/local/pgsql/data
ExecReload=/bin/kill -HUP $MAINPID
KillMode=mixed
KillSignal=SIGINT
TimeoutSec=infinity

[Install]
WantedBy=multi-user.target
```

然后让服务生效并实现开机自启

```sh
sudo su - postgres -c 'pg_ctl -D /usr/local/pgsql/data -l /usr/local/pgsql/data/logfile stop'
sudo systemctl daemon-reload
sudo systemctl enable postgres
sudo systemctl start postgres
```

完成上面的操作，postgres服务已经安装完成，重启系统试一下，postgres服务应该可以开机自启。

### 编译安装PostGIS扩展

#### 安装依赖

```sh
apt-get install -y \
    libxml2-dev \
    libgeos-dev \
    libproj-dev \
    libprotobuf-c-dev \
    protobuf-c-compiler \
    libgdal-dev
```

#### 编译

```sh
tar zxvf postgis-3.5.2.tar.gz
cd postgis-3.5.2
./configure \
  --prefix=/usr/local/pgsql \
  --with-pgconfig=/usr/local/pgsql/bin/pg_config \
  --with-geosconfig=/usr/bin/geos-config \
  --with-proj \
  --with-gdalconfig=/usr/bin/gdal-config \
  --with-json-c
```

#### 构建并安装

```sh
make
make install
```

#### 创建数据库并启用PostGIS扩展

```sh
sudo su - postgres -c 'createdb postgis_template'
sudo su - postgres -c 'psql postgis_template -c "CREATE EXTENSION postgis;"'
sudo su - postgres -c 'psql postgis_template -c "CREATE EXTENSION postgis_raster;"'
sudo su - postgres -c 'psql postgis_template -c "CREATE EXTENSION postgis_topology;"
```

### 验证Postgres和PostGIS

```sh
sudo su - postgres -c 'psql -d postgis_template -c "SELECT postgis_full_version();"'
```

应该可以看到类似下面的结果

```sh
POSTGIS="3.5.2 dea6d0a" [EXTENSION] PGSQL="170" GEOS="3.11.1-CAPI-1.17.1" PROJ="9.1.1 NETWORK_ENABLED=OFF URL_ENDPOINT=https://cdn.proj.org USER_WRITABLE_DIRECTORY=/tmp/proj DATABASE_PATH=/usr/share/proj/pro
j.db" (compiled against PROJ 9.1.1) GDAL="GDAL 3.6.2, released 2023/01/02" LIBXML="2.9.14" LIBJSON="0.16" LIBPROTOBUF="1.4.1" WAGYU="0.5.0 (Internal)" TOPOLOGY RASTER
(1 row)
```

再试着进入psql命令行：

```sh
sudo su - postgres -c 'psql -d postgis_template;'
```

在psql命令行中执行下面的SQL：

```sh
SELECT ST_AsText(ST_GeomFromText('POINT(1 1)'));
```

应该能看到下面的结果

```sh
 st_astext
------------
 POINT(1 1)
(1 row)
```

用`exit`命令可以退出psql命令行

## 完成

以上过程是本人边操作边记录的，结束后又在新的虚拟机上重现了一遍，所以可以保证成功。
