postgresql: improve init script
authorDaniel Golle <daniel@makrotopia.org>
Tue, 10 Aug 2021 23:48:15 +0000 (00:48 +0100)
committerDaniel Golle <daniel@makrotopia.org>
Thu, 12 Aug 2021 02:11:09 +0000 (03:11 +0100)
Use newly introduced procd_add_restart_mount_trigger to make sure
postmaster gets started only once PGDATA becomes available.
Relocate socket directory to /var/lib/postgresql to make it possible
to run postgresql inside a ujail.
Use signal for shutdown, so it works nicely with jail.
Allow multiple script in UCI 'config postgres-db' to be a list and
run them in order listed.
User more silent methods to check for db or role existence and make
it easy to create several databases owned by the same user by passing
the same credentials multiple times.
Remove disfunctional reload handler.

Signed-off-by: Daniel Golle <daniel@makrotopia.org>
libs/postgresql/Makefile
libs/postgresql/files/postgresql.init
libs/postgresql/files/postgresql.sh

index dd40d884731366733edf69a3aa3778929fa26666..eb19b93c94572301cbee243070701cc4e4e781e0 100644 (file)
@@ -70,7 +70,7 @@ endef
 define Package/pgsql-server
   SECTION:=utils
   CATEGORY:=Utilities
-  DEPENDS:=+pgsql-cli
+  DEPENDS:=+pgsql-cli +blockd
   TITLE:=PostgreSQL databases Server
   URL:=http://www.postgresql.org/
   SUBMENU:=Database
index 3d3dbadf47ab36e998ba888f61f63d727da3960e..57613364fad76f60af35d87776c20e133d182b1b 100644 (file)
@@ -32,40 +32,57 @@ start_service() {
        user_exists postgres 5432 || user_add postgres 5432
        group_exists postgres 5432 || group_add postgres 5432
 
+       [ "$_BOOT" = "1" ] &&
+               [ "$(procd_get_mountpoints $pgdata)" ] && return 0
+
        fix_perms
        fix_hosts
 
-       if [ ! -d "${pgdata}" ]; then
+       if [ ! -e "${pgdata}/PG_VERSION" ]; then
                pg_init_data ${pgdata}
                [ $? -gt 0 ] && return 1
        fi
 
        cleanup "${pgdata}"
 
-       procd_open_instance
+       mkdir -m 0755 -p /var/run/postgresql
+       chmod 0750 /var/run/postgresql
+       chown postgres:postgres /var/run/postgresql
+       procd_open_instance postmaster
        procd_set_param user postgres
        procd_set_param command $PROG
        procd_append_param command -D "${pgdata}"
+       procd_append_param command -k "/var/run/postgresql"
        [ -n "${pgopts}" ] && procd_append_param command -o "${pgopts}"
        procd_set_param respawn retry=60
+       procd_add_jail postgresql log
+       procd_add_jail_mount /usr/lib/postgresql /usr/share/postgresql
+       procd_add_jail_mount_rw /var/run/postgresql "${pgdata}"
+       procd_add_jail_mount_rw /dev/shm
+       procd_set_param stderr 1
+       procd_set_param stdout 1
        procd_close_instance
 
-       procd_open_instance
+       procd_open_instance uci_dbinit
        procd_set_param user postgres
        procd_set_param command /lib/functions/postgresql.sh init "${pgdata}"
+       procd_set_param stdout 1
+       procd_set_param stderr 1
        procd_close_instance
 }
 
