6cb03e
#!/bin/bash
6cb03e
#
6cb03e
# postgresql-setup - Initialization and upgrade operations for PostgreSQL
6cb03e
6cb03e
# For SELinux we need to use 'runuser' not 'su'
6cb03e
if [ -x /sbin/runuser ]; then
6cb03e
    SU=runuser
6cb03e
else
6cb03e
    SU=su
6cb03e
fi
6cb03e
6cb03e
if test "$(id -u)" -eq 0; then
6cb03e
    cmd=
6cb03e
    for v in PGSETUP_DEBUG PGSETUP_INITDB_OPTIONS PGSETUP_PGUPGRADE_OPTIONS; do
6cb03e
        eval var_content=\$$v
6cb03e
        test -z "$var_content" && continue
6cb03e
        cmd+=$v="$(printf %q "$var_content") "
6cb03e
    done
6cb03e
    cmd+=$(printf %q "$(readlink -f "$0")")
6cb03e
    for arg; do cmd+=" $(printf %q "$arg")" ; done
6cb03e
    # Drop root privileges asap.  It's not recommended to run postgresql-setup
6cb03e
    # script under root nowadays; so we take the liberty to switch to the
6cb03e
    # PostgreSQL admin user (by default 'postgres') without any other option.
6cb03e
    exec $SU -s /bin/sh postgres -c "$cmd"
6cb03e
fi
6cb03e
6cb03e
die () { echo >&2 "$*"; exit 1; }
6cb03e
6cb03e
test "$(id -u)" -eq 0 && exit 1
6cb03e
6cb03e
# ensure privacy
6cb03e
umask 0077
6cb03e
6cb03e
: ${RESTORECON=/sbin/restorecon}
6cb03e
test -x $RESTORECON || RESTORECON=:
6cb03e
6cb03e
test x"$PGSETUP_DEBUG" != x && set -x
6cb03e
6cb03e
# PGVERSION is the full package version, e.g., 9.0.2
6cb03e
# Note: the specfile inserts the correct value during package build
6cb03e
PGVERSION=xxxx
6cb03e
6cb03e
# PGMAJORVERSION is the major version, e.g. 9.0
6cb03e
PGMAJORVERSION=xxxx
6cb03e
6cb03e
# PGENGINE is the directory containing the postmaster executable
6cb03e
PGENGINE=xxxx
6cb03e
6cb03e
# PREVMAJORVERSION is the previous major version, e.g., 8.4, for upgrades
6cb03e
PREVMAJORVERSION=xxxx
6cb03e
6cb03e
# PREVPGENGINE is the directory containing the previous postmaster executable
6cb03e
PREVPGENGINE=xxxx
6cb03e
6cb03e
USER=postgres
6cb03e
6cb03e
# Absorb configuration settings from the specified systemd service file,
6cb03e
# or the default "postgresql" service if not specified
6cb03e
SERVICE_NAME="$2"
6cb03e
if [ x"$SERVICE_NAME" = x ]; then
6cb03e
    SERVICE_NAME=postgresql
6cb03e
fi
6cb03e
6cb03e
# Pathname of the RPM distribution README
6cb03e
README_RPM_DIST=xxxx
6cb03e
6cb03e
USAGE_STRING=$"
6cb03e
Usage: $0 {initdb|upgrade} [SERVICE_NAME]
6cb03e
6cb03e
Script is aimed to help sysadmin with basic database cluster administration.
6cb03e
6cb03e
The SERVICE_NAME is used for selection of proper unit configuration file; For
6cb03e
more info and howto/when use this script please look at the docu file
6cb03e
$README_RPM_DIST.  The 'postgresql'
6cb03e
string is used when no SERVICE_NAME is explicitly passed.
6cb03e
6cb03e
Available operation mode:
6cb03e
  initdb        Create a new PostgreSQL database cluster.  This is usually the
6cb03e
                first action you perform after PostgreSQL server installation.
6cb03e
  upgrade       Upgrade PostgreSQL database cluster to be usable with new
6cb03e
                server.  Use this if you upgraded your PostgreSQL server to
6cb03e
                newer major version (currently from $PREVMAJORVERSION \
6cb03e
to $PGMAJORVERSION).
6cb03e
6cb03e
Environment:
6cb03e
  PGSETUP_INITDB_OPTIONS     Options carried by this variable are passed to
