Files
hx-ki.com2/COM2_FIX_POSTGRES_SEMICOLON_AND_VERIFY_ONE_SHOT.sh
2026-03-06 15:22:40 +00:00

86 lines
3.0 KiB
Bash
Executable File

#!/usr/bin/env bash
set -euo pipefail
DIR="/opt/hx-ki/com2-stack"
F="$DIR/docker-compose.yml"
C="hxki-postgres"
TS="$(date +%Y%m%d-%H%M%S)"
BK="/opt/hx-ki/backups/com2-pg-semicolon-$TS"
mkdir -p "$BK"
echo "=== COM2 · FIX POSTGRES ; + VERIFY (one-shot) ==="
echo "Compose: $F"
echo "Backup: $BK"
echo
[ -f "$F" ] || { echo "FAIL: missing $F"; exit 1; }
cp -a "$F" "$BK/docker-compose.yml.pre"
echo "[1] Show offending lines (with trailing ';')"
grep -nE 'POSTGRES_(USER|PASSWORD|DB)=.*;$' "$F" || echo "OK: no trailing ';' in compose"
echo
echo "[2] Patch ONLY trailing ';' for POSTGRES_USER/POSTGRES_PASSWORD/POSTGRES_DB (compose is authority)"
# supports both list-form " - POSTGRES_USER=..." and mapping-form "POSTGRES_USER: ..."
sed -i -E \
-e 's/^(\s*-\s*POSTGRES_USER=[^;]*);$/\1/' \
-e 's/^(\s*-\s*POSTGRES_PASSWORD=[^;]*);$/\1/' \
-e 's/^(\s*-\s*POSTGRES_DB=[^;]*);$/\1/' \
-e 's/^(\s*POSTGRES_USER:\s*[^;]*);$/\1/' \
-e 's/^(\s*POSTGRES_PASSWORD:\s*[^;]*);$/\1/' \
-e 's/^(\s*POSTGRES_DB:\s*[^;]*);$/\1/' \
"$F"
echo
echo "[3] Validate compose"
docker compose -f "$F" config >/dev/null
echo "OK: compose valid"
echo
echo "[4] Recreate postgres container to re-inject ENV"
cd "$DIR"
docker compose up -d --force-recreate --no-deps "$C" >/dev/null
echo
echo "[5] Read ENV actually inside container (ground truth)"
docker inspect "$C" --format '{{range .Config.Env}}{{println .}}{{end}}' | egrep '^POSTGRES_(USER|PASSWORD|DB)=' || true
PG_USER="$(docker inspect "$C" --format '{{range .Config.Env}}{{println .}}{{end}}' | awk -F= '/^POSTGRES_USER=/{print $2}' | tail -n1)"
PG_DB="$(docker inspect "$C" --format '{{range .Config.Env}}{{println .}}{{end}}' | awk -F= '/^POSTGRES_DB=/{print $2}' | tail -n1)"
PG_PW="$(docker inspect "$C" --format '{{range .Config.Env}}{{println .}}{{end}}' | awk -F= '/^POSTGRES_PASSWORD=/{print $2}' | tail -n1)"
echo
echo "[6] Wait until Postgres accepts connections (max 30s)"
for i in $(seq 1 30); do
if docker exec -e PGPASSWORD="$PG_PW" "$C" psql -U "$PG_USER" -d "$PG_DB" -c "SELECT 1;" >/dev/null 2>&1; then
echo "OK: login works with CURRENT ENV"
OK_MODE="CURRENT_ENV"
break
fi
sleep 1
done
if [ "${OK_MODE:-}" != "CURRENT_ENV" ]; then
echo "WARN: login failed with CURRENT ENV. Testing legacy ';' variants deterministically."
# Variant B: user+db with ';' and password with ';'
if docker exec -e PGPASSWORD="${PG_PW};" "$C" psql -U "${PG_USER};" -d "${PG_DB};" -c "SELECT 1;" >/dev/null 2>&1; then
echo "OK: legacy semicolon credentials work (user/db/pw had ';' at init time)"
OK_MODE="LEGACY_SEMICOLON"
else
echo "FAIL: Neither CURRENT_ENV nor LEGACY_SEMICOLON credentials can authenticate."
echo "=> Then the only deterministic path is an auth-reset inside the data dir (no guessing), because plaintext can't be recovered."
exit 2
fi
fi
echo
echo "=== RESULT ==="
echo "MODE=$OK_MODE"
echo "POSTGRES_USER=$PG_USER"
echo "POSTGRES_DB=$PG_DB"
echo "POSTGRES_PASSWORD=$PG_PW"
echo "Backup: $BK"
echo "=== DONE ==="