PostgreSQLをソースからビルドしよう

# はじめに
直近かかわってるプロジェクトでPostgreSQLの話が出ました。Postgre触ってないのが5年ぐらい経つと思います。はっきり覚えていませんが、最後に使ったのが9系だったと思います。家に帰って調べようと思いましたが、どこから調べたらいいか悩みました。
さぁ、ソースからビルドしようか！となり、やった事を共有することにしました。
今回はUbuntu18.04でビルドをしました。ちなみにDockerでUbuntuのイメージをpullしました。Dockerは日ごろ大変お世話になっています。

<font color="Red">3月8日追記：</font>
**CentOS**でのビルドの仕方を追加しました。上記と同様にDockerでCentos:7をpullしました。
>UbuntuとCentOSのビルドの仕方は全く同じです。
最初のパッケージインストールのコマンドが違うだけです。

## PRE INSTALLATION
### ① パッケージリストのアップデート

まずは、パッケージを管理しているDBを最新の状態にします。（パッケージの更新自体はしません。）

``` Ubuntu.コマンド
root@2b4511afa430:/# apt-get update
Get:1 http://security.ubuntu.com/ubuntu bionic-security InRelease [88.7 kB]
Get:2 http://archive.ubuntu.com/ubuntu bionic InRelease [242 kB]
Get:3 http://archive.ubuntu.com/ubuntu bionic-updates InRelease [88.7 kB]
....
....
```
※CentOSはスキップします。

### ② ビルド用ライブラリのインストール
ビルドに必要とするライブラリは以下のページに書いてあります。
https://www.postgresql.org/docs/12/install-requirements.html
※今回ビルドするのが12.2なので上記のURLになっています。
上記のサイトを参考にインストールしてもいいですが、僕は以下の一つのコマンドで一気に入れました。

``` Ubuntu.コマンド
# apt-get install build-essential
```
``` CentOS.コマンド
# yum groupinstall "Development Tools"
```

これら以外に二つの重要パッケージがあります。それら使わずにビルドする事が可能ですが、その反面一部便利な機能が使えなくなります。
1. readline：矢印キーを押した時にコマンドの履歴を表示するツール
2. zlib： pg_dumpやpg_restoreがデータの圧縮に使うツール

``` Ubuntu.コマンド
# apt-get install libreadline-dev zlib1g-dev
```
``` CentOS.コマンド
# yum install readline-devel zlib-devel
```


### ③ ソースのダウンロード
以下のリンクからビルドしたいバージョンのソースをダウンロードします。
https://www.postgresql.org/ftp/source/
今回は、12.2を使います。
以下のコマンドでダウンロードと解凍を行います。

```bash
# cd /usr/local/src/

# wget https://ftp.postgresql.org/pub/source/v12.2/postgresql-12.2.tar.gz

# tar zxf postgresql-12.2.tar.gz
                                                                                                                                   
```
※「wget」がなかった場合は、以下のコマンドでインストールします。

``` Ubuntu.コマンド
# apt-get install wget
```
``` CentOS.コマンド
# yum install wget
```

## INSTALLATION
やっとビルドの出番です。
### ① configure
今回はビルドようのディレクトリを別に用意します。こうすることで何か問題になった時にそのディレクトリを削除し、再ビルドすれば前のデータが邪魔しません。

```bash
root@2b4511afa430:/usr/local/src# cd postgresql-12.2
root@2b4511afa430:/usr/local/src/postgresql-12.2# mkdir tmp_build_dir
root@2b4511afa430:/usr/local/src/postgresql-12.2# cd tmp_build_dir/
root@2b4511afa430:/usr/local/src/postgresql-12.2/tmp_build_dir#  
```
この場所から以下のコマンドを実行します。

```bash
/usr/local/src/postgresql-12.2/configure --prefix=/opt/postgresql12
```
**--prefix**はあとで出ますが、ここで指定したディレクトリに実行ファイル、ライブラリファイルなどの重要なファイルがインストールされます。
※詳しく知りたい場合は「--prefix」でググってくださいね。

> ここで何しているかというと、ソースディレクトリにある「configure」ファイルを実行し、インストールに必要な環境変数やライブラリのチェックを行っています。チェックした結果、MakeFileが作られます。