6cb03e
                             subsequent call of \`initdb\` binary (see man
6cb03e
                             initdb(1)).  This variable is used also during
6cb03e
                             'upgrade' mode because the new cluster is actually
6cb03e
                             re-initialized from the old one.
6cb03e
  PGSETUP_PGUPGRADE_OPTIONS  Options in this variable are passed next to the
6cb03e
                             subsequent call of \`pg_upgrade\`.  For more info
6cb03e
                             about possible options please look at man
6cb03e
                             pg_upgrade(1).
6cb03e
  PGSETUP_DEBUG              Set to '1' if you want to see debugging output."
6cb03e
6cb03e
# note that these options are useful at least for help2man processing
6cb03e
case "$1" in
6cb03e
    --version)
6cb03e
        echo "postgresql-setup $PGVERSION"
6cb03e
        exit 0
6cb03e
        ;;
6cb03e
    --help|--usage)
6cb03e
        echo "$USAGE_STRING"
6cb03e
        exit 0
6cb03e
        ;;
6cb03e
esac
6cb03e
6cb03e
# this parsing technique fails for PGDATA pathnames containing spaces,
6cb03e
# but there's not much I can do about it given systemctl's output format...
6cb03e
PGDATA=`systemctl show -p Environment "${SERVICE_NAME}.service" |
6cb03e
                sed 's/^Environment=//' | tr ' ' '\n' |
6cb03e
                sed -n 's/^PGDATA=//p' | tail -n 1`
6cb03e
if [ x"$PGDATA" = x ]; then
6cb03e
    echo "failed to find PGDATA setting in ${SERVICE_NAME}.service"
6cb03e
    exit 1
6cb03e
fi
6cb03e
6cb03e
PGPORT=`systemctl show -p Environment "${SERVICE_NAME}.service" |
6cb03e
                sed 's/^Environment=//' | tr ' ' '\n' |
