Files
backend_v2/scripts/setup_pg_wsl.sh
2026-09-20 01:06:13 +08:00

165 lines
6.9 KiB
Bash
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env bash
#
# setup_pg_wsl.sh — WSL (Ubuntu/Debian) 下一键装 PostgreSQL + pgvector 开发环境
#
# 用法(在 WSL 终端里,不要用 Windows 的 CMD/PowerShell 跑):
# sudo bash setup_pg_wsl.sh
#
# 三态幂等:
# 1) 未安装 -> 安装 + 启动
# 2) 已安装未运行 -> 仅启动
# 3) 已安装且运行 -> 完全不动(不重装 / 不重启;仅幂等确保库/用户/扩展存在)
#
# 仅用于本地开发 / 迁移验证,生产环境请改强密码并单独评审配置。
#
set -euo pipefail
# ============================ 配置(按需修改)============================
PG_VERSION=16 # PostgreSQL 大版本,pgvector HNSW 在 13+ 均可用
DB_NAME=fashion # 业务库名(替换成你的项目库)
DB_USER=fashion # 应用账号
DB_PASS="fashion_dev_2026" # 仅本地开发;生产务必换成强密码
# =========================================================================
log() { echo -e "\033[32m==>\033[0m $*"; }
# 需要 root
if [ "$(id -u)" -ne 0 ]; then
echo "请以 root 运行: sudo bash $0"; exit 1
fi
# 发行版探测(仅提示,不强制)
if [ -r /etc/os-release ]; then
. /etc/os-release
log "检测到发行版: ${PRETTY_NAME:-unknown}"
case "${ID:-}" in
ubuntu|debian) ;;
*) echo "⚠️ 本脚本面向 Ubuntu/Debian WSL,其他发行版请自行调整 apt 命令";;
esac
fi
# PG 是否在运行(用超级用户连 postgres 库试探,对活实例零副作用)
pg_is_running() { sudo -u postgres psql -d postgres -tAc "SELECT 1" >/dev/null 2>&1; }
# 1) 已装则跳过安装(不重装)
if command -v psql >/dev/null 2>&1; then
log "PostgreSQL 已安装 ($(psql --version 2>/dev/null || echo unknown)),跳过安装"
else
log "安装依赖并添加 PostgreSQL 官方 apt 源"
# 关键:先清掉旧的 pgdg 源与坏 key,否则下面第一次 apt-get update 会因旧 .asc key
# 报 "not signed" 返回非零,被 set -e 直接退出,导致修 key 步骤永远没机会执行。
rm -f /etc/apt/sources.list.d/pgdg.list
rm -f /usr/share/postgresql-common/pgdg/apt.postgresql.org.asc
apt-get update -y
apt-get install -y curl ca-certificates gnupg lsb-release
# 加 pgdg 源(官方标准:armored key -> dearmor 成 .gpg,signed-by 指向 .gpg)
install -d /usr/share/postgresql-common/pgdg
curl -fsSL https://www.postgresql.org/media/keys/ACCC4CF8.asc -o /tmp/pgdg-key.asc
gpg --dearmor -o /usr/share/postgresql-common/pgdg/apt.postgresql.org.gpg /tmp/pgdg-key.asc
chmod 644 /usr/share/postgresql-common/pgdg/apt.postgresql.org.gpg
echo "deb [signed-by=/usr/share/postgresql-common/pgdg/apt.postgresql.org.gpg] https://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" \
> /etc/apt/sources.list.d/pgdg.list
apt-get update -y
apt-get install -y "postgresql-$PG_VERSION" "postgresql-client-$PG_VERSION"
fi
# 2) pgvector(已可用则跳过,不重装)
if sudo -u postgres psql -d postgres -tAc "SELECT 1 FROM pg_available_extensions WHERE name='vector'" 2>/dev/null | grep -q 1; then
log "pgvector 已可用,跳过"
else
log "安装 pgvector 扩展"
if apt-get install -y "postgresql-$PG_VERSION-pgvector"; then
:
else
echo "apt 无 pgvector 包,改用源码编译..."
apt-get install -y "build-essential" "postgresql-server-dev-$PG_VERSION" git
tmp=$(mktemp -d)
git clone --depth 1 https://github.com/pgvector/pgvector.git "$tmp/pgvector"
make -C "$tmp/pgvector"
make -C "$tmp/pgvector" install
rm -rf "$tmp"
fi
fi
# 3) 仅在未运行时启动;已在运行则完全不动
if pg_is_running; then
log "PostgreSQL 已在运行,跳过启动 / 重启"
else
log "启动 PostgreSQL"
pg_ctlcluster "$PG_VERSION" main start 2>/dev/null \
|| service postgresql start 2>/dev/null \
|| systemctl start postgresql
# 等实例就绪(最多 15s)
for i in $(seq 1 15); do
if pg_is_running; then break; fi
sleep 1
done
if ! pg_is_running; then
echo "❌ PostgreSQL 启动失败,请查日志: journalctl -u postgresql 或 /var/log/postgresql/"; exit 1
fi
fi
# 4) 幂等确保库/用户/扩展(对运行中实例无副作用,不重启)
log "确保用户、数据库与 pgvector 扩展存在(幂等)"
sudo -u postgres psql -c "ALTER USER postgres WITH PASSWORD '$DB_PASS';"
sudo -u postgres psql -c "CREATE ROLE $DB_USER LOGIN PASSWORD '$DB_PASS';" 2>/dev/null \
|| echo " 角色 $DB_USER 已存在,跳过"
sudo -u postgres psql -tc "SELECT 1 FROM pg_database WHERE datname='$DB_NAME'" | grep -q 1 \
|| sudo -u postgres createdb -O "$DB_USER" "$DB_NAME"
sudo -u postgres psql -d "$DB_NAME" -c "CREATE EXTENSION IF NOT EXISTS vector;"
# 5) 本地访问配置:仅当 listen 还不是 localhost 才改;运行中走在线 reload,绝不重启
PGCONF="/etc/postgresql/$PG_VERSION/main/postgresql.conf"
if [ -f "$PGCONF" ]; then
if grep -q "^listen_addresses = 'localhost'" "$PGCONF"; then
: # 已配置,无需改动
else
log "调整 listen_addresses=localhost(仅本地)"
sed -i "s/^#*listen_addresses = .*/listen_addresses = 'localhost'/" "$PGCONF"
if pg_is_running; then
pg_ctlcluster "$PG_VERSION" main reload 2>/dev/null \
|| sudo -u postgres psql -d postgres -c "SELECT pg_reload_conf();" >/dev/null 2>&1 \
|| echo " ⚠️ reload 失败,配置将在下次重启生效"
else
log "(实例未运行,配置将在下次启动时生效)"
fi
fi
fi
# 6) 验证
log "验证安装"
sudo -u postgres psql -d "$DB_NAME" \
-c "SELECT version();" \
-c "SELECT extname, extversion FROM pg_extension WHERE extname='vector';"
cat <<EOF
✅ PostgreSQL $PG_VERSION + pgvector 就绪(WSL)
连接串 : postgres://$DB_USER:$DB_PASS@localhost:5432/$DB_NAME
命令行 : psql -h localhost -U $DB_USER -d $DB_NAME
数据目录: /var/lib/postgresql/$PG_VERSION/main
⚠️ WSL 注意事项
- WSL 重启后 PG 不会自动起,手动: sudo service postgresql start
- 想开机自启:在 Windows 侧建 .bat 执行 wsl -u root service postgresql start
或在 /etc/wsl.conf 加 [boot] command="service postgresql start"
- 本脚本密码为弱密码,仅本地开发;生产请更换并 review pg_hba.conf
(可选)CLIP / DINOv2 embedding 表示例:
CREATE TABLE image_embedding (
id BIGSERIAL PRIMARY KEY,
image_uid VARCHAR(32) NOT NULL, -- 对应你现有的 hashid uid
kind SMALLINT NOT NULL, -- 0=runway 1=street
embedding vector(512), -- 512 维特征(CLIP ViT-B/32 或 DINOv2)
created_at INTEGER NOT NULL DEFAULT 0
);
CREATE INDEX image_embedding_vec_idx
ON image_embedding USING hnsw (embedding vector_cosine_ops);
-- 去重查询:找最近邻
SELECT image_uid, 1 - (embedding <=> '[...]'::vector) AS sim
FROM image_embedding
WHERE kind = 0
ORDER BY embedding <=> '[...]'::vector
LIMIT 20;
EOF