From 9c800a8f50b1b3736aa81e646d66a4a1c6812773 Mon Sep 17 00:00:00 2001 From: Pavel Raiskup Date: Sat, 21 Jun 2014 20:37:33 +0200 Subject: configury: prepare for autotools --- .gitignore | 11 ++ Makefile.am | 1 + configure.ac | 131 ++++++++++++++ postgresql-setup | 478 ---------------------------------------------------- postgresql-setup.in | 472 +++++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 615 insertions(+), 478 deletions(-) create mode 100644 .gitignore create mode 100644 Makefile.am create mode 100644 configure.ac delete mode 100644 postgresql-setup create mode 100644 postgresql-setup.in diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2cd6e87 --- /dev/null +++ b/.gitignore @@ -0,0 +1,11 @@ +Makefile +Makefile.in +aclocal.m4 +autom4te.cache/ +config.log +config.status +configure +install-sh +missing +*.log +postgresql-setup diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 0000000..ba79058 --- /dev/null +++ b/Makefile.am @@ -0,0 +1 @@ +bin_SCRIPTS = postgresql-setup diff --git a/configure.ac b/configure.ac new file mode 100644 index 0000000..64cfbd3 --- /dev/null +++ b/configure.ac @@ -0,0 +1,131 @@ +AC_INIT([postgresql-setup], [0.9], [praiskup@redhat.com]) +AM_INIT_AUTOMAKE([foreign -Wall -Werror]) +AC_CONFIG_FILES([Makefile]) +AC_CONFIG_FILES([postgresql-setup], [chmod +x postgresql-setup]) + +# For SELinux purposes use rather runuser +AC_PATH_PROG([SU], [runuser]) +test -z "$ac_cv_path_SU" && + AC_PATH_PROG([SU], [su]) +test -z "$ac_cv_path_SU" && + AC_MSG_ERROR([Neither 'runuser' nor 'su' program found]) + +distro_family=redhat +test -r /etc/redhat-release || + AC_MSG_ERROR([This still works for Red Hat distributions only]) + +# Check package manager is installed +case "$distro_family" in +redhat) + AC_PATH_PROG([RPM], [rpm]) + test -z "$ac_cv_path_RPM" && + AC_MSG_ERROR([RPM package manager is required]) + ;; +esac + +# Make sure that the variable is in './configure --help' output and that it is +# not empty. +m4_define([subst_required_var], [ + AC_ARG_VAR([$1], [$2]) + test -z "$[]$1" && + AC_MSG_ERROR([the \$$1 variable is not set]) +]) + +# Check for main PostgreSQL binary +# -------------------------------- + +AC_ARG_VAR([POSTGRES_BIN], [full path to postgres binary]) +AC_PATH_PROG([POSTGRES_BIN], [postgres]) + + +# PGVERSION & PGMAJORVERSION +# -------------------------- + +if test -z "$PGVERSION" -a -z "$PGMAJORVERSION"; then + test -z "$ac_cv_path_POSTGRES_BIN" && + AC_MSG_ERROR([no postgres binary, can not detect version]) + + AC_MSG_CHECKING([for full version PostgreSQL server]) + raw_version=$("$POSTGRES_BIN" --version) || + AC_MSG_ERROR([command $POSTGRES_BIN --version failed]) + + PGVERSION=${raw_version##* } + AC_MSG_RESULT($PGVERSION) + + PGMAJORVERSION=${PGVERSION%%.[[0-9]]} +fi + +# Detect PGENGINE location +# ------------------------ + +if test -z "$PGENGINE"; then + test -z "$ac_cv_path_POSTGRES_BIN" && + AC_MSG_ERROR([no postgres binary, can not detect PGENGINE]) + PGENGINE=`AS_DIRNAME($POSTGRES_BIN)` +fi + +# pg_upgrade binary +# ----------------- + +AC_PATH_PROG([PG_UPGRADE_BIN], [pg_upgrade]) + +# Detect PREVMAJORVERSION +# ----------------------- +# This sets as a side effect PREV_POSTGRES_BIN, which is used later on. + +if test -z "$PREVMAJORVERSION"; then + case "$distro_family" in + redhat) + AC_MSG_CHECKING([for prev major version]) + test -z "$ac_cv_path_PG_UPGRADE_BIN" && + AC_MSG_ERROR([no pg_upgrade found]) + + PREV_POSTGRES_BIN=$(rpm -ql \ + $(rpm -qf "$ac_cv_path_PG_UPGRADE_BIN") \ + | grep 'bin/postgres' ) + + PREVMAJORVERSION=$(echo $PREV_POSTGRES_BIN \ + | sed 's/.*postgresql-\([[0-9\.]]\+\).*/\1/') + AC_MSG_RESULT($PREVMAJORVERSION) + ;; + esac +fi + +# Detect PREVPGENGINE +# ------------------- + +if test -z "$PREVPGENGINE"; then + PREVPGENGINE=`AS_DIRNAME($PREV_POSTGRES_BIN)` +fi + +# Detect where distribution-like README is +# ---------------------------------------- + +case "$distro_family" in +redhat) + README_DIST=`rpm -ql postgresql | grep README | grep dist` + ;; +esac + +test -z "$INITDB_LOG" && + INITDB_LOG=/var/lib/pgsql/initdb.log + +test -z "$UPGRADE_LOG" && + UPGRADE_LOG=/var/lib/pgsql/pgupgrade.log + +if test -z "$SYSCONFIG_DIR" -a "$distro_family" = redhat; then + SYSCONFIG_DIR=/etc/sysconfig +fi + +# Deal with previous versions +subst_required_var([PGVERSION], [full PG version]) +subst_required_var([PGMAJORVERSION], [major PG version]) +subst_required_var([PGENGINE], [directory where PG server resides]) +subst_required_var([PREVMAJORVERSION], [PG major version to upgrade _from_]) +subst_required_var([PREVPGENGINE], [directory where old PG server resides]) +subst_required_var([README_DIST], [README file for distribution]) +subst_required_var([INITDB_LOG], [log file for initdb]) +subst_required_var([UPGRADE_LOG], [log file for pg_upgrade]) +subst_required_var([SYSCONFIG_DIR], [log file for pg_upgrade]) + +AC_OUTPUT diff --git a/postgresql-setup b/postgresql-setup deleted file mode 100644 index 2a682e2..0000000 --- a/postgresql-setup +++ /dev/null @@ -1,478 +0,0 @@ -#!/bin/bash -# -# postgresql-setup - Initialization and upgrade operations for PostgreSQL - -test -z "$PATH" && export PATH="/sbin:/usr/sbin:/bin:/usr/bin" - -test x"$PGSETUP_DEBUG" != x && set -x && PS4='${LINENO}: ' - -# PGVERSION is the full package version, e.g., 9.0.2 -# Note: the specfile inserts the correct value during package build -PGVERSION=xxxx - -# PGMAJORVERSION is the major version, e.g. 9.0 -PGMAJORVERSION=xxxx - -# PGENGINE is the directory containing the postmaster executable -PGENGINE=xxxx - -# PREVMAJORVERSION is the previous major version, e.g., 8.4, for upgrades -PREVMAJORVERSION=xxxx - -# PREVPGENGINE is the directory containing the previous postmaster executable -PREVPGENGINE=xxxx - -# Pathname of the RPM distribution README -README_RPM_DIST=xxxx - -# Log file for initdb -PGLOG=/var/lib/pgsql/initdb.log - -# Log file for pg_upgrade -PGUPLOG=/var/lib/pgsql/pgupgrade.log - -SYSCONFIG_DIR=/etc/sysconfig - -# For SELinux we need to use 'runuser' not 'su' -if [ -x /sbin/runuser ]; then - SU=runuser -else - SU=su -fi - -USAGE_STRING=$" -Usage: $0 {initdb|upgrade} [--name SERVICE_NAME] - -Script is aimed to help sysadmin with basic database cluster administration. - -The SERVICE_NAME is used for selection of proper unit configuration file; For -more info and howto/when use this script please look at the docu file -$README_RPM_DIST. The 'postgresql' -string is used when no SERVICE_NAME is explicitly passed. - -Available operation mode: - --initdb Create a new PostgreSQL database cluster. This is usually the - first action you perform after PostgreSQL server installation. - --upgrade Upgrade PostgreSQL database cluster to be usable with new - server. Use this if you upgraded your PostgreSQL server to - newer major version (currently from $PREVMAJORVERSION \ -to $PGMAJORVERSION). - -Environment: - PGSETUP_INITDB_OPTIONS Options carried by this variable are passed to - subsequent call of \`initdb\` binary (see man - initdb(1)). This variable is used also during - 'upgrade' mode because the new cluster is actually - re-initialized from the old one. - PGSETUP_PGUPGRADE_OPTIONS Options in this variable are passed next to the - subsequent call of \`pg_upgrade\`. For more info - about possible options please look at man - pg_upgrade(1). - PGSETUP_DEBUG Set to '1' if you want to see debugging output." - -die() { echo >&2 $"FATAL: $@" ; exit 1 ; } -error() { echo >&2 $"ERROR: $@" ; } -error_q() { echo >&2 $" $@" ; } -warn() { echo >&2 $"WARNING: $@" ; } -info() { echo >&2 $" * $@" ; } -debug() { test "$option_debug" = "1" && echo >&2 $"DEBUG: $@"; } - -# -# Alow users to use the old style arguments like -# 'postgresql-setup initdb $SERVICE_NAME'. -case "$1" in initdb|upgrade) - action="--$1" - shift - - warn "using obsoleted argument syntax, try --help" - old_long_args="help,usage,version,debug" - oldargs=`getopt -o "" -l "$old_long_args" -n "old-options" -- "$@"` \ - || die "can't parse old arguments" - eval set -- "$oldargs" - additional_opts= - while true; do - case "$1" in - --version|--help|--usage|--debug) - additional_opts="$additional_opts $1" - shift - ;; - --) - shift - break - ;; - esac - done - - service=postgresql - if test -n "$1"; then - service=$1 - shift - fi - - set -- $additional_opts "$action" --service "$service" "$@" - warn "arguments transformed to: ${0##*/} $@" -esac -# - -option_mode=none -option_service=postgresql -option_port= -option_debug=0 - -sysconfig_pgdata= -sysconfig_pgport= - -unit_pgdata= -unit_pgport= - -conf_pgport= - -pgdata=default -pgport=default - -short_opts="" -long_opts="\ -initdb,upgrade,\ -service:,port:,\ -debug,\ -version,help,usage" - -args=`getopt -o "$short_opts" -l "$long_opts" -n "postgresql-setup" -- "$@"` \ - || die "can't parse arguments" -eval set -- "$args" -parse_fail=0 -while true; do - case "$1" in - --initdb|--upgrade) - if test "$option_mode" != none; then - error "bad argument $1, mode already specified: --$option_mode" - parse_fail=1 - else - option_mode=${1##--} - fi - shift - ;; - - --service) - option_service=$2 - shift 2 - ;; - - --port) - option_port=$2 - shift 2 - ;; - - --debug) - option_debug=1 - shift - ;; - - --help|--usage) - echo "$USAGE_STRING" - exit 0 - ;; - - --version) - echo "postgresql-setup $PGVERSION" - exit 0 - ;; - - --) - shift - break - ;; - - *) - die "author's fault: option $1 not handled" - break - ;; - esac -done - -test $parse_fail -ne 0 && die "can't parse arguments" - -test "$option_mode" = none \ - && die "no mode specified, use --initdb or --upgrade, or --help" - -[[ "$option_port" =~ ^[0-9]*$ ]] \ - || die $"port set to '$option_port', must be integer number" - -test -n "$option_port" && pgport=$option_port - -debug "mode used: $option_mode" -debug "service name: $option_service" -debug "port: $pgport" - -handle_sysconfig() -{ - local mode="$1" - local service="$2" - local sysconfig_file="$SYSCONFIG_DIR/$service" - - test -r "$sysconfig_file" || { - warn "system config file '$sysconfig_file' not found or unreadable" - return 1 - } - - unset PGPORT PGDATA - . "$sysconfig_file" - sysconfig_pgdata="$PGDATA" - sysconfig_pgport="$PGPORT" - unset PGPORT PGDATA - - test -n "$sysconfig_pgdata" && debug "sysconfig pgdata: '$sysconfig_pgdata'" - test -n "$sysconfig_pgport" && debug "sysconfig pgport: $sysconfig_pgport" -} - -# This is mostly for backward compatibility with version <= 9.3.4-7 as this type -# of configuration is not adviced anymore. But user still may override the -# /etc/sysconfig/* settings with Environment= statement in service file. Note -# that this parsing technique fails for PGDATA pathnames containing spaces, but -# there's not much we can do about it given systemctl's output format. - -handle_service_file() -{ - local mode="$1" - local service="$2" - - local systemd_env="$(systemctl show -p Environment "${service}.service")" \ - || { return; } - - for env_var in `echo "$systemd_env" | sed 's/^Environment=//'`; do - # If one variable name is defined multiple times the last definition wins. - case "$env_var" in - PGDATA=*) - unit_pgdata="${env_var##PGDATA=}" - debug "unit's datadir: '$unit_pgdata'" - ;; - PGPORT=*) - unit_pgport="${env_var##PGPORT=}" - debug "unit's pgport: $unit_pgport" - ;; - esac - done -} - -handle_pgconf() -{ - local mode="$1" - local datadir="$2" - local conffile="$datadir/postgresql.conf" - - test "$mode" = initdb && return 0 - - debug "postgresql.conf: $conffile" - - test -r "$conffile" || { - error "config file $conffile is not readable or does not exist" - return 1 - } - - local sp='[[:space:]]' - local sed_expr="s/^$sp*port$sp*=$sp\([0-9]\+\).*/\1/p" - - rv=0 - conf_pgport=`sed -n "$sed_expr" $conffile | tail -1` || rv=1 - test -n "$conf_pgport" && debug "postgresql.conf pgport: $conf_pgport" - return $rv -} - -handle_sysconfig "$option_mode" "$option_service" -handle_service_file "$option_mode" "$option_service" - -test -n "$sysconfig_pgdata" && pgdata="$sysconfig_pgdata" -test -n "$unit_pgdata" && pgdata="$unit_pgdata" - -test "$pgdata" = default && die "no datadir specified" -[[ "$pgdata" =~ ^/.* ]] \ - || die $"the PostgreSQL datadir not absolute path: '$pgdata', try --debug" - -handle_pgconf "$option_mode" "$pgdata" || die "can not parse postgresql.conf" - -test -n "$conf_pgport" && pgport="$conf_pgport" -test -n "$sysconfig_pgport" && pgport="$sysconfig_pgport" -test -n "$unit_pgport" && pgport="$unit_pgport" - -if test $option_mode = initdb -a "$pgport" = default; then - test $option_service == postgresql \ - && pgport=5432 \ - || die $"for initdb $option_service, the --port must be specified" -fi - -test "$pgport" = default \ - && die $"\ -port is not set by postgresql.conf, '$SYSCONFIG_DIR/$option_service' \ -nor by --port" - -# These variables are read by underlying utilites, rather export them. -export PGDATA=$pgdata -export PGPORT=$pgport - -script_result=0 - -# code shared between initdb and upgrade actions -perform_initdb() -{ - if [ ! -e "$pgdata" ]; then - mkdir "$pgdata" || return 1 - chown postgres:postgres "$pgdata" - chmod go-rwx "$pgdata" - fi - - # Clean up SELinux tagging for pgdata - [ -x /sbin/restorecon ] && /sbin/restorecon "$pgdata" - - # Create the initdb log file if needed - if [ ! -e "$PGLOG" -a ! -h "$PGLOG" ]; then - touch "$PGLOG" || return 1 - chown postgres:postgres "$PGLOG" - chmod go-rwx "$PGLOG" - [ -x /sbin/restorecon ] && /sbin/restorecon "$PGLOG" - fi - - # Initialize the database - initdbcmd="$PGENGINE/initdb --pgdata='$pgdata' --auth='ident'" - initdbcmd+=" $PGSETUP_INITDB_OPTIONS" - - $SU -l postgres -c "$initdbcmd" >> "$PGLOG" 2>&1 < /dev/null - - # Create directory for postmaster log files - mkdir "$pgdata/pg_log" - chown postgres:postgres "$pgdata/pg_log" - chmod go-rwx "$pgdata/pg_log" - [ -x /sbin/restorecon ] && /sbin/restorecon "$pgdata/pg_log" - - local pgconf="$pgdata/postgresql.conf" - sed -i "s|^[[:space:]#]*port[[:space:]]=[^#]*|port = $pgport |g" \ - "$pgconf" \ - && grep "^port = " "$pgconf" >/dev/null - - test $? -ne 0 && { - error "can not change port in $pgdata/postgresql.conf" - return 1 - } - - if [ -f "$pgdata/PG_VERSION" ]; then - return 0 - fi - - return 1 -} - -initdb(){ - if [ -f "$pgdata/PG_VERSION" ]; then - error $"Data directory $pgdata is not empty!" - script_result=1 - else - info $"Initializing database in $pgdata." - if perform_initdb; then - info $"Initialized." - else - error $"Initializing database failed, see $PGLOG" - script_result=1 - fi - fi -} - -upgrade(){ - # must see previous version in PG_VERSION - if [ ! -f "$pgdata/PG_VERSION" -o \ - x`cat "$pgdata/PG_VERSION"` != x"$PREVMAJORVERSION" ] - then - error $"Cannot upgrade because the database in $pgdata is not of" - error_q $"compatible previous version $PREVMAJORVERSION." - exit 1 - fi - if [ ! -x "$PGENGINE/pg_upgrade" ]; then - echo - echo $"Please install the postgresql-upgrade RPM." - echo - exit 5 - fi - - # Set up log file for pg_upgrade - rm -f "$PGUPLOG" - touch "$PGUPLOG" || exit 1 - chown postgres:postgres "$PGUPLOG" - chmod go-rwx "$PGUPLOG" - [ -x /sbin/restorecon ] && /sbin/restorecon "$PGUPLOG" - - # Move old DB to pgdataold - pgdataold="${pgdata}-old" - rm -rf "$pgdataold" - mv "$pgdata" "$pgdataold" || exit 1 - - # Create configuration file for upgrade process - HBA_CONF_BACKUP="$pgdataold/pg_hba.conf.postgresql-setup.`date +%s`" - HBA_CONF_BACKUP_EXISTS=0 - - if [ ! -f $HBA_CONF_BACKUP ]; then - mv "$pgdataold/pg_hba.conf" "$HBA_CONF_BACKUP" - HBA_CONF_BACKUP_EXISTS=1 - - # For fluent upgrade 'postgres' user should be able to connect - # to any database without password. Temporarily, no other type - # of connection is needed. - echo "local all postgres ident" > "$pgdataold/pg_hba.conf" - fi - - echo -n $"Upgrading database: " - - # Create empty new-format database - if perform_initdb; then - # Do the upgrade - $SU -l postgres -c "$PGENGINE/pg_upgrade \ - '--old-bindir=$PREVPGENGINE' \ - '--new-bindir=$PGENGINE' \ - '--old-datadir=$pgdataold' \ - '--new-datadir=$pgdata' \ - --link \ - '--old-port=$PGPORT' '--new-port=$PGPORT' \ - --user=postgres \ - $PGSETUP_PGUPGRADE_OPTIONS" \ - >> "$PGUPLOG" 2>&1 < /dev/null - if [ $? -ne 0 ]; then - # pg_upgrade failed - script_result=1 - fi - else - # initdb failed - script_result=1 - fi - - # Move back the backed-up pg_hba.conf regardless of the script_result. - if [ x$HBA_CONF_BACKUP_EXISTS = x1 ]; then - mv -f "$HBA_CONF_BACKUP" "$pgdataold/pg_hba.conf" - fi - - if [ $script_result -eq 0 ]; then - echo $"OK" - echo - echo $"The configuration files were replaced by default configuration." - echo $"The previous configuration and data are stored in folder" - echo $pgdataold. - else - # Clean up after failure - rm -rf "$pgdata" - mv "$pgdataold" "$pgdata" - echo $"failed" - fi - echo - echo $"See $PGUPLOG for details." -} - -# See how we were called. -case "$option_mode" in - initdb) - initdb - ;; - upgrade) - upgrade - ;; - *) - echo >&2 "$USAGE_STRING" - exit 2 -esac - -exit $script_result diff --git a/postgresql-setup.in b/postgresql-setup.in new file mode 100644 index 0000000..65f540a --- /dev/null +++ b/postgresql-setup.in @@ -0,0 +1,472 @@ +#!/bin/bash +# +# postgresql-setup - Initialization and upgrade operations for PostgreSQL + +test -z "$PATH" && export PATH="/sbin:/usr/sbin:/bin:/usr/bin" + +test x"$PGSETUP_DEBUG" != x && set -x && PS4='${LINENO}: ' + +# Full PostgreSQL version, e.g. 9.0.2 +PGVERSION=@PGVERSION@ + +# Major version of PostgreSQL, e.g. 9.0 +PGMAJORVERSION=@PGMAJORVERSION@ + +# Directory containing the postmaster executable +PGENGINE=@PGENGINE@ + +# Previous major version, e.g., 8.4, for upgrades +PREVMAJORVERSION=@PREVMAJORVERSION@ + +# Directory containing the previous postmaster executable +PREVPGENGINE=@PREVPGENGINE@ + +# Distribution README file +README_DIST=@README_DIST@ + +# Log file for initdb +PGLOG=@INITDB_LOG@ + +# Log file for pg_upgrade +PGUPLOG=@UPGRADE_LOG@ + +SYSCONFIG_DIR=@SYSCONFIG_DIR@ + +SU=@SU@ + +USAGE_STRING=$" +Usage: $0 {initdb|upgrade} [--name SERVICE_NAME] + +Script is aimed to help sysadmin with basic database cluster administration. + +The SERVICE_NAME is used for selection of proper unit configuration file; For +more info and howto/when use this script please look at the docu file +$README_DIST. The 'postgresql' +string is used when no SERVICE_NAME is explicitly passed. + +Available operation mode: + --initdb Create a new PostgreSQL database cluster. This is usually the + first action you perform after PostgreSQL server installation. + --upgrade Upgrade PostgreSQL database cluster to be usable with new + server. Use this if you upgraded your PostgreSQL server to + newer major version (currently from $PREVMAJORVERSION \ +to $PGMAJORVERSION). + +Environment: + PGSETUP_INITDB_OPTIONS Options carried by this variable are passed to + subsequent call of \`initdb\` binary (see man + initdb(1)). This variable is used also during + 'upgrade' mode because the new cluster is actually + re-initialized from the old one. + PGSETUP_PGUPGRADE_OPTIONS Options in this variable are passed next to the + subsequent call of \`pg_upgrade\`. For more info + about possible options please look at man + pg_upgrade(1). + PGSETUP_DEBUG Set to '1' if you want to see debugging output." + +die() { echo >&2 $"FATAL: $@" ; exit 1 ; } +error() { echo >&2 $"ERROR: $@" ; } +error_q() { echo >&2 $" $@" ; } +warn() { echo >&2 $"WARNING: $@" ; } +info() { echo >&2 $" * $@" ; } +debug() { test "$option_debug" = "1" && echo >&2 $"DEBUG: $@"; } + +# +# Alow users to use the old style arguments like +# 'postgresql-setup initdb $SERVICE_NAME'. +case "$1" in initdb|upgrade) + action="--$1" + shift + + warn "using obsoleted argument syntax, try --help" + old_long_args="help,usage,version,debug" + oldargs=`getopt -o "" -l "$old_long_args" -n "old-options" -- "$@"` \ + || die "can't parse old arguments" + eval set -- "$oldargs" + additional_opts= + while true; do + case "$1" in + --version|--help|--usage|--debug) + additional_opts="$additional_opts $1" + shift + ;; + --) + shift + break + ;; + esac + done + + service=postgresql + if test -n "$1"; then + service=$1 + shift + fi + + set -- $additional_opts "$action" --service "$service" "$@" + warn "arguments transformed to: ${0##*/} $@" +esac +# + +option_mode=none +option_service=postgresql +option_port= +option_debug=0 + +sysconfig_pgdata= +sysconfig_pgport= + +unit_pgdata= +unit_pgport= + +conf_pgport= + +pgdata=default +pgport=default + +short_opts="" +long_opts="\ +initdb,upgrade,\ +service:,port:,\ +debug,\ +version,help,usage" + +args=`getopt -o "$short_opts" -l "$long_opts" -n "postgresql-setup" -- "$@"` \ + || die "can't parse arguments" +eval set -- "$args" +parse_fail=0 +while true; do + case "$1" in + --initdb|--upgrade) + if test "$option_mode" != none; then + error "bad argument $1, mode already specified: --$option_mode" + parse_fail=1 + else + option_mode=${1##--} + fi + shift + ;; + + --service) + option_service=$2 + shift 2 + ;; + + --port) + option_port=$2 + shift 2 + ;; + + --debug) + option_debug=1 + shift + ;; + + --help|--usage) + echo "$USAGE_STRING" + exit 0 + ;; + + --version) + echo "postgresql-setup $PGVERSION" + exit 0 + ;; + + --) + shift + break + ;; + + *) + die "author's fault: option $1 not handled" + break + ;; + esac +done + +test $parse_fail -ne 0 && die "can't parse arguments" + +test "$option_mode" = none \ + && die "no mode specified, use --initdb or --upgrade, or --help" + +[[ "$option_port" =~ ^[0-9]*$ ]] \ + || die $"port set to '$option_port', must be integer number" + +test -n "$option_port" && pgport=$option_port + +debug "mode used: $option_mode" +debug "service name: $option_service" +debug "port: $pgport" + +handle_sysconfig() +{ + local mode="$1" + local service="$2" + local sysconfig_file="$SYSCONFIG_DIR/$service" + + test -r "$sysconfig_file" || { + warn "system config file '$sysconfig_file' not found or unreadable" + return 1 + } + + unset PGPORT PGDATA + . "$sysconfig_file" + sysconfig_pgdata="$PGDATA" + sysconfig_pgport="$PGPORT" + unset PGPORT PGDATA + + test -n "$sysconfig_pgdata" && debug "sysconfig pgdata: '$sysconfig_pgdata'" + test -n "$sysconfig_pgport" && debug "sysconfig pgport: $sysconfig_pgport" +} + +# This is mostly for backward compatibility with version <= 9.3.4-7 as this type +# of configuration is not adviced anymore. But user still may override the +# /etc/sysconfig/* settings with Environment= statement in service file. Note +# that this parsing technique fails for PGDATA pathnames containing spaces, but +# there's not much we can do about it given systemctl's output format. + +handle_service_file() +{ + local mode="$1" + local service="$2" + + local systemd_env="$(systemctl show -p Environment "${service}.service")" \ + || { return; } + + for env_var in `echo "$systemd_env" | sed 's/^Environment=//'`; do + # If one variable name is defined multiple times the last definition wins. + case "$env_var" in + PGDATA=*) + unit_pgdata="${env_var##PGDATA=}" + debug "unit's datadir: '$unit_pgdata'" + ;; + PGPORT=*) + unit_pgport="${env_var##PGPORT=}" + debug "unit's pgport: $unit_pgport" + ;; + esac + done +} + +handle_pgconf() +{ + local mode="$1" + local datadir="$2" + local conffile="$datadir/postgresql.conf" + + test "$mode" = initdb && return 0 + + debug "postgresql.conf: $conffile" + + test -r "$conffile" || { + error "config file $conffile is not readable or does not exist" + return 1 + } + + local sp='[[:space:]]' + local sed_expr="s/^$sp*port$sp*=$sp\([0-9]\+\).*/\1/p" + + rv=0 + conf_pgport=`sed -n "$sed_expr" $conffile | tail -1` || rv=1 + test -n "$conf_pgport" && debug "postgresql.conf pgport: $conf_pgport" + return $rv +} + +handle_sysconfig "$option_mode" "$option_service" +handle_service_file "$option_mode" "$option_service" + +test -n "$sysconfig_pgdata" && pgdata="$sysconfig_pgdata" +test -n "$unit_pgdata" && pgdata="$unit_pgdata" + +test "$pgdata" = default && die "no datadir specified" +[[ "$pgdata" =~ ^/.* ]] \ + || die $"the PostgreSQL datadir not absolute path: '$pgdata', try --debug" + +handle_pgconf "$option_mode" "$pgdata" || die "can not parse postgresql.conf" + +test -n "$conf_pgport" && pgport="$conf_pgport" +test -n "$sysconfig_pgport" && pgport="$sysconfig_pgport" +test -n "$unit_pgport" && pgport="$unit_pgport" + +if test $option_mode = initdb -a "$pgport" = default; then + test $option_service == postgresql \ + && pgport=5432 \ + || die $"for initdb $option_service, the --port must be specified" +fi + +test "$pgport" = default \ + && die $"\ +port is not set by postgresql.conf, '$SYSCONFIG_DIR/$option_service' \ +nor by --port" + +# These variables are read by underlying utilites, rather export them. +export PGDATA=$pgdata +export PGPORT=$pgport + +script_result=0 + +# code shared between initdb and upgrade actions +perform_initdb() +{ + if [ ! -e "$pgdata" ]; then + mkdir "$pgdata" || return 1 + chown postgres:postgres "$pgdata" + chmod go-rwx "$pgdata" + fi + + # Clean up SELinux tagging for pgdata + [ -x /sbin/restorecon ] && /sbin/restorecon "$pgdata" + + # Create the initdb log file if needed + if [ ! -e "$PGLOG" -a ! -h "$PGLOG" ]; then + touch "$PGLOG" || return 1 + chown postgres:postgres "$PGLOG" + chmod go-rwx "$PGLOG" + [ -x /sbin/restorecon ] && /sbin/restorecon "$PGLOG" + fi + + # Initialize the database + initdbcmd="$PGENGINE/initdb --pgdata='$pgdata' --auth='ident'" + initdbcmd+=" $PGSETUP_INITDB_OPTIONS" + + $SU -l postgres -c "$initdbcmd" >> "$PGLOG" 2>&1 < /dev/null + + # Create directory for postmaster log files + mkdir "$pgdata/pg_log" + chown postgres:postgres "$pgdata/pg_log" + chmod go-rwx "$pgdata/pg_log" + [ -x /sbin/restorecon ] && /sbin/restorecon "$pgdata/pg_log" + + local pgconf="$pgdata/postgresql.conf" + sed -i "s|^[[:space:]#]*port[[:space:]]=[^#]*|port = $pgport |g" \ + "$pgconf" \ + && grep "^port = " "$pgconf" >/dev/null + + test $? -ne 0 && { + error "can not change port in $pgdata/postgresql.conf" + return 1 + } + + if [ -f "$pgdata/PG_VERSION" ]; then + return 0 + fi + + return 1 +} + +initdb(){ + if [ -f "$pgdata/PG_VERSION" ]; then + error $"Data directory $pgdata is not empty!" + script_result=1 + else + info $"Initializing database in $pgdata." + if perform_initdb; then + info $"Initialized." + else + error $"Initializing database failed, see $PGLOG" + script_result=1 + fi + fi +} + +upgrade(){ + # must see previous version in PG_VERSION + if [ ! -f "$pgdata/PG_VERSION" -o \ + x`cat "$pgdata/PG_VERSION"` != x"$PREVMAJORVERSION" ] + then + error $"Cannot upgrade because the database in $pgdata is not of" + error_q $"compatible previous version $PREVMAJORVERSION." + exit 1 + fi + if [ ! -x "$PGENGINE/pg_upgrade" ]; then + echo + echo $"Please install the postgresql-upgrade RPM." + echo + exit 5 + fi + + # Set up log file for pg_upgrade + rm -f "$PGUPLOG" + touch "$PGUPLOG" || exit 1 + chown postgres:postgres "$PGUPLOG" + chmod go-rwx "$PGUPLOG" + [ -x /sbin/restorecon ] && /sbin/restorecon "$PGUPLOG" + + # Move old DB to pgdataold + pgdataold="${pgdata}-old" + rm -rf "$pgdataold" + mv "$pgdata" "$pgdataold" || exit 1 + + # Create configuration file for upgrade process + HBA_CONF_BACKUP="$pgdataold/pg_hba.conf.postgresql-setup.`date +%s`" + HBA_CONF_BACKUP_EXISTS=0 + + if [ ! -f $HBA_CONF_BACKUP ]; then + mv "$pgdataold/pg_hba.conf" "$HBA_CONF_BACKUP" + HBA_CONF_BACKUP_EXISTS=1 + + # For fluent upgrade 'postgres' user should be able to connect + # to any database without password. Temporarily, no other type + # of connection is needed. + echo "local all postgres ident" > "$pgdataold/pg_hba.conf" + fi + + echo -n $"Upgrading database: " + + # Create empty new-format database + if perform_initdb; then + # Do the upgrade + $SU -l postgres -c "$PGENGINE/pg_upgrade \ + '--old-bindir=$PREVPGENGINE' \ + '--new-bindir=$PGENGINE' \ + '--old-datadir=$pgdataold' \ + '--new-datadir=$pgdata' \ + --link \ + '--old-port=$PGPORT' '--new-port=$PGPORT' \ + --user=postgres \ + $PGSETUP_PGUPGRADE_OPTIONS" \ + >> "$PGUPLOG" 2>&1 < /dev/null + if [ $? -ne 0 ]; then + # pg_upgrade failed + script_result=1 + fi + else + # initdb failed + script_result=1 + fi + + # Move back the backed-up pg_hba.conf regardless of the script_result. + if [ x$HBA_CONF_BACKUP_EXISTS = x1 ]; then + mv -f "$HBA_CONF_BACKUP" "$pgdataold/pg_hba.conf" + fi + + if [ $script_result -eq 0 ]; then + echo $"OK" + echo + echo $"The configuration files were replaced by default configuration." + echo $"The previous configuration and data are stored in folder" + echo $pgdataold. + else + # Clean up after failure + rm -rf "$pgdata" + mv "$pgdataold" "$pgdata" + echo $"failed" + fi + echo + echo $"See $PGUPLOG for details." +} + +# See how we were called. +case "$option_mode" in + initdb) + initdb + ;; + upgrade) + upgrade + ;; + *) + echo >&2 "$USAGE_STRING" + exit 2 +esac + +exit $script_result -- cgit