mirror of
https://abf.rosa.ru/djam/postgrespro-1c.git
synced 2025-02-23 21:42:47 +00:00
482 lines
12 KiB
Bash
482 lines
12 KiB
Bash
#!/bin/sh
|
|
#
|
|
# postgrespro-setup Initialization and control operations for Postgres Pro
|
|
#
|
|
|
|
PG_SETUP_VERSION=13.2.1
|
|
BINDIR=@BINDIR@
|
|
SERVICE=@PROGNAME@-@EDITION@-@VERSION@
|
|
PGENGINE=$BINDIR
|
|
|
|
OU_STRING=""
|
|
if [ "ent" = "@EDITION@" ] && [ "@VERSION@" -ge 13 ]; then
|
|
OU_STRING=" [--enable-online-upgrade]"
|
|
fi
|
|
|
|
USAGE_STRING="Usage: $0 initdb [<initdb-options>]
|
|
or: $0 find-free-port
|
|
or: $0 set-server-port <port>
|
|
or: $0 service (enable|disable)
|
|
or: $0 service (start|stop|condrestart|status)
|
|
or: $0 set GUC-variable value
|
|
or: $0 psql [<psql options>]
|
|
|
|
Script is aimed to help sysadmin with basic database cluster administration.
|
|
|
|
Available operation mode:
|
|
initdb [--tune=conf]${OU_STRING} [<initdb-options>] Create a new Postgres Pro database cluster.
|
|
find-free-port Search of free server TCP-port number, start with 5432.
|
|
set-server-port <port> Set server port number.
|
|
service enable Enable service.
|
|
service disable Disable service.
|
|
service status Service status.
|
|
service start Start service.
|
|
service stop Stop service.
|
|
service condrestart Conditional restart of service.
|
|
|
|
pg-setup psql allows to start SQL shell correctly switching from root
|
|
to postgres user and use port set by pg-setup set-server-port.
|
|
"
|
|
|
|
# note that these options are useful at least for help2man processing
|
|
case "$1" in
|
|
--version)
|
|
echo "pg-setup $PG_SETUP_VERSION"
|
|
exit 0
|
|
;;
|
|
--help|--usage)
|
|
echo "$USAGE_STRING"
|
|
exit 0
|
|
;;
|
|
"")
|
|
echo "$USAGE_STRING"
|
|
exit 1
|
|
;;
|
|
esac
|
|
|
|
if [ "$(id -u)" -ne 0 ]; then
|
|
echo "$0 must be started as root" >&2
|
|
exit 1
|
|
fi
|
|
|
|
PGDATA=/var/lib/pgpro/@EDITION@-@VERSION@/data
|
|
DEFCONFIG=/etc/default/postgrespro-@EDITION@-@VERSION@
|
|
# shellcheck disable=SC1090
|
|
[ -f $DEFCONFIG ] && . $DEFCONFIG
|
|
export PGDATA
|
|
# make safe PATH
|
|
PATH=/sbin:/bin:/usr/sbin:/usr/bin:@BINDIR@
|
|
export PATH
|
|
|
|
# For SELinux we need to use 'runuser' not 'su'
|
|
if [ -x /sbin/runuser ]
|
|
then
|
|
SU=/sbin/runuser
|
|
else
|
|
SU=su
|
|
fi
|
|
|
|
#
|
|
# This function sets confguration value in the postgresql.conf to given
|
|
# string. If value should contain quotes, they should be passed as part
|
|
# of string
|
|
# i.e. set_conf_value log_destination "'stderr'"
|
|
# Keeps end of line comments if it can.
|
|
# Removes corresponding paramters from postgresql.auto.conf if any
|
|
# FIXME - this function is unable to handle arbitrary includes,
|
|
# but possibly would do a right thing, because if directive is in the
|
|
# include, it would not find it in the main configuration file
|
|
# and append new value to the end of it after all includes.
|
|
|
|
set_conf_value() {
|
|
param="$1"
|
|
value="$2"
|
|
config="$PGDATA/postgresql.conf"
|
|
if [ ! -f "$config" ]; then
|
|
echo "Cannot find configuration file for $PGDATA!" >&2
|
|
return 1
|
|
fi
|
|
|
|
# Check if there is (possibly commented out) parameter in the config
|
|
if grep -q "^#\\?${param}[ ]*=" "$config"; then
|
|
# Found one edit
|
|
sed -i "s/^#\\?${param}[ ]*=[ ]*[^#]*\\(#.*\\)\\?/$param = $value \\1/" \
|
|
"$config"
|
|
else
|
|
# Not found, just append
|
|
echo "$param = $value" >> "$config"
|
|
fi
|
|
# Check postgresql.auto.conf
|
|
if [ -f "$PGDATA/postgresql.auto.conf" ] && grep -q "^${param}[ ]*=" "$PGDATA/postgresql.auto.conf"; then
|
|
#Really we could call sed without previous check, but
|
|
#I want to keep file timestamp if there is nothing to change
|
|
sed -i "/^${param}[ ]*=/d" "$PGDATA/postgresql.auto.conf";
|
|
fi
|
|
}
|
|
|
|
#
|
|
# This function checks whether environment variable needs shell
|
|
# quoting. Pass there unquited variable and function will return
|
|
# 0 if it got more than one argument and 1 if just one
|
|
need_quotes() {
|
|
[ "$#" -gt 1 ]
|
|
}
|
|
#
|
|
# This function checks whether existing directory does contain any files
|
|
# and subdirectories
|
|
#
|
|
dir_is_not_empty() {
|
|
[ "$(ls -A "$1")" ]
|
|
}
|
|
|
|
initdb(){
|
|
INITDB_OPTIONS=""
|
|
datadir=""
|
|
TUNE=@EDITION@
|
|
ENABLE_ONLINE_UPGRADE=0
|
|
for opt in "$@"; do
|
|
if [ -n "$consume_next" ]; then
|
|
datadir="$opt"
|
|
consume_next=""
|
|
continue
|
|
fi
|
|
case "$opt" in
|
|
-D|--pgdata)
|
|
if [ -n "$datadir" ]; then
|
|
echo "Duplicate option $opt" 1>&2
|
|
return 1
|
|
fi
|
|
consume_next=1
|
|
;;
|
|
--pgdata=*)
|
|
if [ -n "$datadir" ]; then
|
|
echo "Duplicate option --pgdata" 1>&2
|
|
return 1
|
|
fi
|
|
datadir=$(echo "$opt"|sed 's/^[^=]*=//')
|
|
;;
|
|
--auth-local=*)
|
|
if [ -n "$local_auth" ]; then
|
|
echo "Duplicate option --auth-local" 1>&2
|
|
return 1
|
|
fi
|
|
local_auth=$opt
|
|
;;
|
|
--auth-host=*)
|
|
if [ -n "$host_auth" ]; then
|
|
echo "Duplicate option --auth-host" 1>&2
|
|
return 1
|
|
fi
|
|
host_auth=$opt
|
|
;;
|
|
--tune|--auth-local|-auth-host)
|
|
echo "Please use syntax $opt=value" >&2;
|
|
return 1
|
|
;;
|
|
--tune=*)
|
|
TUNE=${opt#*=}
|
|
;;
|
|
--enable-online-upgrade)
|
|
ENABLE_ONLINE_UPGRADE=1
|
|
;;
|
|
*)
|
|
INITDB_OPTIONS="$INITDB_OPTIONS \"$opt\""
|
|
;;
|
|
esac
|
|
done
|
|
if [ -n "$datadir" ]; then
|
|
# shellcheck disable=SC2166
|
|
if [ "$datadir" != "$PGDATA" -a -f ${DEFCONFIG} ]; then
|
|
echo "${DEFCONFIG} already exists " >&2
|
|
echo "And sets up database location $PGDATA." >&2
|
|
echo "If you want to setup second postgres instance in" >&2
|
|
echo "$datadir" >&2
|
|
echo "use @BINDIR@/initdb directly and configure service" >&2
|
|
echo "startup manually." >&2
|
|
return 1
|
|
fi
|
|
PGDATA="$datadir"
|
|
export PGDATA
|
|
fi
|
|
# Check for relative path
|
|
if [ ! -d "$PGDATA" ]; then
|
|
mkdir -p "$PGDATA" || return 1
|
|
elif dir_is_not_empty "$PGDATA" ; then
|
|
echo "Data directory $PGDATA is not empty!" 1>&2
|
|
return 1
|
|
fi
|
|
# convert path to PGDATA to absolute
|
|
PGDATA="$(sh -c "cd '$PGDATA' && pwd -P")"
|
|
|
|
chown postgres:postgres "$PGDATA"
|
|
chmod go-rwx "$PGDATA"
|
|
# We intend word splitting here. This line checks if
|
|
# PGDATA would be splitted
|
|
# shellcheck disable=SC2086
|
|
if need_quotes $PGDATA ; then
|
|
echo "PGDATA=\"$PGDATA\"" > "${DEFCONFIG}"
|
|
else
|
|
echo "PGDATA=$PGDATA" > "${DEFCONFIG}"
|
|
fi
|
|
if [ "$ENABLE_ONLINE_UPGRADE" = "1" ]; then
|
|
echo "ENABLE_ONLINE_UPGRADE=1" >> "${DEFCONFIG}"
|
|
fi
|
|
PGLOG="$(dirname "${PGDATA}")/initdb.$(basename "${PGDATA}").log"
|
|
# Clean up SELinux tagging for PGDATA
|
|
RESTORECON=/sbin/restorecon
|
|
[ -x $RESTORECON ] && $RESTORECON "$PGDATA"
|
|
# Check if locale of this script is suitable for creating database
|
|
# and try to find better one if not
|
|
if [ "$(locale charmap)" = "ANSI_X3.4-1968" ]; then
|
|
# If current locale is 7-bit, try to get locale of
|
|
# invoking user or default locale of user postgres,
|
|
# shellcheck disable=SC2046
|
|
eval $($SU - "${SUDO_USER:-postgres}" -c locale)
|
|
[ -z "$LANG" ] || export LANG
|
|
[ -z "$LC_CTYPE" ] || export LC_CTYPE
|
|
elif [ -z "$LANG" ]&&[ -n "$LC_CTYPE" ]; then
|
|
# If LC_CTYPE set to something usable, but LANG is unset,
|
|
# set it equal to LC_CTYPE, because we need LC_COLLATE as well
|
|
# as LC_CTYPE
|
|
LANG="$LC_CTYPE"
|
|
export LANG
|
|
fi
|
|
# if locale still C or POSIX, use C.UTF-8
|
|
if [ "$(locale charmap)" = "ANSI_X3.4-1968" ]; then
|
|
LANG=C.UTF-8
|
|
[ -z "$LC_CTYPE" ] || LC_CTYPE="$LANG"
|
|
[ -z "$LC_COLLATE" ] || LC_COLLATE="$LANG"
|
|
[ -z "$LC_ALL" ] || LC_ALL="$LANG"
|
|
[ -z "$LC_ALL" ] || export LC_ALL
|
|
fi
|
|
# Create the initdb log file if needed
|
|
# shellcheck disable=SC2166
|
|
if [ -f "$PGLOG" -o ! -e "$PGLOG" ]; then
|
|
if ! : > "$PGLOG" ; then
|
|
echo "Cannot write installation log file $PGLOG" >&2
|
|
rm -rf "${PGDATA}" "${DEFCONFIG}"
|
|
return 1
|
|
fi
|
|
chown postgres:postgres "$PGLOG"
|
|
chmod go-wx "$PGLOG"
|
|
[ -x $RESTORECON ] && $RESTORECON "$PGLOG"
|
|
else
|
|
echo "Log file $PGLOG exist and is not regular file. Cannot continue." >&2
|
|
rm -rf "${PGDATA}" "${DEFCONFIG}"
|
|
return 1
|
|
fi
|
|
|
|
# Initialize the database
|
|
initdbcmd="$PGENGINE/initdb --pgdata='$PGDATA' ${local_auth:---auth-local=peer} ${host_auth:---auth-host=md5} $INITDB_OPTIONS"
|
|
echo "Initalizing database..."
|
|
if $SU -l postgres -c "LANG=$LANG $initdbcmd" >> "$PGLOG" 2>&1 < /dev/null; then
|
|
# Create directory for postmaster log files
|
|
mkdir "$PGDATA/log"
|
|
chown postgres:postgres "$PGDATA/log"
|
|
chmod go-rwx "$PGDATA/log"
|
|
[ -x $RESTORECON ] && $RESTORECON "$PGDATA/log"
|
|
# Tune configuration
|
|
if [ -x "@PREFIX@/share/$TUNE.tune" ]; then
|
|
if ! "@PREFIX@/share/$TUNE.tune" >> "$PGDATA/postgresql.conf"; then
|
|
rm -rf "${PGDATA}" "${DEFCONFIG}"
|
|
return 1
|
|
fi
|
|
if grep -q "^listen_addresses[ ]*=[ ]*'\\*'" "$PGDATA/postgresql.conf"
|
|
then
|
|
echo "host all all 0.0.0.0/0 md5" >> "$PGDATA/pg_hba.conf"
|
|
fi
|
|
fi
|
|
# Fix shared_memory_type for online-upgrade
|
|
if [ "$ENABLE_ONLINE_UPGRADE" = "1" ]; then
|
|
set_conf_value "shared_memory_type" "sysv"
|
|
fi
|
|
# Fix configuration file to enable loging_collector
|
|
if set_conf_value "logging_collector" "on"; then
|
|
echo OK
|
|
return 0
|
|
fi
|
|
fi
|
|
rm -rf "${PGDATA}" "${DEFCONFIG}"
|
|
echo "failed, see $PGLOG" 1>&2
|
|
return 1
|
|
}
|
|
|
|
find_free_port() {
|
|
free_port=5432
|
|
while /usr/bin/timeout 5 /bin/bash -c "cat < /dev/null > /dev/tcp/127.0.0.1/$free_port" 2>/dev/null; do
|
|
# shellcheck disable=SC2003
|
|
free_port=$((free_port + 1))
|
|
done
|
|
echo $free_port
|
|
}
|
|
|
|
set_server_port(){
|
|
port=$1
|
|
if [ -z "$port" ]; then
|
|
echo "Error: port value is empty!" >&2
|
|
return 1
|
|
fi
|
|
# shellcheck disable=SC2003
|
|
if ! /usr/bin/expr "$port" + 0 >/dev/null >&2; then
|
|
echo "Bad port value: $port" 1>&2
|
|
return 1
|
|
fi
|
|
# shellcheck disable=SC2166
|
|
if [ "$port" -lt 1024 -o "$port" -gt 65535 ]; then
|
|
echo "Port value $port is out of range (1024-65535)" 1>&2;
|
|
return 1
|
|
fi
|
|
set_conf_value "port" "$port"
|
|
}
|
|
|
|
enable_service() {
|
|
if [ -n "$SCTL" ]; then
|
|
$SCTL enable $SERVICE
|
|
return $?
|
|
else
|
|
URCD=/usr/sbin/update-rc.d
|
|
if [ -x $URCD ]; then
|
|
$URCD $SERVICE defaults
|
|
else
|
|
/sbin/chkconfig --add $SERVICE
|
|
/sbin/chkconfig --level 35 $SERVICE on
|
|
fi
|
|
return $?
|
|
fi
|
|
}
|
|
|
|
disable_service() {
|
|
if [ -n "$SCTL" ]; then
|
|
$SCTL disable $SERVICE
|
|
return $?
|
|
else
|
|
URCD=/usr/sbin/update-rc.d
|
|
if [ -x $URCD ]; then
|
|
$URCD -f $SERVICE remove
|
|
else
|
|
/sbin/chkconfig --del $SERVICE
|
|
fi
|
|
return $?
|
|
fi
|
|
}
|
|
|
|
start_service() {
|
|
if [ -n "$SCTL" ]; then
|
|
$SCTL is-active --quiet $SERVICE || $SCTL start $SERVICE
|
|
return $?
|
|
else
|
|
SS=/usr/sbin/service
|
|
if [ -x /sbin/service ]; then
|
|
SS=/sbin/service
|
|
fi
|
|
$SS $SERVICE start
|
|
return $?
|
|
fi
|
|
}
|
|
|
|
status_service() {
|
|
if [ -n "$SCTL" ]; then
|
|
$SCTL status $SERVICE
|
|
return $?
|
|
else
|
|
SS=/usr/sbin/service
|
|
if [ -x /sbin/service ]; then
|
|
SS=/sbin/service
|
|
fi
|
|
$SS $SERVICE status
|
|
return $?
|
|
fi
|
|
}
|
|
|
|
stop_service() {
|
|
if [ -n "$SCTL" ]; then
|
|
$SCTL stop $SERVICE
|
|
return $?
|
|
else
|
|
SS=/usr/sbin/service
|
|
if [ -x /sbin/service ]; then
|
|
SS=/sbin/service
|
|
fi
|
|
$SS $SERVICE stop
|
|
return $?
|
|
fi
|
|
}
|
|
|
|
condrestart_service() {
|
|
if [ -n "$SCTL" ]; then
|
|
if $SCTL 1>/dev/null 2>/dev/null; then
|
|
$SCTL condrestart $SERVICE
|
|
return $?
|
|
fi
|
|
else
|
|
SS=/usr/sbin/service
|
|
if [ -x /sbin/service ]; then
|
|
SS=/sbin/service
|
|
fi
|
|
$SS $SERVICE condrestart
|
|
return $?
|
|
fi
|
|
}
|
|
|
|
service() {
|
|
if [ ! -f ${DEFCONFIG} ]; then
|
|
echo "Default database not found. Use $0 initdb to create it" 2>&1
|
|
if [ "$1" = "enable" ]; then
|
|
return 1
|
|
else
|
|
return 0
|
|
fi
|
|
fi
|
|
SCTL=""
|
|
# shellcheck disable=2166
|
|
if [ -d "/run/systemd/system" -a -x "/bin/systemctl" ]; then
|
|
SCTL=/bin/systemctl
|
|
fi
|
|
export SCTL
|
|
cmd=$1
|
|
shift
|
|
case "${cmd}" in
|
|
start|stop|enable|disable|status|condrestart)
|
|
"${cmd}_service" "$@"
|
|
|
|
;;
|
|
*)
|
|
echo >&2 "$USAGE_STRING"
|
|
exit 2
|
|
esac
|
|
}
|
|
|
|
command="$1"
|
|
shift
|
|
|
|
case "$command" in
|
|
initdb)
|
|
# We want wordsplitting here
|
|
# shellcheck disable=SC2086
|
|
initdb "$@" $PGSETUP_INITDB_OPTIONS || exit 1
|
|
;;
|
|
find-free-port)
|
|
find_free_port "$@" || exit 1
|
|
;;
|
|
set-server-port)
|
|
set_server_port "$@" || exit 1
|
|
;;
|
|
service)
|
|
service "$@" || exit 1
|
|
;;
|
|
set)
|
|
set_conf_value "$@" || exit 1
|
|
;;
|
|
psql)
|
|
if [ ! -f "$PGDATA/postgresql.conf" ]; then
|
|
echo "Database in $PGDATA not found. Do you need pg-setup initdb first?" 1>&2
|
|
exit 1;
|
|
fi
|
|
PORT=$(sed -n 's/^port[ ]*=[ ]*\([0-9]\+\)/\1/p' "$PGDATA/postgresql.conf")
|
|
$SU -l postgres -c "exec ${BINDIR}/psql ${PORT:+-p ${PORT}} $*"
|
|
;;
|
|
*)
|
|
echo >&2 "$USAGE_STRING"
|
|
exit 2
|
|
;;
|
|
esac
|