#!/bin/sh # # postgresql-setup Initialization and upgrade operations for PostgreSQL # # Installed as /usr/pgsql-x.y/bin/postgresqlxy-setup # # PGVERSION is the full package version, e.g., 9.4.0 # Note: the specfile inserts the correct value during package build PGVERSION=__RPM_PGVERSION__ # PGMAJORVERSION is major version, e.g., 9.4 (this should match PG_VERSION) PGMAJORVERSION=__RPM_PGMAJORVERSION__ # PGENGINE is the directory containing the postmaster executable # Note: the specfile inserts the correct value during package build PGENGINE=__RPM_PGENGINE__ # PREVMAJORVERSION is the previous major version, e.g., 9.1; it's the default # target for pg_upgrade if not overridden. PREVMAJORVERSION=__RPM_PREVMAJORVERSION__ # systemd unit name PGUNITNAME=__RPM_UNITNAME__ # Package name; used in help messages PGPACKAGENAME=__RPM_PACKAGENAME__ # The second parameter is the new database version, i.e. $PGMAJORVERSION in this case. # Use the unit name from the rpm build, if not specified. SERVICE_NAME="${2:-$PGUNITNAME}" # The third parameter is the old database service control file name sans any # .service suffix, e.g postgresql-9.3 in this case. Use # "postgresql-$PREVMAJORVERSION" service, if not specified. OLD_SERVICE_NAME="${3:-postgresql-$PREVMAJORVERSION}" # Was this RPM built with systemd or sysvinit? USING_SYSTEMD=__RPM_SYSTEMD__ # Find the unit file for new version. if [ -f "/etc/systemd/system/${SERVICE_NAME}.service" ] then SERVICE_FILE="/etc/systemd/system/${SERVICE_NAME}.service" elif [ -f "/lib/systemd/system/${SERVICE_NAME}.service" ] then SERVICE_FILE="/lib/systemd/system/${SERVICE_NAME}.service" else echo "Could not find systemd unit file ${SERVICE_NAME}.service" exit 1 fi # Get port number and data directory from the service file PGPORT=$(gawk -F '=' '/^Environment=PGPORT=/ { print $3}' "${SERVICE_FILE}") PGDATA=$(gawk -F '=' '/^Environment=PGDATA=/ { print $3}' "${SERVICE_FILE}") PGSERVERUSER=$(awk -F '=' '/^User=/ { print $2}' "${SERVICE_FILE}") PGSERVERGROUP=$(awk -F '=' '/^Group=/ { print $2}' "${SERVICE_FILE}") # Log files for initdb and pg_upgrade are placed in the parent dir of the # datadir. On a default install that's /var/lib/pgsql/$MAJORVERSION . PGINITDBLOG="$(dirname $PGDATA)/initdb.log" export PGPORT export PGDATA # For SELinux we need to use 'runuser' not 'su' if [ -x /sbin/runuser ] then SU=runuser else SU=su fi script_result=0 # code shared between initdb and upgrade actions perform_initdb(){ if [ ! -e "$PGDATA" -a ! -h "$PGDATA" ] then mkdir -p "$PGDATA" || return 1 chown $PGSERVERUSER:$PGSERVERGROUP "$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 "$PGINITDBLOG" -a ! -h "$PGINITDBLOG" ] then touch "$PGINITDBLOG" || return 1 chown $PGSERVERUSER:$PGSERVERGROUP "$PGINITDBLOG" chmod go-rwx "$PGINITDBLOG" [ -x /sbin/restorecon ] && /sbin/restorecon "$PGINITDBLOG" fi # Initialize the database $SU -l postgres -c "$PGENGINE/initdb --pgdata='$PGDATA' --auth='ident'" >> "$PGINITDBLOG" 2>&1 < /dev/null # Create directory for postmaster log files mkdir "$PGDATA/pg_log" chown $PGSERVERUSER:$PGSERVERGROUP "$PGDATA/pg_log" chmod go-rwx "$PGDATA/pg_log" if [ -f "$PGDATA/PG_VERSION" ] then return 0 fi echo 1>&2 "ERROR: $PGDATA/PG_VERSION not found after initdb; check logs for details." return 1 } initdb(){ if [ -f "$PGDATA/PG_VERSION" ] then echo $"Data directory is not empty!" echo script_result=1 else echo -n $"Initializing database ... " if perform_initdb then echo $"OK" else echo $"failed, see $PGINITDBLOG" script_result=1 fi echo fi } upgrade(){ PGUPLOG="$(dirname $PGDATA)/pgupgrade.log" ## Absorb configuration settings from the specified systemd service files. # Figure out what version we're upgrading from using the control file name # if we can. OLDMAJORVERSION=$(echo "$OLD_SERVICE_NAME" | gawk 'match($0, "postgresql-([0-9]+)\\.([0-9]+)\\.service", matches) { printf "%d.%d",matches[1],matches[2]; }' ) if [ -z "$OLDMAJORVERSION" ]; then echo 2>&1 "Failed to determine major version from service file name $OLD_SERVICE_NAME" echo 2>&1 "You will need to run pg_upgrade manually instead." exit 1 fi # Find the old Pg version's control file if [ -f "/etc/systemd/system/${OLD_SERVICE_NAME}.service" ] then OLD_SERVICE_FILE="/etc/systemd/system/${OLD_SERVICE_NAME}.service" elif [ -f "/lib/systemd/system/${OLD_SERVICE_NAME}.service" ] then OLD_SERVICE_FILE="/lib/systemd/system/${OLD_SERVICE_NAME}.service" else echo "Could not find systemd unit file ${OLD_SERVICE_NAME}.service" exit 1 fi ## Get port number and data directory from the service file NEWPGPORT=$PGPORT NEWPGDATA=$PGDATA ## Get port number and data directory for old serverfrom the service file OLDPGPORT=$(gawk -F '=' '/^Environment=PGPORT=/ { print $3}' "${OLD_SERVICE_FILE}") OLDPGDATA=$(gawk -F '=' '/^Environment=PGDATA=/ { print $3}' "${OLD_SERVICE_FILE}") # OLDPGENGINE is the directory containing the previous postmaster executable # We can determine it reliably by examining the binary paths in the control file OLDPGENGINE=$(dirname $(awk -F '[= ]' '/^ExecStart=/ { print $2}' "${OLD_SERVICE_FILE}" ) ) # must see previous version in PG_VERSION if [ ! -f "$OLDPGDATA/PG_VERSION" -o x`cat "$OLDPGDATA/PG_VERSION"` != x"$OLDMAJORVERSION" ] then echo echo $"Cannot upgrade because database in $OLDPGDATA is missing or not of expected version $OLDMAJORVERSION." echo exit 1 fi if [ ! -x "$PGENGINE/pg_upgrade" ] then echo echo $"pg_upgrade not found for $PGMAJORVERSION. Please install the ${PGPACKAGENAME}-contrib RPM." echo exit 5 fi # Perform initdb on the new server $PGENGINE/postgresql${PGMAJORVERSION/.}-setup initdb RETVAL=$? if [ $RETVAL -ne 0 ] then echo "Failed to initdb new datadir for $PGMAJORVERSION; see $PGINITDBLOG for details" exit 1 fi # Check the clusters first, without changing any data: $RUNUSER -l postgres -c "$PGENGINE/pg_upgrade -b $OLDPGENGINE -B $PGENGINE/ -d $OLDPGDATA -D $NEWPGDATA -p $OLDPGPORT -P $NEWPGPORT -c" RETVAL=$? if [ $RETVAL -eq 0 ] then echo "Clusters checked successfully, proceeding with upgrade from $OLDMAJORVERSION to $PGMAJORVERSION" echo "Stopping old cluster" if [ "$USING_SYSTEMD" = 1 ] then /bin/systemctl stop $OLD_SERVICE_NAME.service else service $OLD_SERVICE_NAME stop fi # Set up log file for pg_upgrade rm -f "$PGUPLOG" touch "$PGUPLOG" || exit 1 chown $PGSERVERUSER:$PGSERVERGROUP "$PGUPLOG" chmod go-rwx "$PGUPLOG" [ -x /sbin/restorecon ] && /sbin/restorecon "$PGUPLOG" echo "Performing upgrade" $RUNUSER -l postgres -c "$PGENGINE/pg_upgrade \ -b $OLDPGENGINE -B $PGENGINE/ \ -d $OLDPGDATA -D $NEWPGDATA -p $OLDPGPORT -P $NEWPGPORT" >> "$PGUPLOG" 2>&1 < /dev/null else echo "Cluster check failed. Please see the output above." exit 1 fi echo exit 0 } # See how we were called. case "$1" in initdb) initdb ;; upgrade) upgrade ;; *) echo $"Usage: $0 {initdb|upgrade} [ service_name ]" exit 2 esac exit $script_result