2026-10-11 14:45:57

This commit is contained in:
support committed 2026-10-11 16:45:57 +02:00
1 parent ce49d78f31
commit fbf826bf0c
12 files changed
+511 -56

No files matched your search

+44 -11
View File
@@ -16,6 +16,23 @@ Run the orchestrator with the PostgreSQL version to install:
./install_postgresql_extensions.sh 18.6
```
The version may also be supplied explicitly with `-v` or `--version`:
```bash
./install_postgresql_extensions.sh --version 18.6
```
The orchestrator accepts a custom installation prefix and PostgreSQL `configure` options:
```bash
./install_postgresql_extensions.sh \
--version 18.6 \
--prefix /app/postgres/rdbms/18.6 \
--options="--with-ssl=openssl,--with-lz4"
```
`-p`/`--prefix` defaults to `/app/postgres/rdbms/<version>`. `-o`/`--options` accepts a comma-separated list of `configure` arguments; if omitted, the defaults are `--with-ssl=openssl,--with-lz4`. The prefix is passed to all component installers. If the selected prefix already exists, the orchestrator asks whether to recreate it; the prompt defaults to No, and non-interactive runs cancel safely.
The orchestrator runs the installers in this order:
1. PostgreSQL
@@ -32,27 +49,41 @@ After a successful run, the orchestrator:
- Optionally updates `shared_preload_libraries` when `CONFIG_FILE` is set.
- Prints the installed PostgreSQL and extension versions.
- Creates `postgresql-<version>-engine.tar.gz` in the directory from which the command was launched.
- Recreates `sources/<complete-version>/` before starting, where `<complete-version>` is the final directory name of the selected prefix (for example, prefix `/app/postgres/rdbms/18.6.3` uses `sources/18.6.3/`). Each successfully installed component's source tree is saved there with an executable `install_<postgresql-version>.sh` recipe containing that component's configure/build/install commands.
- Creates `postgresql-<prefix-basename>-engine.tar.gz` in the directory from which the command was launched (for example, a prefix ending in `18.6.3` produces `postgresql-18.6.3-engine.tar.gz`).
- Writes the complete process log to `postgresql-<version>-process.log` in that same directory.
- Prints and logs the total execution duration in hours, minutes, and seconds.
## Individual installers
Each component can also be installed independently. The PostgreSQL installation must already exist before running an extension installer.
```bash
./install_postgresql.sh 18.6
./install_pg_cron.sh 18.6
./install_timescaledb.sh 18.6
./install_pgaudit.sh 18.6
./install_set_user.sh 18.6
./install_pg_stat_statements.sh 18.6
./install_pg_repack.sh 18.6
./install_pg_stat_monitor.sh 18.6
./install_pgvector.sh 18.6
./install_postgresql.sh --version 18.6
./install_pg_cron.sh --version 18.6
./install_timescaledb.sh --version 18.6
./install_pgaudit.sh --version 18.6
./install_set_user.sh --version 18.6
./install_pg_stat_statements.sh --version 18.6
./install_pg_repack.sh --version 18.6
./install_pg_stat_monitor.sh --version 18.6
./install_pgvector.sh --version 18.6
```
Each installer also accepts `-v 18.6` and the previous positional form (`./install_pg_cron.sh 18.6`). The all-in-one orchestrator passes its complete `--version` value to every component installer.
All source downloads, extracted source trees, and build workspaces use the `tmp/` directory alongside the scripts by default. `install_postgresql.sh` recreates that staging directory and the versioned PostgreSQL prefix before downloading sources. Each extension installer recreates only the staging directory and preserves the PostgreSQL prefix.
When the main orchestrator is invoked without `--help` or `-h`, it first recreates `tmp/` alongside the scripts. Help mode prints usage only and does not create, delete, or modify files.
Every installer accepts `--help` or `-h`, for example:
```bash
./install_pgvector.sh --help
```
The generated `install_<version>.sh` recipes also accept `--help`/`-h` and can be run from their saved component source directory to repeat that component's configure/build/install steps.
## Script descriptions
### `install_postgresql_extensions.sh`
@@ -61,7 +92,7 @@ All-in-one entry point. It invokes every installer, applies optional configurati
### `install_postgresql.sh`
Downloads, configures, builds, and installs PostgreSQL. The build uses:
Downloads, configures, builds, and installs PostgreSQL. By default, `configure` uses:
```text
--with-ssl=openssl
@@ -118,6 +149,8 @@ The following environment variables can override defaults:
| Variable | Default | Purpose |
| --- | --- | --- |
| `POSTGRES_ROOT` | `/app/postgres/rdbms` | Root directory for versioned PostgreSQL installations |
| `-p`, `--prefix` | `/app/postgres/rdbms/<version>` | Exact PostgreSQL installation prefix |
| `-o`, `--options` | `--with-ssl=openssl,--with-lz4` | Comma-separated PostgreSQL `configure` options |
| `STAGING_DIR` | `<script directory>/tmp` | Temporary source downloads, extracted source, and build directory |
| `JOBS` | `nproc` result | Parallel build job count |
| `CONFIG_FILE` | unset | PostgreSQL configuration file to update |
+106
View File
@@ -7,6 +7,51 @@ die() {
exit 1
}
show_help() {
local script_name="$1"
local description="$2"
printf '%s\n' "$description"
printf 'Usage: %s -v|--version <postgresql-version>\n' "$script_name"
printf ' %s <postgresql-version>\n' "$script_name"
printf ' %s --help | -h\n' "$script_name"
}
parse_postgresql_version() {
local version=""
local positional_seen=0
while (($#)); do
case "$1" in
-v|--version)
(($# >= 2)) || die "$1 requires a PostgreSQL version"
[[ -n "$2" ]] || die "PostgreSQL version must not be empty"
[[ -z "$version" ]] || die "PostgreSQL version was specified more than once"
version="$2"
shift 2
;;
--version=*)
[[ -n "${1#*=}" ]] || die "PostgreSQL version must not be empty"
[[ -z "$version" ]] || die "PostgreSQL version was specified more than once"
version="${1#*=}"
shift
;;
-*)
die "unknown option: $1"
;;
*)
(( positional_seen == 0 )) || die "unexpected argument: $1"
[[ -z "$version" ]] || die "PostgreSQL version was specified more than once"
version="$1"
positional_seen=1
shift
;;
esac
done
[[ -n "$version" ]] || die "PostgreSQL version is required"
validate_postgresql_version "$version"
printf '%s\n' "$version"
}
require_tools() {
local tool
for tool in "$@"; do
@@ -60,6 +105,56 @@ reset_staging_dir() {
mkdir -p "$staging_dir"
}
copy_install_source() {
local source_directory="$1"
local prefix="$2"
local source_name="$3"
local complete_version
complete_version="$(basename -- "$prefix")"
local sources_directory="$SCRIPT_DIR/sources/$complete_version"
local destination="$sources_directory/$source_name"
mkdir -p "$sources_directory"
rm -rf -- "$destination"
cp -a -- "$source_directory" "$destination"
printf '%s\n' "$destination"
}
write_install_recipe() {
local source_directory="$1"
local postgresql_version="$2"
local prefix="$3"
local configure_options="${4:-}"
local recipe="$source_directory/install_$postgresql_version.sh"
{
printf '#!/usr/bin/env bash\n\nset -Eeuo pipefail\n\n'
printf 'SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"\n'
printf 'readonly PREFIX=%q\n' "$prefix"
printf 'readonly POSTGRES_VERSION=%q\n' "$postgresql_version"
printf 'readonly POSTGRES_CONFIGURE_OPTIONS=%q\n' "$configure_options"
cat <<'RECIPE_HEADER'
if [[ "${1:-}" == "--help" || "${1:-}" == "-h" ]]; then
printf 'Re-run the saved installation steps for PostgreSQL %s.\n' "$POSTGRES_VERSION"
printf 'Usage: %s\n' "$0"
printf ' %s --help | -h\n' "$0"
exit 0
fi
[[ $# -eq 0 ]] || {
printf 'Usage: %s [--help|-h]\n' "$0" >&2
exit 2
}
readonly PG_CONFIG="$PREFIX/bin/pg_config"
readonly JOBS="${JOBS:-$(nproc)}"
RECIPE_HEADER
cat
} > "$recipe"
chmod +x "$recipe"
printf 'Saved installation recipe: %s\n' "$recipe"
}
require_postgresql_installation() {
local prefix="$1"
local pg_config="$prefix/bin/pg_config"
@@ -81,3 +176,14 @@ download_source() {
tar -xzf "$archive" -C "$staging_dir"
[[ -d "$source_dir" ]] || die "source directory was not created: $source_dir"
}
if [[ "${BASH_SOURCE[0]}" == "$0" ]]; then
if [[ "${1:-}" == "--help" || "${1:-}" == "-h" ]]; then
printf 'Shared helper functions used by PostgreSQL component installers.\n'
printf 'This file is sourced by the install scripts and does not install a component.\n'
exit 0
fi
printf 'This helper is not an installer; run a component installer with <postgresql-version>.\n' >&2
printf 'Usage: %s --help | -h\n' "$0" >&2
exit 2
fi
+22 -3
View File
@@ -10,11 +10,16 @@ readonly STAGING_DIR="${STAGING_DIR:-$SCRIPT_DIR/tmp}"
readonly POSTGRES_ROOT="${POSTGRES_ROOT:-/app/postgres/rdbms}"
readonly PG_CRON_REPOSITORY="${PG_CRON_REPOSITORY:-citusdata/pg_cron}"
[[ $# -eq 1 ]] || die "Usage: $0 <postgresql-version>"
readonly POSTGRES_VERSION="$1"
if [[ "${1:-}" == "--help" || "${1:-}" == "-h" ]]; then
show_help "$0" "Build and install pg_cron for an existing PostgreSQL installation."
exit 0
fi
POSTGRES_VERSION="$(parse_postgresql_version "$@")"
readonly POSTGRES_VERSION
validate_postgresql_version "$POSTGRES_VERSION"
require_tools curl tar make
readonly PREFIX="$POSTGRES_ROOT/$POSTGRES_VERSION"
readonly PREFIX="${PREFIX:-$POSTGRES_ROOT/$POSTGRES_VERSION}"
readonly PG_CONFIG="$PREFIX/bin/pg_config"
require_postgresql_installation "$PREFIX"
reset_staging_dir "$STAGING_DIR"
@@ -30,3 +35,17 @@ cd "$PG_CRON_DIR"
make -j"${JOBS:-$(nproc)}" PG_CONFIG="$PG_CONFIG"
make install PG_CONFIG="$PG_CONFIG"
test -x "$PREFIX/lib/pg_cron.so"
readonly SAVED_SOURCE_DIR="$(copy_install_source "$PG_CRON_DIR" "$PREFIX" "pg_cron-$PG_CRON_TAG")"
write_install_recipe "$SAVED_SOURCE_DIR" "$POSTGRES_VERSION" "$PREFIX" <<'RECIPE'
cd "$SCRIPT_DIR"
# Configure
# pg_cron uses PG_CONFIG directly and does not require a separate configure step.
# Make
make -j"$JOBS" PG_CONFIG="$PG_CONFIG"
# Make install
make install PG_CONFIG="$PG_CONFIG"
RECIPE
+22 -3
View File
@@ -10,11 +10,16 @@ readonly STAGING_DIR="${STAGING_DIR:-$SCRIPT_DIR/tmp}"
readonly POSTGRES_ROOT="${POSTGRES_ROOT:-/app/postgres/rdbms}"
readonly PG_REPACK_REPOSITORY="${PG_REPACK_REPOSITORY:-reorg/pg_repack}"
[[ $# -eq 1 ]] || die "Usage: $0 <postgresql-version>"
readonly POSTGRES_VERSION="$1"
if [[ "${1:-}" == "--help" || "${1:-}" == "-h" ]]; then
show_help "$0" "Build and install pg_repack for an existing PostgreSQL installation."
exit 0
fi
POSTGRES_VERSION="$(parse_postgresql_version "$@")"
readonly POSTGRES_VERSION
validate_postgresql_version "$POSTGRES_VERSION"
require_tools curl tar make
readonly PREFIX="$POSTGRES_ROOT/$POSTGRES_VERSION"
readonly PREFIX="${PREFIX:-$POSTGRES_ROOT/$POSTGRES_VERSION}"
readonly PG_CONFIG="$PREFIX/bin/pg_config"
require_postgresql_installation "$PREFIX"
reset_staging_dir "$STAGING_DIR"
@@ -31,3 +36,17 @@ make -j"${JOBS:-$(nproc)}" PG_CONFIG="$PG_CONFIG"
make install PG_CONFIG="$PG_CONFIG"
test -x "$PREFIX/bin/pg_repack"
test -f "$PREFIX/share/extension/pg_repack.control"
readonly SAVED_SOURCE_DIR="$(copy_install_source "$PG_REPACK_DIR" "$PREFIX" "pg_repack-$PG_REPACK_TAG")"
write_install_recipe "$SAVED_SOURCE_DIR" "$POSTGRES_VERSION" "$PREFIX" <<'RECIPE'
cd "$SCRIPT_DIR"
# Configure
# pg_repack uses PG_CONFIG directly and does not require a separate configure step.
# Make
make -j"$JOBS" PG_CONFIG="$PG_CONFIG"
# Make install
make install PG_CONFIG="$PG_CONFIG"
RECIPE
@@ -10,11 +10,16 @@ readonly STAGING_DIR="${STAGING_DIR:-$SCRIPT_DIR/tmp}"
readonly POSTGRES_ROOT="${POSTGRES_ROOT:-/app/postgres/rdbms}"
readonly PG_STAT_MONITOR_REPOSITORY="${PG_STAT_MONITOR_REPOSITORY:-percona/pg_stat_monitor}"
[[ $# -eq 1 ]] || die "Usage: $0 <postgresql-version>"
readonly POSTGRES_VERSION="$1"
if [[ "${1:-}" == "--help" || "${1:-}" == "-h" ]]; then
show_help "$0" "Build and install pg_stat_monitor for an existing PostgreSQL installation."
exit 0
fi
POSTGRES_VERSION="$(parse_postgresql_version "$@")"
readonly POSTGRES_VERSION
validate_postgresql_version "$POSTGRES_VERSION"
require_tools curl tar make
readonly PREFIX="$POSTGRES_ROOT/$POSTGRES_VERSION"
readonly PREFIX="${PREFIX:-$POSTGRES_ROOT/$POSTGRES_VERSION}"
readonly PG_CONFIG="$PREFIX/bin/pg_config"
require_postgresql_installation "$PREFIX"
reset_staging_dir "$STAGING_DIR"
@@ -31,3 +36,17 @@ make -j"${JOBS:-$(nproc)}" PG_CONFIG="$PG_CONFIG"
make install PG_CONFIG="$PG_CONFIG"
test -x "$PREFIX/lib/pg_stat_monitor.so"
test -f "$PREFIX/share/extension/pg_stat_monitor.control"
readonly SAVED_SOURCE_DIR="$(copy_install_source "$PG_STAT_MONITOR_DIR" "$PREFIX" "pg_stat_monitor-$PG_STAT_MONITOR_TAG")"
write_install_recipe "$SAVED_SOURCE_DIR" "$POSTGRES_VERSION" "$PREFIX" <<'RECIPE'
cd "$SCRIPT_DIR"
# Configure
# pg_stat_monitor uses PGXS directly and does not require a separate configure step.
# Make
make -j"$JOBS" PG_CONFIG="$PG_CONFIG"
# Make install
make install PG_CONFIG="$PG_CONFIG"
RECIPE
@@ -9,11 +9,16 @@ source "$SCRIPT_DIR/install_common.sh"
readonly STAGING_DIR="${STAGING_DIR:-$SCRIPT_DIR/tmp}"
readonly POSTGRES_ROOT="${POSTGRES_ROOT:-/app/postgres/rdbms}"
[[ $# -eq 1 ]] || die "Usage: $0 <postgresql-version>"
readonly POSTGRES_VERSION="$1"
if [[ "${1:-}" == "--help" || "${1:-}" == "-h" ]]; then
show_help "$0" "Build and install pg_stat_statements from matching PostgreSQL source."
exit 0
fi
POSTGRES_VERSION="$(parse_postgresql_version "$@")"
readonly POSTGRES_VERSION
validate_postgresql_version "$POSTGRES_VERSION"
require_tools curl tar make
readonly PREFIX="$POSTGRES_ROOT/$POSTGRES_VERSION"
readonly PREFIX="${PREFIX:-$POSTGRES_ROOT/$POSTGRES_VERSION}"
readonly PG_CONFIG="$PREFIX/bin/pg_config"
require_postgresql_installation "$PREFIX"
reset_staging_dir "$STAGING_DIR"
@@ -30,3 +35,17 @@ make -C "$POSTGRES_SOURCE/contrib/pg_stat_statements" \
make -C "$POSTGRES_SOURCE/contrib/pg_stat_statements" \
install USE_PGXS=1 PG_CONFIG="$PG_CONFIG"
grep -E '^default_version' "$PREFIX/share/extension/pg_stat_statements.control"
readonly SAVED_SOURCE_DIR="$(copy_install_source "$POSTGRES_SOURCE/contrib/pg_stat_statements" "$PREFIX" "pg_stat_statements-$POSTGRES_VERSION")"
write_install_recipe "$SAVED_SOURCE_DIR" "$POSTGRES_VERSION" "$PREFIX" <<'RECIPE'
cd "$SCRIPT_DIR"
# Configure
# pg_stat_statements uses PGXS directly and does not require a separate configure step.
# Make
make -j"$JOBS" USE_PGXS=1 PG_CONFIG="$PG_CONFIG"
# Make install
make install USE_PGXS=1 PG_CONFIG="$PG_CONFIG"
RECIPE
+22 -3
View File
@@ -10,11 +10,16 @@ readonly STAGING_DIR="${STAGING_DIR:-$SCRIPT_DIR/tmp}"
readonly POSTGRES_ROOT="${POSTGRES_ROOT:-/app/postgres/rdbms}"
readonly PGAUDIT_REPOSITORY="${PGAUDIT_REPOSITORY:-pgaudit/pgaudit}"
[[ $# -eq 1 ]] || die "Usage: $0 <postgresql-version>"
readonly POSTGRES_VERSION="$1"
if [[ "${1:-}" == "--help" || "${1:-}" == "-h" ]]; then
show_help "$0" "Build and install pgAudit for an existing PostgreSQL installation."
exit 0
fi
POSTGRES_VERSION="$(parse_postgresql_version "$@")"
readonly POSTGRES_VERSION
validate_postgresql_version "$POSTGRES_VERSION"
require_tools curl tar make
readonly PREFIX="$POSTGRES_ROOT/$POSTGRES_VERSION"
readonly PREFIX="${PREFIX:-$POSTGRES_ROOT/$POSTGRES_VERSION}"
readonly PG_CONFIG="$PREFIX/bin/pg_config"
require_postgresql_installation "$PREFIX"
reset_staging_dir "$STAGING_DIR"
@@ -30,3 +35,17 @@ cd "$PGAUDIT_DIR"
make -j"${JOBS:-$(nproc)}" USE_PGXS=1 PG_CONFIG="$PG_CONFIG"
make install USE_PGXS=1 PG_CONFIG="$PG_CONFIG"
test -x "$PREFIX/lib/pgaudit.so"
readonly SAVED_SOURCE_DIR="$(copy_install_source "$PGAUDIT_DIR" "$PREFIX" "pgaudit-$PGAUDIT_TAG")"
write_install_recipe "$SAVED_SOURCE_DIR" "$POSTGRES_VERSION" "$PREFIX" <<'RECIPE'
cd "$SCRIPT_DIR"
# Configure
# pgAudit uses PGXS directly and does not require a separate configure step.
# Make
make -j"$JOBS" USE_PGXS=1 PG_CONFIG="$PG_CONFIG"
# Make install
make install USE_PGXS=1 PG_CONFIG="$PG_CONFIG"
RECIPE
+22 -3
View File
@@ -10,11 +10,16 @@ readonly STAGING_DIR="${STAGING_DIR:-$SCRIPT_DIR/tmp}"
readonly POSTGRES_ROOT="${POSTGRES_ROOT:-/app/postgres/rdbms}"
readonly PGVECTOR_REPOSITORY="${PGVECTOR_REPOSITORY:-pgvector/pgvector}"
[[ $# -eq 1 ]] || die "Usage: $0 <postgresql-version>"
readonly POSTGRES_VERSION="$1"
if [[ "${1:-}" == "--help" || "${1:-}" == "-h" ]]; then
show_help "$0" "Build and install pgvector for an existing PostgreSQL installation."
exit 0
fi
POSTGRES_VERSION="$(parse_postgresql_version "$@")"
readonly POSTGRES_VERSION
validate_postgresql_version "$POSTGRES_VERSION"
require_tools curl tar make
readonly PREFIX="$POSTGRES_ROOT/$POSTGRES_VERSION"
readonly PREFIX="${PREFIX:-$POSTGRES_ROOT/$POSTGRES_VERSION}"
readonly PG_CONFIG="$PREFIX/bin/pg_config"
require_postgresql_installation "$PREFIX"
reset_staging_dir "$STAGING_DIR"
@@ -32,3 +37,17 @@ make -j"${JOBS:-$(nproc)}" PG_CONFIG="$PG_CONFIG"
make install PG_CONFIG="$PG_CONFIG"
test -f "$PREFIX/lib/vector.so"
test -f "$PREFIX/share/extension/vector.control"
readonly SAVED_SOURCE_DIR="$(copy_install_source "$PGVECTOR_DIR" "$PREFIX" "pgvector-$PGVECTOR_TAG")"
write_install_recipe "$SAVED_SOURCE_DIR" "$POSTGRES_VERSION" "$PREFIX" <<'RECIPE'
cd "$SCRIPT_DIR"
# Configure
# pgvector uses PGXS directly and does not require a separate configure step.
# Make
make -j"$JOBS" PG_CONFIG="$PG_CONFIG"
# Make install
make install PG_CONFIG="$PG_CONFIG"
RECIPE
@@ -9,12 +9,18 @@ source "$SCRIPT_DIR/install_common.sh"
readonly STAGING_DIR="${STAGING_DIR:-$SCRIPT_DIR/tmp}"
readonly POSTGRES_ROOT="${POSTGRES_ROOT:-/app/postgres/rdbms}"
[[ $# -eq 1 ]] || die "Usage: $0 <postgresql-version>"
readonly POSTGRES_VERSION="$1"
if [[ "${1:-}" == "--help" || "${1:-}" == "-h" ]]; then
show_help "$0" "Build and install PostgreSQL from source."
exit 0
fi
POSTGRES_VERSION="$(parse_postgresql_version "$@")"
readonly POSTGRES_VERSION
validate_postgresql_version "$POSTGRES_VERSION"
require_tools curl tar make gcc
readonly PREFIX="$POSTGRES_ROOT/$POSTGRES_VERSION"
readonly PREFIX="${PREFIX:-$POSTGRES_ROOT/$POSTGRES_VERSION}"
readonly POSTGRES_CONFIGURE_OPTIONS="${POSTGRES_CONFIGURE_OPTIONS:---with-ssl=openssl,--with-lz4}"
readonly PG_BIN="$PREFIX/bin"
readonly PG_CONFIG="$PG_BIN/pg_config"
[[ "$PREFIX" != "/" ]] || die "PREFIX must not be the filesystem root"
@@ -31,13 +37,33 @@ curl -fL --retry 3 --retry-delay 2 \
tar -xzf "$POSTGRES_ARCHIVE" -C "$STAGING_DIR"
cd "$POSTGRES_SOURCE"
[[ "$POSTGRES_CONFIGURE_OPTIONS" != ,* &&
"$POSTGRES_CONFIGURE_OPTIONS" != *, &&
"$POSTGRES_CONFIGURE_OPTIONS" != *,,* ]] || die "configure options must be a non-empty comma-separated list"
IFS=',' read -r -a CONFIGURE_OPTIONS <<< "${POSTGRES_CONFIGURE_OPTIONS:-}"
./configure \
--prefix="$PREFIX" \
--with-ssl=openssl \
--with-lz4
"${CONFIGURE_OPTIONS[@]}"
make -j"${JOBS:-$(nproc)}"
make install
printf '\nVerification:\n'
"$PG_BIN/postgres" --version
"$PG_CONFIG" --version
readonly SAVED_SOURCE_DIR="$(copy_install_source "$POSTGRES_SOURCE" "$PREFIX" "postgresql-$POSTGRES_VERSION")"
write_install_recipe "$SAVED_SOURCE_DIR" "$POSTGRES_VERSION" "$PREFIX" "$POSTGRES_CONFIGURE_OPTIONS" <<'RECIPE'
cd "$SCRIPT_DIR"
# Configure
IFS=',' read -r -a CONFIGURE_OPTIONS <<< "$POSTGRES_CONFIGURE_OPTIONS"
./configure \
--prefix="$PREFIX" \
"${CONFIGURE_OPTIONS[@]}"
# Make
make -j"$JOBS"
# Make install
make install
RECIPE
@@ -5,31 +5,157 @@ set -Eeuo pipefail
SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
readonly INVOCATION_DIR="$PWD"
[[ $# -eq 1 ]] || {
printf 'Usage: %s <postgresql-version>\n' "$0" >&2
usage() {
printf 'Usage: %s [-v|--version <postgresql-version>] [-p|--prefix <path>] [-o|--options <configure-options>]\n' "$0"
printf ' %s [-p|--prefix <path>] [-o|--options <configure-options>] <postgresql-version>\n' "$0"
printf ' %s --help | -h\n' "$0"
}
for argument in "$@"; do
if [[ "$argument" == "--help" || "$argument" == "-h" ]]; then
usage
exit 0
fi
done
POSTGRES_VERSION=""
PREFIX_OVERRIDE=""
CONFIGURE_OPTIONS="--with-ssl=openssl,--with-lz4"
while (($#)); do
case "$1" in
-p|--prefix)
(($# >= 2)) || { printf 'ERROR: %s requires a path\n' "$1" >&2; exit 2; }
[[ -n "$2" ]] || { printf 'ERROR: prefix path must not be empty\n' >&2; exit 2; }
PREFIX_OVERRIDE="$2"
shift 2
;;
-v|--version)
(($# >= 2)) || { printf 'ERROR: %s requires a PostgreSQL version\n' "$1" >&2; exit 2; }
[[ -n "$2" ]] || { printf 'ERROR: PostgreSQL version must not be empty\n' >&2; exit 2; }
[[ -z "$POSTGRES_VERSION" ]] || { printf 'ERROR: PostgreSQL version was specified more than once\n' >&2; exit 2; }
POSTGRES_VERSION="$2"
shift 2
;;
--prefix=*)
PREFIX_OVERRIDE="${1#*=}"
[[ -n "$PREFIX_OVERRIDE" ]] || { printf 'ERROR: prefix path must not be empty\n' >&2; exit 2; }
shift
;;
--version=*)
[[ -n "${1#*=}" ]] || { printf 'ERROR: PostgreSQL version must not be empty\n' >&2; exit 2; }
[[ -z "$POSTGRES_VERSION" ]] || { printf 'ERROR: PostgreSQL version was specified more than once\n' >&2; exit 2; }
POSTGRES_VERSION="${1#*=}"
shift
;;
-o|--options)
(($# >= 2)) || { printf 'ERROR: %s requires a comma-separated option list\n' "$1" >&2; exit 2; }
CONFIGURE_OPTIONS="$2"
shift 2
;;
--options=*)
CONFIGURE_OPTIONS="${1#*=}"
shift
;;
-*)
printf 'ERROR: unknown option: %s\n' "$1" >&2
usage >&2
exit 2
;;
*)
[[ -z "$POSTGRES_VERSION" ]] || { printf 'ERROR: unexpected argument: %s\n' "$1" >&2; usage >&2; exit 2; }
POSTGRES_VERSION="$1"
shift
;;
esac
done
[[ -n "$POSTGRES_VERSION" ]] || { usage >&2; exit 2; }
[[ "$POSTGRES_VERSION" =~ ^[0-9]+\.[0-9]+([.][0-9]+)?$ ]] || {
printf 'ERROR: invalid PostgreSQL version: %s\n' "$POSTGRES_VERSION" >&2
exit 1
}
SECONDS=0
readonly POSTGRES_ROOT="${POSTGRES_ROOT:-/app/postgres/rdbms}"
PREFIX="${PREFIX_OVERRIDE:-$POSTGRES_ROOT/$POSTGRES_VERSION}"
readonly POSTGRES_CONFIGURE_OPTIONS="$CONFIGURE_OPTIONS"
[[ "$PREFIX" == /* && "$PREFIX" != "/" && "$PREFIX" != "$POSTGRES_ROOT" ]] || {
printf 'ERROR: prefix must be an absolute version-specific directory, not / or POSTGRES_ROOT itself: %s\n' "$PREFIX" >&2
exit 1
}
readonly NORMALIZED_PREFIX="$(realpath -m -- "$PREFIX")"
readonly NORMALIZED_POSTGRES_ROOT="$(realpath -m -- "$POSTGRES_ROOT")"
[[ "$NORMALIZED_PREFIX" != "/" && "$NORMALIZED_PREFIX" != "$NORMALIZED_POSTGRES_ROOT" ]] || {
printf 'ERROR: prefix must not resolve to / or POSTGRES_ROOT: %s\n' "$PREFIX" >&2
exit 1
}
readonly PREFIX="$NORMALIZED_PREFIX"
if [[ -n "$POSTGRES_CONFIGURE_OPTIONS" ]]; then
[[ "$POSTGRES_CONFIGURE_OPTIONS" != ,* &&
"$POSTGRES_CONFIGURE_OPTIONS" != *, &&
"$POSTGRES_CONFIGURE_OPTIONS" != *,,* ]] || {
printf 'ERROR: configure options must be a non-empty comma-separated list\n' >&2
exit 2
}
readonly POSTGRES_VERSION="$1"
IFS=',' read -r -a parsed_configure_options <<< "$POSTGRES_CONFIGURE_OPTIONS"
for option in "${parsed_configure_options[@]}"; do
[[ "$option" == -* && "$option" != "-" ]] || {
printf 'ERROR: invalid PostgreSQL configure option: %s\n' "$option" >&2
exit 2
}
done
fi
readonly PREFIX_VERSION="$(basename -- "$PREFIX")"
readonly SOURCES_DIR="$SCRIPT_DIR/sources/$PREFIX_VERSION"
readonly STAGING_DIR="$SCRIPT_DIR/tmp"
readonly PROCESS_LOG="$INVOCATION_DIR/postgresql-$POSTGRES_VERSION-process.log"
readonly ENGINE_ARCHIVE="$INVOCATION_DIR/postgresql-$POSTGRES_VERSION-engine.tar.gz"
readonly ENGINE_ARCHIVE="$INVOCATION_DIR/postgresql-$PREFIX_VERSION-engine.tar.gz"
[[ "$STAGING_DIR" != "/" ]] || {
printf 'ERROR: staging directory must not be the filesystem root\n' >&2
exit 1
}
rm -rf -- "$STAGING_DIR"
mkdir -p "$STAGING_DIR"
export PREFIX POSTGRES_CONFIGURE_OPTIONS
if [[ -e "$PREFIX" || -L "$PREFIX" ]]; then
printf 'WARNING: PostgreSQL installation directory already exists: %s\n' "$PREFIX" >&2
if [[ ! -t 0 ]]; then
printf 'Non-interactive input; defaulting to No and exiting without changes.\n' >&2
exit 0
fi
read -r -p "Recreate this directory and continue? [y/N] " response || response=""
case "$response" in
Y|y) printf 'Confirmed: %s will be recreated.\n' "$PREFIX" ;;
*) printf 'Installation cancelled; existing directory was left unchanged.\n'; exit 0 ;;
esac
fi
exec > >(tee "$PROCESS_LOG") 2>&1
printf 'Installation started: %s\n' "$(date -Is)"
printf 'Invocation directory: %s\n' "$INVOCATION_DIR"
printf 'PostgreSQL version: %s\n' "$POSTGRES_VERSION"
printf 'Install prefix: %s\n' "$PREFIX"
printf 'PostgreSQL configure options: %s\n' "${POSTGRES_CONFIGURE_OPTIONS:-<none>}"
printf 'Recreating source archive directory: %s\n' "$SOURCES_DIR"
rm -rf -- "$SOURCES_DIR"
mkdir -p "$SOURCES_DIR"
"$SCRIPT_DIR/install_postgresql.sh" "$POSTGRES_VERSION"
"$SCRIPT_DIR/install_pg_cron.sh" "$POSTGRES_VERSION"
"$SCRIPT_DIR/install_timescaledb.sh" "$POSTGRES_VERSION"
"$SCRIPT_DIR/install_pgaudit.sh" "$POSTGRES_VERSION"
"$SCRIPT_DIR/install_set_user.sh" "$POSTGRES_VERSION"
"$SCRIPT_DIR/install_pg_stat_statements.sh" "$POSTGRES_VERSION"
"$SCRIPT_DIR/install_pg_repack.sh" "$POSTGRES_VERSION"
"$SCRIPT_DIR/install_pg_stat_monitor.sh" "$POSTGRES_VERSION"
"$SCRIPT_DIR/install_pgvector.sh" "$POSTGRES_VERSION"
"$SCRIPT_DIR/install_postgresql.sh" --version "$POSTGRES_VERSION"
"$SCRIPT_DIR/install_pg_cron.sh" --version "$POSTGRES_VERSION"
"$SCRIPT_DIR/install_timescaledb.sh" --version "$POSTGRES_VERSION"
"$SCRIPT_DIR/install_pgaudit.sh" --version "$POSTGRES_VERSION"
"$SCRIPT_DIR/install_set_user.sh" --version "$POSTGRES_VERSION"
"$SCRIPT_DIR/install_pg_stat_statements.sh" --version "$POSTGRES_VERSION"
"$SCRIPT_DIR/install_pg_repack.sh" --version "$POSTGRES_VERSION"
"$SCRIPT_DIR/install_pg_stat_monitor.sh" --version "$POSTGRES_VERSION"
"$SCRIPT_DIR/install_pgvector.sh" --version "$POSTGRES_VERSION"
readonly POSTGRES_ROOT="${POSTGRES_ROOT:-/app/postgres/rdbms}"
readonly PREFIX="$POSTGRES_ROOT/$POSTGRES_VERSION"
readonly CONFIG_FILE="${CONFIG_FILE:-}"
readonly SHARED_PRELOAD_LIBRARIES="pg_cron,timescaledb,pgaudit,pg_stat_statements,pg_stat_monitor"
@@ -74,6 +200,7 @@ extension_version() {
printf '\nInstalled products and extensions:\n'
printf ' PostgreSQL: %s\n' "$("$PREFIX/bin/pg_config" --version | sed 's/^PostgreSQL //')"
printf ' PostgreSQL configure options: %s\n' "${POSTGRES_CONFIGURE_OPTIONS//,/ }"
printf ' pg_cron: %s\n' "$(extension_version pg_cron)"
printf ' TimescaleDB: %s\n' "$(extension_version timescaledb)"
printf ' pgaudit: %s\n' "$(extension_version pgaudit)"
@@ -85,7 +212,14 @@ printf ' pgvector: %s\n' "$(extension_version vector)"
printf " shared_preload_libraries = '%s'\n" "$SHARED_PRELOAD_LIBRARIES"
rm -f -- "$ENGINE_ARCHIVE"
tar -czf "$ENGINE_ARCHIVE" -C "$POSTGRES_ROOT" "$POSTGRES_VERSION"
tar -czf "$ENGINE_ARCHIVE" -C "$(dirname -- "$PREFIX")" "$(basename -- "$PREFIX")"
printf '\nCreated engine archive: %s\n' "$ENGINE_ARCHIVE"
printf 'Archive size: %s\n' "$(du -h "$ENGINE_ARCHIVE" | awk '{print $1}')"
elapsed_seconds=$SECONDS
elapsed_hours=$((elapsed_seconds / 3600))
elapsed_minutes=$(((elapsed_seconds % 3600) / 60))
elapsed_remainder=$((elapsed_seconds % 60))
printf 'Total execution time: %dh %dm %ds\n' \
"$elapsed_hours" "$elapsed_minutes" "$elapsed_remainder"
printf 'Installation completed: %s\n' "$(date -Is)"
exit 0
+22 -3
View File
@@ -10,11 +10,16 @@ readonly STAGING_DIR="${STAGING_DIR:-$SCRIPT_DIR/tmp}"
readonly POSTGRES_ROOT="${POSTGRES_ROOT:-/app/postgres/rdbms}"
readonly SET_USER_REPOSITORY="${SET_USER_REPOSITORY:-pgaudit/set_user}"
[[ $# -eq 1 ]] || die "Usage: $0 <postgresql-version>"
readonly POSTGRES_VERSION="$1"
if [[ "${1:-}" == "--help" || "${1:-}" == "-h" ]]; then
show_help "$0" "Build and install set_user for an existing PostgreSQL installation."
exit 0
fi
POSTGRES_VERSION="$(parse_postgresql_version "$@")"
readonly POSTGRES_VERSION
validate_postgresql_version "$POSTGRES_VERSION"
require_tools curl tar make
readonly PREFIX="$POSTGRES_ROOT/$POSTGRES_VERSION"
readonly PREFIX="${PREFIX:-$POSTGRES_ROOT/$POSTGRES_VERSION}"
readonly PG_CONFIG="$PREFIX/bin/pg_config"
require_postgresql_installation "$PREFIX"
reset_staging_dir "$STAGING_DIR"
@@ -30,3 +35,17 @@ cd "$SET_USER_DIR"
make -j"${JOBS:-$(nproc)}" PG_CONFIG="$PG_CONFIG"
make install PG_CONFIG="$PG_CONFIG"
test -x "$PREFIX/lib/set_user.so"
readonly SAVED_SOURCE_DIR="$(copy_install_source "$SET_USER_DIR" "$PREFIX" "set_user-$SET_USER_TAG")"
write_install_recipe "$SAVED_SOURCE_DIR" "$POSTGRES_VERSION" "$PREFIX" <<'RECIPE'
cd "$SCRIPT_DIR"
# Configure
# set_user uses PGXS directly and does not require a separate configure step.
# Make
make -j"$JOBS" PG_CONFIG="$PG_CONFIG"
# Make install
make install PG_CONFIG="$PG_CONFIG"
RECIPE
@@ -10,11 +10,16 @@ readonly STAGING_DIR="${STAGING_DIR:-$SCRIPT_DIR/tmp}"
readonly POSTGRES_ROOT="${POSTGRES_ROOT:-/app/postgres/rdbms}"
readonly TIMESCALEDB_REPOSITORY="${TIMESCALEDB_REPOSITORY:-timescale/timescaledb}"
[[ $# -eq 1 ]] || die "Usage: $0 <postgresql-version>"
readonly POSTGRES_VERSION="$1"
if [[ "${1:-}" == "--help" || "${1:-}" == "-h" ]]; then
show_help "$0" "Build and install TimescaleDB for an existing PostgreSQL installation."
exit 0
fi
POSTGRES_VERSION="$(parse_postgresql_version "$@")"
readonly POSTGRES_VERSION
validate_postgresql_version "$POSTGRES_VERSION"
require_tools curl tar cmake
readonly PREFIX="$POSTGRES_ROOT/$POSTGRES_VERSION"
readonly PREFIX="${PREFIX:-$POSTGRES_ROOT/$POSTGRES_VERSION}"
readonly PG_CONFIG="$PREFIX/bin/pg_config"
require_postgresql_installation "$PREFIX"
reset_staging_dir "$STAGING_DIR"
@@ -34,3 +39,21 @@ cd "$TIMESCALEDB_DIR"
cmake --build build --parallel "${JOBS:-$(nproc)}"
cmake --install build
test -x "$PREFIX/lib/timescaledb.so"
readonly SAVED_SOURCE_DIR="$(copy_install_source "$TIMESCALEDB_DIR" "$PREFIX" "timescaledb-$TIMESCALEDB_TAG")"
write_install_recipe "$SAVED_SOURCE_DIR" "$POSTGRES_VERSION" "$PREFIX" <<'RECIPE'
cd "$SCRIPT_DIR"
# Configure
rm -rf -- build
./bootstrap \
-DPG_CONFIG="$PG_CONFIG" \
-DCMAKE_INSTALL_PREFIX="$PREFIX" \
-DCMAKE_BUILD_TYPE=Release
# Make
cmake --build build --parallel "$JOBS"
# Make install
cmake --install build
RECIPE