246 lines
7.9 KiB
Bash
246 lines
7.9 KiB
Bash
#!/bin/bash
|
|
|
|
# This script performs the PostgreSQL upgrade. This script should only be
|
|
# called by upgrade_postgresql_database.sh and not by itself. If the upgrade
|
|
# fails, you may rerun the script and it will start from the beginning.
|
|
#
|
|
# Do not Ctrl+C or otherwise interrupt the script while it is running as this
|
|
# may prevent proper cleanup.
|
|
#
|
|
# Author: tgurney
|
|
|
|
# $1 is the directory containing this script
|
|
here="$1"
|
|
source "$here/settings.sh" || exit 1
|
|
|
|
# directory for temporarily keeping config files from the data dir
|
|
temp_config_dir=$(mktemp -d) || exit 1
|
|
|
|
export LD_LIBRARY_PATH="${postgres_lib}:${psql_dir}/lib:$LD_LIBRARY_PATH"
|
|
|
|
|
|
# roll back as much as possible in the event of an error
|
|
cleanup_exit() {
|
|
echo "INFO: Cleaning up"
|
|
# remove symlinked psql
|
|
if [[ -h "${postgres_dir}/bin/psql" ]]; then
|
|
rm -vf "${postgres_dir}/bin/psql"
|
|
fi
|
|
# put back any tablespaces that had been moved
|
|
for ts_dir in "${tablespaces[@]}"; do
|
|
if [[ -d "${temp_new_data}/${ts_dir}" && ! -e "${postgres_data_dir}/${ts_dir}" ]]; then
|
|
mv -fv "${temp_new_data}/${ts_dir}" "${postgres_data_dir}/${ts_dir}"
|
|
fi
|
|
done
|
|
# restore original pg_hba.conf
|
|
if [[ -f "${temp_config_dir}/pg_hba.conf" ]]; then
|
|
cp -fv "${temp_config_dir}/pg_hba.conf" "${postgres_data_dir}/pg_hba.conf"
|
|
fi
|
|
# clean up temp directories
|
|
rm -rf "${temp_config_dir}"
|
|
rm -rf "${temp_old_data}"
|
|
rm -rf "${temp_new_data}"
|
|
sync
|
|
echo -e "\nERROR: !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
|
|
echo "ERROR: !! UPGRADE FAILED !!"
|
|
echo "ERROR: !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
|
|
echo -e "\nERROR: One or more errors occurred. See above output."
|
|
echo -en "\nAny changes made by this script have been rolled back. You "
|
|
echo -en "may run this script again once any issues have been resolved.\n"
|
|
exit 1
|
|
}
|
|
|
|
|
|
if [[ ! -d "${postgres_data_dir}" ]]; then
|
|
echo "ERROR: Specified PostgreSQL data dir ${postgres_data_dir} does not exist."
|
|
echo "ERROR: Cannot continue."
|
|
cleanup_exit
|
|
fi
|
|
|
|
if [[ -d "${postgres_copy_of_old}_done" ]]; then
|
|
echo "INFO: PostgreSQL upgrade has already been completed."
|
|
exit 0
|
|
fi
|
|
|
|
if [[ ! -d "${postgres_copy_of_old}" ]]; then
|
|
echo -n "ERROR: Did not find the old version of PostgreSQL at "
|
|
echo "${postgres_copy_of_old}. Upgrade might already be complete."
|
|
echo "ERROR: Cannot continue."
|
|
cleanup_exit
|
|
fi
|
|
|
|
if [[ "${postgres_version}" != "${new_ver}" ]]; then
|
|
echo -n "ERROR: Currently installed version of PostgreSQL is "
|
|
echo "${postgres_version}. Expected ${new_ver}. Cannot continue."
|
|
cleanup_exit
|
|
fi
|
|
|
|
if [[ "${psql_version}" != "${new_ver}" ]]; then
|
|
echo -n "ERROR: Currently installed version of psql is "
|
|
echo "${psql_version}. Expected ${new_ver}. Cannot continue."
|
|
cleanup_exit
|
|
fi
|
|
|
|
${postgres_dir}/bin/pg_ctl -D "${postgres_data_dir}" status
|
|
if [[ "$?" -eq 0 ]]; then
|
|
echo "ERROR: It looks like PostgreSQL is running. Cannot continue."
|
|
cleanup_exit
|
|
fi
|
|
|
|
# This doesn't appear to work consistently, so we cannot guarantee proper
|
|
# cleanup on Ctrl+C or other interruption.
|
|
trap cleanup_exit SIGINT SIGTERM
|
|
|
|
# Identify any tablespaces that need to be moved after running pg_upgrade
|
|
tablespaces=()
|
|
for ts_link in "${pg_tblspc}"/* ; do
|
|
this_ts=$(readlink "${ts_link}")
|
|
if [[ "${this_ts}" == "${postgres_data_dir}"* ]]; then
|
|
echo "INFO: ${this_ts} is inside the data dir. It will be moved temporarily"
|
|
tablespaces+=("$(basename ${this_ts})")
|
|
fi
|
|
done
|
|
|
|
|
|
echo -e "\nINFO: Backing up config files"
|
|
for conf in "${config_files[@]}"; do
|
|
if [[ -f "${postgres_data_dir}/${conf}" ]]; then
|
|
cp -v "${postgres_data_dir}/${conf}" "${temp_config_dir}/${conf}" || cleanup_exit
|
|
else
|
|
echo "INFO: $conf does not exist, skipping this one"
|
|
fi
|
|
done
|
|
echo "INFO: Done backing up config files"
|
|
|
|
|
|
echo -e "\nINFO: Initializing new cluster at ${temp_new_data}"
|
|
rm -rf "${temp_new_data}"
|
|
"${initdb}" -D "${temp_new_data}" || cleanup_exit
|
|
|
|
|
|
echo -e "\nINFO: Starting new cluster on port ${temp_port}"
|
|
"${postgres_dir}/bin/postgres" --port="${temp_port}" -D "${temp_new_data}" 2>&1 &
|
|
echo "INFO: Waiting 10 seconds for cluster to start"
|
|
sleep 10 || cleanup_exit
|
|
"${psql}" --port="${temp_port}" --db=postgres -c 'select 1 test;'
|
|
if [[ "$?" != "0" ]]; then
|
|
echo "ERROR: Test query failed"
|
|
cleanup_exit
|
|
fi
|
|
|
|
if [[ -n "${is_openfire}" ]]; then
|
|
echo -e "\nINFO: Setting up awips db user"
|
|
"${psql}" --port="${temp_port}" --db=postgres << EOF
|
|
begin;
|
|
alter role awips with password 'awips';
|
|
commit;
|
|
EOF
|
|
else
|
|
echo -e "\nINFO: Setting up $db_admin_user db user"
|
|
"${psql}" --port="${temp_port}" --db=postgres -c \
|
|
'create role awipstmp with login superuser createdb createrole;'
|
|
"${psql}" --port="${temp_port}" --db=postgres --user=awipstmp << EOF
|
|
begin;
|
|
alter role awips rename to $db_admin_user;
|
|
alter role awipstmp with nologin;
|
|
commit;
|
|
EOF
|
|
"${psql}" --port="${temp_port}" --db=postgres --user=$db_admin_user << EOF
|
|
begin;
|
|
alter role $db_admin_user with password 'awips';
|
|
drop role awipstmp;
|
|
commit;
|
|
EOF
|
|
fi
|
|
|
|
|
|
echo -e "\nINFO: Stopping new cluster"
|
|
"${postgres_dir}/bin/pg_ctl" -D "${temp_new_data}" stop
|
|
sleep 3 || cleanup_exit
|
|
|
|
|
|
# prevent pg_upgrade from prompting for a password for the old cluster
|
|
echo -e "\nINFO: Updating old pg_hba.conf to trust local connections"
|
|
grep -E "local\s+all\s+all\s+trust" "${postgres_data_dir}/pg_hba.conf" >/dev/null
|
|
if [[ "$?" -ne 0 ]]; then
|
|
echo -e "local\tall\tall\ttrust" >> "${postgres_data_dir}/pg_hba.conf" || cleanup_exit
|
|
fi
|
|
|
|
# Need to symlink psql,
|
|
# because pg_upgrade expects $postgres_dir/bin/psql to exist
|
|
echo -e "\nINFO: Creating link to ${psql} at ${postgres_dir}/bin/psql"
|
|
if [[ ! -x "${postgres_dir}/bin/psql" ]]; then
|
|
ln -fvs "${psql}" "${postgres_dir}/bin/psql" || cleanup_exit
|
|
fi
|
|
|
|
echo -e "\nINFO: Starting upgrade"
|
|
|
|
# Run pg_upgrade twice, first time is a read-only compatibility check.
|
|
for check in yes no; do
|
|
if [[ "${check}" == "yes" ]]; then
|
|
check="--check"
|
|
else
|
|
check=""
|
|
fi
|
|
LD_LIBRARY_PATH="$LD_LIBRARY_PATH:${postgres_copy_of_old}/lib" \
|
|
"${pg_upgrade}" ${check} --jobs=4 --link \
|
|
--old-port="${temp_port}" \
|
|
--new-port="${temp_port}" \
|
|
--old-bindir="${postgres_copy_of_old}/bin" \
|
|
--new-bindir="${postgres_dir}/bin" \
|
|
--old-datadir="${postgres_data_dir}" \
|
|
--new-datadir="${temp_new_data}" \
|
|
--username="${db_admin_user}" \
|
|
|| cleanup_exit
|
|
done
|
|
|
|
# Point of no return, no cleanup/rollback is possible.
|
|
trap - SIGINT SIGTERM
|
|
|
|
# These scripts are created by pg_upgrade but are not needed.
|
|
# We provide our own script (rebuild_stats_and_hash_indexes.sh) instead.
|
|
rm -f analyze_new_cluster.sh
|
|
rm -f reindex_hash.sql
|
|
|
|
echo -e "\nINFO: Copying config files to new data directory"
|
|
for conf in "${config_files[@]}"; do
|
|
if [[ -f "${temp_config_dir}/${conf}" ]]; then
|
|
cp -v "${temp_config_dir}/${conf}" "${temp_new_data}/${conf}"
|
|
fi
|
|
done
|
|
|
|
|
|
echo -e "\nINFO: Moving tablespaces"
|
|
for ts_dir in "${tablespaces[@]}"; do
|
|
mv -v "${postgres_data_dir}/${ts_dir}" "${temp_new_data}"
|
|
done
|
|
echo "INFO: Done moving tablespaces"
|
|
|
|
|
|
echo -e "\nINFO: Moving new data dir to ${postgres_data_dir}"
|
|
rm -rf "${temp_old_data}"
|
|
mkdir "${temp_old_data}"
|
|
mv "${postgres_data_dir}"/* "${temp_old_data}"
|
|
mv "${temp_new_data}"/* "${postgres_data_dir}"
|
|
|
|
|
|
echo -e "\nINFO: Deleting temp directories"
|
|
rm -rf "${temp_old_data}"
|
|
rm -rf "${temp_new_data}"
|
|
rm -rf "${temp_config_dir}"
|
|
|
|
echo -e "\nINFO: Removing symlinked psql"
|
|
if [[ -h "${postgres_dir}/bin/psql" ]]; then
|
|
rm -f "${postgres_dir}/bin/psql"
|
|
fi
|
|
|
|
echo -e "\nINFO: Syncing disks"
|
|
sync
|
|
|
|
echo -e "\nINFO: Moving old PostgreSQL install to ${postgres_copy_of_old}_done"
|
|
mv "${postgres_copy_of_old}" "${postgres_copy_of_old}_done"
|
|
|
|
echo -e "\nINFO: ****************************************"
|
|
echo "INFO: ** UPGRADE COMPLETE **"
|
|
echo "INFO: ****************************************"
|
|
|