6026c0
#!/bin/bash
27aa74
#
6026c0
# postgresql-setup - Initialization and upgrade operations for PostgreSQL
6026c0
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
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
# For SELinux we need to use 'runuser' not 'su'
6026c0
if [ -x /sbin/runuser ]; then
27aa74
    SU=runuser
27aa74
else
27aa74
    SU=su
27aa74
fi
27aa74
27aa74
script_result=0
27aa74
27aa74
# code shared between initdb and upgrade actions
27aa74
perform_initdb(){
6026c0
    if [ ! -e "$PGDATA" ]; then
6026c0
        mkdir "$PGDATA" || return 1
6026c0
        chown postgres:postgres "$PGDATA"
6026c0
        chmod go-rwx "$PGDATA"
6026c0
    fi
6026c0
    # Clean up SELinux tagging for PGDATA
6026c0
    [ -x /sbin/restorecon ] && /sbin/restorecon "$PGDATA"
6026c0
6026c0
    # Create the initdb log file if needed
6026c0
    if [ ! -e "$PGLOG" -a ! -h "$PGLOG" ]; then
6026c0
        touch "$PGLOG" || return 1
6026c0
        chown postgres:postgres "$PGLOG"
6026c0
        chmod go-rwx "$PGLOG"
6026c0
        [ -x /sbin/restorecon ] && /sbin/restorecon "$PGLOG"
6026c0
    fi
6026c0
6026c0
    # Initialize the database
6026c0
    initdbcmd="$PGENGINE/initdb --pgdata='$PGDATA' --auth='ident'"
6026c0
    initdbcmd+=" $PGSETUP_INITDB_OPTIONS"
6026c0
6026c0
    $SU -l postgres -c "$initdbcmd" >> "$PGLOG" 2>&1 < /dev/null
6026c0
6026c0
    # Create directory for postmaster log files
6026c0
    mkdir "$PGDATA/pg_log"
6026c0
    chown postgres:postgres "$PGDATA/pg_log"
6026c0
    chmod go-rwx "$PGDATA/pg_log"
6026c0
    [ -x /sbin/restorecon ] && /sbin/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
27aa74
    chown postgres:postgres "$PGUPLOG"
27aa74
    chmod go-rwx "$PGUPLOG"
27aa74
    [ -x /sbin/restorecon ] && /sbin/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
6026c0
        # Do the upgrade
6026c0
        $SU -l postgres -c "$PGENGINE/pg_upgrade \
6026c0
                        '--old-bindir=$PREVPGENGINE' \
6026c0
                        '--new-bindir=$PGENGINE' \
6026c0
                        '--old-datadir=$PGDATAOLD' \
6026c0
                        '--new-datadir=$PGDATA' \
6026c0
                        --link \
6026c0
                        '--old-port=$PGPORT' '--new-port=$PGPORT' \
6026c0
                        --user=postgres \
6026c0
                        $PGSETUP_PGUPGRADE_OPTIONS" \
6026c0
                                >> "$PGUPLOG" 2>&1 < /dev/null
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