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