-reload_service() {
+boot() {
+       _BOOT=1 start
+}
+
+service_triggers() {
        config_load "postgresql"
        config_get pgdata config PGDATA
-       /usr/bin/pg_ctl reload -U postgres -D "${pgdata}" -s
+       procd_add_restart_mount_trigger "${pgdata}"
 }
 
 stop_service() {
-       config_load "postgresql"
-       config_get pgdata config PGDATA
-       /usr/bin/pg_ctl stop -U postgres -D "${pgdata}" -s
+       procd_send_signal "postgresql" postmaster SIGTERM
 }
 
 status_service() {
index 8d4e377a4a778f9e02f2ebc8900388121d809a2c..e1076d54eadb6249a9892f14fef829ed1df31f18 100644 (file)
@@ -5,21 +5,21 @@ PSQL="/usr/bin/psql"
 free_megs() {
        fsdir=$1
        while [ ! -d "$fsdir" ]; do
-               fsdir=$(dirname $fsdir)
+               fsdir="$(dirname "$fsdir")"
        done
        df -m $fsdir | while read fs bl us av cap mnt; do [ "$av" = "Available" ] || echo $av; done
 }
 
 pg_init_data() {
        # make sure we got at least 50MB of free space
-       [ $(free_megs $1) -lt 50 ] && return 1
-       pg_ctl initdb -U postgres -D $1
+       [ $(free_megs "$1") -lt 50 ] && return 1
+       pg_ctl initdb -U postgres -D "$1"
 }
 
 pg_server_ready() {
        t=0
        while [ $t -le 90 ]; do
-               pg_ctl status -U postgres -D $1 2>/dev/null >/dev/null && return 0
+               psql -h /var/run/postgresql/ -U postgres -c "\q" 1>/dev/null 2>/dev/null && return 0
                t=$((t+1))
                sleep 1
        done
@@ -28,21 +28,19 @@ pg_server_ready() {
 
 
 pg_test_db() {
-       if [ "$3" ]; then
-               echo "SHOW ALL;" | env PGPASSWORD="$3" $PSQL -U "$2" -d "$1" -q 2>/dev/null >/dev/null
-               return $?
-       else
-               echo "SHOW ALL;" | $PSQL -w -U "$2" -d "$1" -q 2>/dev/null >/dev/null
-               return $?
-       fi
+       echo "SELECT datname FROM pg_catalog.pg_database WHERE datname = '$1';" |
+               $PSQL -h /var/run/postgresql -w -U "postgres" -d "template1" -q |
+                       grep -q "0 rows" && return 1
+
+       return 0
 }
 
 pg_include_sql() {
        if [ "$3" ]; then
-               env PGPASSWORD="$3" $PSQL -U "$2" -d "$1" -e -f "$4"
+               env PGPASSWORD="$3" $PSQL -h /var/run/postgresql -U "$2" -d "$1" -e -f "$4"
                return $?
        else
-               $PSQL -w -U "$2" -d "$1" -e -f "$4"
+               $PSQL -w -h /var/run/postgresql -U "$2" -d "$1" -e -f "$4"
                return $?
        fi
 }
@@ -50,22 +48,37 @@ pg_include_sql() {
 # $1: dbname, $2: username, $3: password, $4: sql populate script
 pg_require_db() {
        local ret
+       local dbname="$1"
+       local dbuser="$2"
+       local dbpass="$3"
+       local exuser
 
        pg_test_db $@ && return 0
-       ( echo "CREATE DATABASE $1;"
-       echo -n "CREATE USER $2"
-       [ "$3" ] && echo -n " WITH PASSWORD '$3'"
-       echo " NOCREATEDB NOSUPERUSER NOCREATEROLE NOINHERIT;"
-       echo "GRANT ALL PRIVILEGES ON DATABASE \"$1\" TO $2;" ) |
-               $PSQL -U postgres -d template1 -e
-       ret=$?
-       [ "$ret" = "0" ] || return $ret
-
-       if [ "$4" ]; then
-               pg_include_sql "$@"
-               ret=$?
+
+       shift ; shift ; shift
+
+       echo "CREATE DATABASE $dbname;" |
+               $PSQL -h /var/run/postgresql -U postgres -d template1 -e || return $?
+
+       if [ "$dbuser" ]; then
+               echo "SELECT usename FROM pg_catalog.pg_user WHERE usename = '$dbuser';" |
+                       $PSQL -h /var/run/postgresql -U postgres -d template1 -e | grep -q "0 rows" &&
+                       ( echo -n "CREATE USER $dbuser"
+                       [ "$dbpass" ] && echo -n " WITH PASSWORD '$dbpass'"
+                       echo " NOCREATEDB NOSUPERUSER NOCREATEROLE NOINHERIT;" ) |
+                               $PSQL -h /var/run/postgresql -U postgres -d template1 -e
+
+               echo "GRANT ALL PRIVILEGES ON DATABASE \"$dbname\" TO $dbuser;" |
+                       $PSQL -h /var/run/postgresql -U postgres -d template1 -e
        fi
 
+       while [ "$1" ]; do
+               pg_include_sql "$dbname" "$dbuser" "$dbpass" "$1"
+               ret=$?
+               [ $ret != 0 ] && break
+               shift
+       done
+
        return $ret
 }
 
@@ -75,7 +88,7 @@ uci_require_db() {
        config_get dbuser $1 user
        config_get dbpass $1 pass
        config_get dbscript $1 script
-       pg_require_db "$dbname" "$dbuser" "$dbpass" "$dbscript"
+       pg_require_db "$dbname" "$dbuser" "$dbpass" $dbscript
 }
 
 [ "$1" = "init" ] && {