Thinking_Out_Loud

OpenWRT上使用PostgreSQL

2018-10-21

遇到了两个大坑,气得要在小本子上狠狠记一笔。

安装PostgreSQL

安装很方便,一切看起来那么美好:

1
> opkg install pgsql-server pgsql-cli

查看安装信息可以发现安装时自动帮我们创建了一个postgres用户,这是一个伏笔。

我安装的版本:

1
2
root@Joe-OpenWrt:~# psql --version
psql (PostgreSQL) 9.6.10

配置PostgreSQL

我们不能以root角色进行配置,可以创建一个postgres用户进行操作。又因为OpenWRT的设计初衷是一个单用户系统,我们需要安装shadow全家桶来polyfill用户组相关功能。

1
> opkg install shadow

注意了,我们需要先删除安装时自动创建的postgres用户,再重新创建,这是一个坑,否则无法用su切换用户(最过分的是无错误提示)。

配置data目录

1
2
3
> chmod -R postgres:postgres /path/to/data
> su postgres
> $LC_COLLATE="C" initdb --pwprompt -D /path/to/data

配置服务

更改UCI中的配置:

1
2
3
> uci set postgresql.config.PGDATA=/path/to/data
> uci set postgresql.config.PGLOG=/path/to/data/postgresql.log
> uci commit

设置开机自启:

1
> /etc/init.d/postgresql enable

但是我发现使用

1
> /etc/init.d/postgresql start

是无法启用服务的,这就是第二个坑。

我们查看/etc/init.d/postgresql文件中的start_service函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
...

procd_open_instance
procd_set_param user postgres
procd_set_param command $PROG
procd_append_param command -D "${pgdata}"
[ -n "${pgopts}" ] && procd_append_param command -o "${pgopts}"
procd_set_param respawn retry=60
procd_close_instance

procd_open_instance
procd_set_param user postgres
procd_set_param command /lib/functions/postgresql.sh init "${pgdata}"
procd_close_instance

...

其中$PROG/usr/bin/postmaster,可知先运行postmaster作为服务的一个实例再运行下面的脚本postgresql.sh。但结果是postmaster实例并没有运行的迹象,仅有postgresql.sh在轮询psql daemon的运行状态等待下一步操作,增加设置将输出重定向到syslog

1
2
procd_set_param stdout 1 # forward stdout of the command to logd
procd_set_param stderr 1 # same for stderr

使用logread也没看到任何输出。

ubus call service list查看服务实例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
"postgresql": {
"instances": {
"instance1": {
"running": false,
"command": [
"\/usr\/bin\/postmaster",
"-D",
"\/mnt\/u\/postgresql\/data\/"
],
"term_timeout": 5,
"respawn": {
"threshold": 0,
"timeout": 5,
"retry": 5
}
},
"instance2": {
"running": true,
"pid": 21518,
"command": [
"\/lib\/functions\/postgresql.sh",
"init",
"\/mnt\/u\/postgresql\/data\/"
],
"term_timeout": 5
}
}
}

可以发现也是没有运行。

最后的最后,我发现只有先运行postgresql.sh实例才能正常运行服务,原因不详(肯定是procd的feature)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
...

procd_open_instance
procd_set_param user postgres
procd_set_param command /lib/functions/postgresql.sh init "${pgdata}"
procd_close_instance

procd_open_instance
procd_set_param user postgres
procd_set_param command $PROG
procd_append_param command -D "${pgdata}"
[ -n "${pgopts}" ] && procd_append_param command -o "${pgopts}"
procd_set_param respawn retry=60
procd_close_instance

...

允许远程连接

  1. 修改.../data/postgresql.conf

    1
    listen_addresses = '*'
  2. 修改.../data/pg_hba.conf

    1
    2
    3
    # Put your actual configuration here
    # ----------------------------------
    host all all 0.0.0.0/0 md5
  3. 重启服务:

    1
    > /etc/init.d/postgresql restart
  4. 验证:

    1
    2
    3
    4
    5
    6
    7
    8
    $ psql -h 192.168.100.1 -U postgres
    Password for user postgres:
    psql (9.5.14, server 9.6.10)
    WARNING: psql major version 9.5, server major version 9.6.
    Some psql features might not work.
    Type "help" for help.

    postgres=#

I AM DONE

参考资料

  1. https://www.cnblogs.com/icez/p/3899147.html
  2. https://openwrt.org/docs/guide-developer/procd-init-scripts