### ② make
続いては、configureで作成されたMakeFileに基づいてコンパイルします。

```bash
# make
```

少し時間かかりますが、最後に以下のようなメッセージがでたらOKです。

```bash
省略
make[1]: Entering directory '/usr/local/src/postgresql-12.2/tmp_build_dir/config'
make[1]: Nothing to be done for 'all'.
make[1]: Leaving directory '/usr/local/src/postgresql-12.2/tmp_build_dir/config'
All of PostgreSQL successfully made. Ready to install.
```

### ③ install
そして、上記でコンパイルされたものを**--prefix**で指定したディレクトリにインストールします。

```bash
# make　install
```


最後に以下のようなメッセージがでたらOKです。

```bash
省略
/usr/bin/install -c -m 755 /usr/local/src/postgresql-12.2/config/missing '/opt/postgresql12/lib/pgxs/config/missing'
make[1]: Leaving directory '/opt/temp/build_dir/config'
PostgreSQL installation complete.
```
インストール先の中身が以下のようになります。

```
postgresql12/
|-- bin
|-- include
|-- lib
`-- share
```

## POST INSTALLATION
### ① 環境変数に追加
各ツールがどこからでも実行できるように、実行ファイル群があるディレクトリを[PATHに追加します。](https://qiita.com/_dakc_/items/e26d7540c98e59c6b101)

```bash
export PATH=/opt/postgresql12/bin:$PATH
```

> 上記のやり方は一時的なものです。タミナルを終了するとPATHの値が元の値に戻ります。常に記憶させたい場合は、スタートアップで実行されるファイルに上記のコマンドを追加する必要があります。
例えば、~/.bash_profile、/etc/profile、、

### ① ユーザーの追加
[公式サイト](https://www.postgresql.org/docs/12/postgres-user.html)には、DBのデータへのアクセスは一つの専用のユーザーのみに限定するように勧められています。
>As with any server daemon that is accessible to the outside world, it is advisable to run PostgreSQL under a separate user account. This user account should only own the data that is managed by the server, and should not be shared with other daemons.

新しいユーザー「postgres」を追加します。

```bash
# useradd postgres
```
/homeの下に「postgres」ユーザーのホームディレクトリが作成されます。もし、作成されなかった場合は、**userdel postgres**で削除し、以下のようにホームディレクトリを指定します。

```bash

# useradd --create-home --home-dir /home/posgtres postgres
# ls -al /home
total 12
drwxr-xr-x 1 root     root     4096 Mar  8 04:32 .
drwxr-xr-x 1 root     root     4096 Mar  8 04:12 ..
drwx------ 2 postgres postgres 4096 Mar  8 04:32 posgtres
```
※このホームディレクトリの直下に「data」ディレクトリを作成し、DBのデータを保存します。「/var/lib/pgsql/data」、「/usr/local/pgsql/data」が一般的だと思います。
ここで注意しないといけないのが**所有権**です。上で書いたようにほかのユーザーからはアクセスできないように「postgres」ユーザーのみに権限を与えます。

### ② データの初期化
そして、データベースサーバーを起動するために必要なデータや設定ファイルの準備を行います。
[公式サイト](https://www.postgresql.org/docs/12/creating-cluster.html)には以下のように丁寧に書いてあります。
>Before you can do anything, you must initialize a database storage area on disk. We call this a database cluster. (The SQL standard uses the term catalog cluster.) A database cluster is a collection of databases that is managed by a single instance of a running database server. After initialization, a database cluster will contain a database named postgres, which is meant as a default database for use by utilities, users and third party applications. The database server itself does not require the postgres database to exist, but many external utility programs assume it exists. Another database created within each cluster during initialization is called template1. As the name suggests, this will be used as a template for subsequently created databases; it should not be used for actual work. 

この処理は先ほど作った「postgres」ユーザーで実行します。

```bash
# su postgres
```

データ初期化する方法はほかにもありますが、僕が進めるのが「pg_ctl」を使ったやり方です。この**一つのコマンド**で以下の事ができます。
・　データベース初期化
・　サーバーの起動
・　サーバーの停止
・　サーバーの再起動
等々
まずは、以下のコマンドで初期化処理を実行します。**--pgdata**ではデータを作成するディレクトリを指定します。指定したフォルダーがなくても作ってくれますが、「postgres」ユーザーに作成の権限がある必要があります。今回は「/home/postgres」の直下に「data」を指定しています。上記でユーザー作成した時の権限を確認すれば、「/home/postgres」にはすべての権限（読み，書き、実行）が付いている事が分かります。

```bash
$ pg_ctl --pgdata=/home/posgtres/data initdb
The files belonging to this database system will be owned by user "postgres".
This user must also own the server process.
...
...省略
Success. You can now start the database server using:

    /opt/postgresql12/bin/pg_ctl -D /home/posgtres/data -l logfile start
