#!/sbin/openrc-run # Copyright 1999-2023 Gentoo Foundation # Distributed under the terms of the GNU General Public License v2 extra_started_commands="reload promote" PG_CTL="/usr/@LIBDIR@/postgresql-@SLOT@/bin/pg_ctl" PG_CONTROLDATA="/usr/@LIBDIR@/postgresql-@SLOT@/bin/pg_controldata" description="PostgreSQL @SLOT@ -- the world's most advanced open source database -- ${RC_SERVICE} is a wrapper around pg_ctl with additional administrative checks and convenience" # pid is read by fscanf(3) with the first argument which should be integer, # so this multiple line pidfile can be used. PIDFILE="${DATA_DIR%/}/postmaster.pid" get_config() { [ -f "${PGDATA%/}/postgresql.conf" ] || return 1 eval echo $(sed -e 's:#.*::' "${PGDATA%/}/postgresql.conf" \ | awk '$1 == "'$1'" { print ($2 == "=" ? $3 : $2) }') } depend() { use net provide postgresql if [ "$(get_config log_destination)" = "syslog" ] ; then use logger fi } configured_port=${PGPORT} config_port() { local port=$(get_config port) [ -z ${port} ] || configured_port=${port} } checkconfig() { # Check that DATA_DIR has been set if [ -z "${DATA_DIR}" ] ; then eerror "DATA_DIR not set" eerror "HINT: Perhaps you need to update /etc/conf.d/postgresql-@SLOT@" return 1 fi # Check that DATA_DIR exists if [ ! -d "${DATA_DIR}" ] ; then eerror "Directory not found: ${DATA_DIR}" eerror "HINT: Ensure that DATA_DIR points to the right path." eerror "HINT: Or perhaps you need to create the database cluster:" eerror " emerge --config dev-db/postgresql:@SLOT@" return 1 fi # Check for the existence of PostgreSQL's config files, and set the # proper mode and ownership. # Only three files should be checked as potentially other files # may be in PGDATA that should not be touched. local file for file in postgresql pg_hba pg_ident ; do file="${PGDATA%/}/${file}.conf" if [ -f "${file}" ] ; then checkpath -f -m 0600 -o postgres:postgres "${file}" else eerror "${file} not found" eerror "HINT: mv ${DATA_DIR%/}/*.conf ${PGDATA}" return 1 fi done # Set the proper permission for the socket paths and create it if # it doesn't exist. set -f local IFS=',' s for s in ${PG_SOCKET_DIRECTORIES}; do checkpath -d -m 1775 -o root:postgres "${s}" if [ -e "${s%/}/.s.PGSQL.${configured_port}" ] ; then eerror "Socket conflict." eerror "A server is already listening on:" eerror " ${s%/}/.s.PGSQL.${configured_port}" eerror "HINT: Change PGPORT to listen on a different socket." return 1 fi done set +f } start() { config_port checkconfig || return 1 ebegin "Starting PostgreSQL @SLOT@" rm -f "${DATA_DIR%/}/postmaster.pid" export PGPORT=${configured_port} eval "${PG_EXTRA_ENV:+export} ${PG_EXTRA_ENV}" start-stop-daemon --start --user postgres:postgres \ --pidfile "${PIDFILE}" \ --exec "${PG_CTL}" -- \ start \ -s -w -t ${START_TIMEOUT} -l "${DATA_DIR%/}/postmaster.log" \ -D "${PGDATA}" \ -o "-c data_directory=\"${DATA_DIR}\" \ -c unix_socket_directories=\"${PG_SOCKET_DIRECTORIES}\" \ ${PGOPTS}" local retval=$? if [ ${retval} -ne 0 ] ; then eerror "Check the log for a possible explanation of the above error." eerror "The log may be located at:" eerror " ${DATA_DIR%/}/postmaster.log" eerror "Or wherever you configured PostgreSQL @SLOT@ to log." fi eend ${retval} } stop() { : "${NICE_TIMEOUT:=5}" : "${RUDE_TIMEOUT:=5}" : "${FORCE_TIMEOUT:=5}" # The SIGTERM is the default signal for s-s-d, and corresponds to the # default stop mode 'smart' of postgres. local retry="SIGTERM/${NICE_TIMEOUT}" local seconds=${NICE_TIMEOUT} if yesno RUDE_QUIT; then # retry fast stop mode after NICE_TIMEOUT retry="${retry}/SIGINT/${RUDE_TIMEOUT}" seconds=$(( ${seconds} + ${RUDE_TIMEOUT} )) fi if yesno FORCE_QUIT; then # retry immediate stop mode after RUDE_TIMEOUT retry="${retry}/SIGQUIT/${FORCE_TIMEOUT}" seconds=$(( ${seconds} + ${FORCE_TIMEOUT} )) fi ebegin "Stopping PostgreSQL @SLOT@ (this can take up to ${seconds} seconds)" start-stop-daemon --stop --retry ${retry} --pidfile ${PIDFILE} local retval=$? if [ ${retval} -eq 0 ] ; then # clean up remaining socket files for the case which postgres has crashed before stopping config_port local IFS=',' s for s in ${PG_SOCKET_DIRECTORIES}; do if ls -1 "${s%/}/.s.PGSQL.${configured_port}"* >/dev/null 2>&1; then ewarn "cleaning up remaining socket files in '$s'" rm -vf "${s%/}/.s.PGSQL.${configured_port}"* fi done fi eend ${retval} } status() { default_status local retval=$? local postopts_file="${DATA_DIR%/}/postmaster.opts" if [ $retval -eq 0 -a -r "${postopts_file}" ] ; then einfo "opts: $(cat ${postopts_file})" fi } description_reload="Simply sends the postgres process a SIGHUP signal, causing it to reread its configuration files (postgresql.conf, pg_hba.conf, etc.). This allows changing of configuration-file options that do not require a complete restart to take effect." reload() { ebegin "Reloading PostgreSQL @SLOT@ configuration" start-stop-daemon \ --signal SIGHUP \ --user postgres:postgres \ --pidfile "${PIDFILE}" eend $? } description_promote="If the server is in standby, it is commanded to exit recovery and begin read-write operations." promote() { ebegin "Promoting PostgreSQL @SLOT@" local retval=1 if "${PG_CONTROLDATA}" -D "${DATA_DIR}" 2>/dev/null \ | grep 'in archive recovery' >/dev/null 2>&1; then local promotefile="${DATA_DIR%/}/promote" checkpath -q -f -m 644 -o postgres:postgres "${promotefile}" && \ start-stop-daemon \ --signal SIGUSR1 \ --user postgres:postgres \ --pidfile "${PIDFILE}" retval=$? if [ ${retval} -ne 0 ] ; then rm -f "${promotefile}" fi else eerror "server is not in standby mode" fi eend ${retval} }