From f518cfb2502b746b8e392a295e81ff551e2295e0 Mon Sep 17 00:00:00 2001 From: Daniel Golle Date: Wed, 11 Aug 2021 00:48:15 +0100 Subject: [PATCH] postgresql: improve init script 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 --- libs/postgresql/Makefile | 2 +- libs/postgresql/files/postgresql.init | 33 ++++++++++---- libs/postgresql/files/postgresql.sh | 65 ++++++++++++++++----------- 3 files changed, 65 insertions(+), 35 deletions(-) diff --git a/libs/postgresql/Makefile b/libs/postgresql/Makefile index dd40d8847..eb19b93c9 100644 --- a/libs/postgresql/Makefile +++ b/libs/postgresql/Makefile @@ -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 diff --git a/libs/postgresql/files/postgresql.init b/libs/postgresql/files/postgresql.init index 3d3dbadf4..57613364f 100644 --- a/libs/postgresql/files/postgresql.init +++ b/libs/postgresql/files/postgresql.init @@ -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() { diff --git a/libs/postgresql/files/postgresql.sh b/libs/postgresql/files/postgresql.sh index 8d4e377a4..e1076d54e 100644 --- a/libs/postgresql/files/postgresql.sh +++ b/libs/postgresql/files/postgresql.sh @@ -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" ] && {