```
※--pgdataを-Dとして書くこともできます。

### ③ サーバーの起動
既にお気づきだと思いますが、実はDBサーバー起動するためのコマンドが先ほど初期化処理を行った時に一番最後に表示されています。**-l パラメーター**を除けば、初期化処理のコマンドで全く同じです。ただ、最後のパラメーターが「initdb」ではなく「start」になります。
-lまたは、--logにはログファイルを指定します。ここで注意しないといけない点が一つあります。ここで指定したパスにログファイルを作成できる権限が「postgres」ユーザーについている必要があります。
これらを考慮して以下のコマンドを実行するとDBサーバーが起動されます。

```bash
$ pg_ctl --pgdata=/home/posgtres/data --log=/home/posgtres/db.log start
waiting for server to start.... done
server started
```
※ちなみに-lまたは、--logは指定しなくてもサーバーが起動されます。

### ④ サーバーの停止
DBサーバーの停止も簡単です。最後にstopを指定するだけです。

```
$ pg_ctl --pgdata=/home/posgtres/data stop
```

pg_ctlは起動、停止以外に他の事でも役に立ちます。helpで詳細を見てください。

```bash
[postgres@af6184923e89 /]$ pg_ctl --help
pg_ctl is a utility to initialize, start, stop, or control a PostgreSQL server.

Usage:
  pg_ctl init[db]   [-D DATADIR] [-s] [-o OPTIONS]
  pg_ctl start      [-D DATADIR] [-l FILENAME] [-W] [-t SECS] [-s]
                    [-o OPTIONS] [-p PATH] [-c]
  pg_ctl stop       [-D DATADIR] [-m SHUTDOWN-MODE] [-W] [-t SECS] [-s]
  pg_ctl restart    [-D DATADIR] [-m SHUTDOWN-MODE] [-W] [-t SECS] [-s]
                    [-o OPTIONS] [-c]
  pg_ctl reload     [-D DATADIR] [-s]
  pg_ctl status     [-D DATADIR]
  pg_ctl promote    [-D DATADIR] [-W] [-t SECS] [-s]
  pg_ctl logrotate  [-D DATADIR] [-s]
  pg_ctl kill       SIGNALNAME PID

...省略
```

### ⑤ データベースへの接続
まずは、上記の③を参考にし、DBサーバーを起動します。

```bash
$ pg_ctl -D /home/posgtres/data -l /home/posgtres/db.log start
waiting for server to start.... done
server started
```
ここでは「psql」コマンドを追加います。PostgreSQL対話的ターミナルといっているようですが、ターミナルを使ってデータベースにクエリを実行し、その結果を表示してくれるツールと考えればいいかと思います。
データベースを初期化した時に「postgres」名前のDBが作られます。このDBに接続するにはpsqlコマンドを実行するだけです。ここでも注意しないといけないのが「posgres」ユーザーに切り替えて実行する必要があります。

```bash
$ psql
psql (12.2)
Type "help" for help.

postgres=#

```
※　上記ではパラメーターは省略しましたが、以下のように色々指定する事ができます。**psql --help**を実行してみてください。

```bash
$ psql --host=localhost --port=5432 --username=postgres --no-password --dbname=postgres
```

psqlからぬけるには「\q」を入力し、エンターキー押下します。

```bash
$ psql
psql (12.2)
Type "help" for help.

postgres=# \q
$
```

# 最後に
PostgreSQLをビルドから、サーバーへの接続方法まで書きました。
何かの参考になれば幸いです。