6cb03e
                sed -n 's/^PGPORT=//p' | tail -n 1`
6cb03e
if [ x"$PGPORT" = x ]; then
6cb03e
    echo "failed to find PGPORT setting in ${SERVICE_NAME}.service"
6cb03e
    exit 1
6cb03e
fi
6cb03e
6cb03e
# Log file for initdb
6cb03e
PGLOG=/var/lib/pgsql/initdb.log
6cb03e
6cb03e
# Log file for pg_upgrade
6cb03e
PGUPLOG=/var/lib/pgsql/pgupgrade.log
6cb03e
6cb03e
export PGDATA
6cb03e
export PGPORT
6cb03e
6cb03e
script_result=0
6cb03e
6cb03e
test -w /var/lib/pgsql || {
6cb03e
    echo >&2 $"The /var/lib/pgsql directory has wrong permissions."
6cb03e
    echo >&2 $"Please make sure the directory is writable by postgres."
6cb03e
    exit 1
6cb03e
}
6cb03e
6cb03e
# code shared between initdb and upgrade actions
6cb03e
perform_initdb(){
6cb03e
    if [ ! -e "$PGDATA" ]; then
6cb03e
        mkdir "$PGDATA" || return 1
6cb03e
    fi
6cb03e
    $RESTORECON "$PGDATA"
6cb03e
    test -w "$PGDATA" || die "$PGDATA is not writeable by $USER"
6cb03e
6cb03e
    # Create the initdb log file if needed
6cb03e
    if [ ! -e "$PGLOG" ]; then
6cb03e
        touch "$PGLOG" || return 1
6cb03e
    fi
6cb03e
    $RESTORECON "$PGLOG"
6cb03e
    test -w "$PGLOG" || echo "$PGLOG is not writeable by $USER"
6cb03e
6cb03e
    # Initialize the database
6cb03e
    initdbcmd=(
6cb03e
        "$PGENGINE/initdb" --pgdata="$PGDATA"
6cb03e
                           --auth=ident
6cb03e
    )
6cb03e
    eval "initdbcmd+=( $PGSETUP_INITDB_OPTIONS )"
6cb03e
6cb03e
    "${initdbcmd[@]}" >> "$PGLOG" 2>&1 < /dev/null
6cb03e
6cb03e
    mkdir "$PGDATA/pg_log"
6cb03e
    $RESTORECON "$PGDATA/pg_log"
6cb03e
6cb03e
    if [ -f "$PGDATA/PG_VERSION" ]; then
6cb03e
        return 0
6cb03e
    fi
6cb03e
    return 1
6cb03e
}
6cb03e
6cb03e
initdb(){
6cb03e
    if [ -f "$PGDATA/PG_VERSION" ]; then
6cb03e
        echo $"Data directory is not empty!"
6cb03e
        echo
6cb03e
        script_result=1
6cb03e
    else
6cb03e
        echo -n $"Initializing database ... "
6cb03e
        if perform_initdb; then
6cb03e
            echo $"OK"
6cb03e
        else
6cb03e
            echo $"failed, see $PGLOG"
6cb03e
            script_result=1
6cb03e
        fi
6cb03e
        echo
6cb03e
    fi
6cb03e
}
6cb03e
6cb03e
upgrade(){
6cb03e
    # must see previous version in PG_VERSION
6cb03e
    if [ ! -f "$PGDATA/PG_VERSION" -o \
6cb03e
         x`cat "$PGDATA/PG_VERSION"` != x"$PREVMAJORVERSION" ]
6cb03e
    then
6cb03e
        echo
6cb03e
        echo $"Cannot upgrade because the database in $PGDATA is not of"
6cb03e
        echo $"compatible previous version $PREVMAJORVERSION."
6cb03e
        echo
6cb03e
        exit 1
6cb03e
    fi
6cb03e
    if [ ! -x "$PGENGINE/pg_upgrade" ]; then
6cb03e
        echo
6cb03e
        echo $"Please install the postgresql-upgrade RPM."
6cb03e
        echo
6cb03e
        exit 5
6cb03e
    fi
6cb03e
6cb03e
    # Set up log file for pg_upgrade
6cb03e
    rm -f "$PGUPLOG"
6cb03e
    touch "$PGUPLOG" || exit 1
6cb03e
    $RESTORECON "$PGUPLOG"
6cb03e
6cb03e
    # Move old DB to PGDATAOLD
6cb03e
    PGDATAOLD="${PGDATA}-old"
6cb03e
    rm -rf "$PGDATAOLD"
6cb03e
    mv "$PGDATA" "$PGDATAOLD" || exit 1
6cb03e
6cb03e
    # Create configuration file for upgrade process
6cb03e
    HBA_CONF_BACKUP="$PGDATAOLD/pg_hba.conf.postgresql-setup.`date +%s`"
6cb03e
    HBA_CONF_BACKUP_EXISTS=0
6cb03e
6cb03e
    if [ ! -f $HBA_CONF_BACKUP ]; then
6cb03e
        mv "$PGDATAOLD/pg_hba.conf" "$HBA_CONF_BACKUP"
6cb03e
        HBA_CONF_BACKUP_EXISTS=1
6cb03e
6cb03e
        # For fluent upgrade 'postgres' user should be able to connect
6cb03e
        # to any database without password.  Temporarily, no other type
6cb03e
        # of connection is needed.
6cb03e
        echo "local all postgres ident" > "$PGDATAOLD/pg_hba.conf"
6cb03e
    fi
6cb03e
6cb03e
    echo -n $"Upgrading database: "
6cb03e
6cb03e
    # Create empty new-format database
6cb03e
    if perform_initdb; then
6cb03e
        eval "add_options=( $PGSETUP_PGUPGRADE_OPTIONS )"
6cb03e
        # Do the upgrade
6cb03e
        ( cd # pg_upgrade writes to $PWD
6cb03e
        "$PGENGINE/pg_upgrade" \
6cb03e
                --old-bindir="$PREVPGENGINE" \
6cb03e
                --new-bindir="$PGENGINE" \
6cb03e
                --old-datadir="$PGDATAOLD" \
6cb03e
                --new-datadir="$PGDATA" \
6cb03e
                --link \
6cb03e
                --old-port="$PGPORT" \
6cb03e
                --new-port="$PGPORT" \
6cb03e
                --user=postgres \
6cb03e
                "${add_options[@]}" \
6cb03e
        >> "$PGUPLOG" 2>&1 < /dev/null
6cb03e
        )
6cb03e
6cb03e
        if [ $? -ne 0 ]; then
6cb03e
            # pg_upgrade failed
6cb03e
            script_result=1
6cb03e
        fi
6cb03e
    else
6cb03e
        # initdb failed
6cb03e
        script_result=1
6cb03e
    fi
6cb03e
6cb03e
    # Move back the backed-up pg_hba.conf regardless of the script_result.
6cb03e
    if [ x$HBA_CONF_BACKUP_EXISTS = x1 ]; then
6cb03e
        mv -f "$HBA_CONF_BACKUP" "$PGDATAOLD/pg_hba.conf"
6cb03e
    fi
6cb03e
6cb03e
    if [ $script_result -eq 0 ]; then
6cb03e
        echo $"OK"
6cb03e
        echo
6cb03e
        echo $"The configuration files were replaced by default configuration."
6cb03e
        echo $"The previous configuration and data are stored in folder"
6cb03e
        echo $PGDATAOLD.
6cb03e
    else
6cb03e
        # Clean up after failure
6cb03e
        rm -rf "$PGDATA"
6cb03e
        mv "$PGDATAOLD" "$PGDATA"
6cb03e
        echo $"failed"
6cb03e
    fi
6cb03e
    echo
6cb03e
    echo $"See $PGUPLOG for details."
6cb03e
}
6cb03e
6cb03e
# See how we were called.
6cb03e
case "$1" in
6cb03e
    initdb)
6cb03e
        initdb
6cb03e
        ;;
6cb03e
    upgrade)
6cb03e
        upgrade
6cb03e
        ;;
6cb03e
    *)
6cb03e
        echo >&2 "$USAGE_STRING"
6cb03e
        exit 2
6cb03e
esac
6cb03e
6cb03e
exit $script_result