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