apt upgrade 之后,飞牛相册挂了:PG 15 到 18 的血泪迁移
一个
apt upgrade,629 项相册内容集体失败。根因只是几行硬编码的路径。
本文首发地址 https://h89.cn/archives/629.html
一、事故现场
打开飞牛相册,新图片人脸识别失败,第一反应当然是应用自己的问题,重新安装模型/重建索引,都提示失败,卸载飞牛相册(删除数据),再次识别扑头盖脸一堆红字:
629项内容失败,initdb failed: exit status 1
basePath=/var/apps/trim.photos/meta/data/pgvector
pwfile=/var/apps/trim.photos/meta/data/pgvector/pwfile.txt
workingDir=/usr/local/apps/@appdata/trim.photos
hint: ensure postgres user can read pwfile and enter workingDir
Output: sudo: /usr/lib/postgresql/15/bin/initdb: command not found
此时注意到那一行 initdb: command not found——这跟飞牛相册没关系,是系统里 PG 15 没了。
飞牛相册在启动时会用 initdb/pg_ctl 自己拉起一个 PostgreSQL 实例(数据目录在 /var/apps/trim.photos/meta/data/pgvector/),不走系统的 systemd 服务;这个实例用来存图片的人脸向量(pgvector 扩展)。初始化失败,相册直接瘫痪。
环境:Debian 12 (bookworm),PG 走 pgdg 官方 apt 源。
二、根因:PG 从 15 升级到 18,飞牛相册没跟上
看一眼系统状态:
$ dpkg -l | grep postgresql
ii postgresql-18 18.4-1.pgdg12+1 # PG 18 已安装
# 找不到 postgresql-15 # PG 15 二进制包已卸载
$ ls /usr/lib/postgresql/15/
lib/ # 只剩一个 lib/ 目录,bin/ 已经没了
$ ls /usr/lib/postgresql/15/lib/
vector.so # pgvector 扩展残留,没清理干净
根因链条:
- Debian 12,PG 装了 pgdg 官方源
- 2026-06-15 执行
apt upgrade,postgresql-common从 248 升到 291,postgresql元包从15+248变成18+291——PG 18 被安装,PG 15 仍保留(升级到 15.18) - 同一天稍后,手动执行
apt purge postgresql-15 postgresql-client-15,PG 15 的initdb、pg_ctl等二进制被清除 - 但
postgresql-15-pgvector包的vector.so残留在/usr/lib/postgresql/15/lib/ - 飞牛相册的 Go 二进制里,硬编码了 PG 15 的路径
从二进制里直接搜:
$ strings trim-photos | grep "postgresql/15"
/usr/lib/postgresql/15/bin/initdb
/usr/lib/postgresql/15/bin/pg_ctl
sudo -u postgres /usr/lib/postgresql/15/bin/pg_ctl -D %s start
sudo -u postgres /usr/lib/postgresql/15/bin/pg_ctl -D %s stop
Go 编译时路径写死了,升级 PG 就让这些引用全部变成死链接。闭源二进制你还没法改,只能从系统层面桥接。
三、为什么不能直接软链接
软链接是最直觉的解法:
ln -s /usr/lib/postgresql/18/bin /usr/lib/postgresql/15/bin
但有一个坑:PG 扩展是主版本绑定的。 这里其实是两个独立的问题:
-
路径找不到:PG 18 进程只在它自己的
pkglibdir(/usr/lib/postgresql/18/lib/)下找扩展,根本不会去翻/usr/lib/postgresql/15/lib/。系统里那个残留的 15 版vector.so,对 PG 18 来说等于不存在。 -
ABI 不兼容:就算你把 15 版的
vector.so拷到 18 的 lib 目录,也加载不了——pgvector 编译时绑定 PG 主版本 ABI,跨主版本直接ERROR: incompatible extension。
所以光桥接二进制不够,还得给 PG 18 装上对应版本的 pgvector 扩展。
四、修复(两条命令)
# 1. 安装 PG 18 版 pgvector
sudo apt install -y postgresql-18-pgvector
# 2. 创建 bin 软链接,桥接硬编码路径
sudo ln -s /usr/lib/postgresql/18/bin /usr/lib/postgresql/15/bin
验证:
$ ls -la /usr/lib/postgresql/15/bin
lrwxrwxrwx ... /usr/lib/postgresql/15/bin -> /usr/lib/postgresql/18/bin
$ dpkg -l | grep postgresql-18-pgvector
ii postgresql-18-pgvector 0.8.2-1.pgdg12+1
$ ls /usr/lib/postgresql/18/lib/vector.so
/usr/lib/postgresql/18/lib/vector.so
⚠️ 前提条件:这个软链接方案只在 数据目录为空或可重建 时安全。飞牛相册的 pgvector 数据目录会被清空后重新
initdb,所以没问题。如果你的/var/lib/postgresql/15/下已经有真实的 PG 15 集群数据,不要直接套这个方案——PG 18 二进制无法启动 PG 15 数据文件,直接initdb会覆盖旧数据。这种情况请用pg_upgrade或 dump/restore 迁移。
三样齐了,重启飞牛相册即可。
两个小尾巴:
- 如果之前
initdb跑了一半留下半套数据目录,重启会报directory is not empty。把/var/apps/trim.photos/meta/data/pgvector/清空再重试(里面只有sock/,删了无损失)。 - 残留的
postgresql-15-pgvector包已经没用了,顺手清掉:sudo apt purge postgresql-15-pgvector。
五、教训:你知道要升级 PG,但不知道谁会因此挂掉
升级本身没问题,翻车点在后面那步 apt purge——PG 15 没了,飞牛相册却还指着它的路径。
几点反思:
1. 升级 PG 可以,但别急着删旧版
apt upgrade 只装了 PG 18,PG 15 还留着,两者并存本来没问题。是我后续 apt purge 清掉了 PG 15 二进制,才让飞牛相册的硬编码路径全变成死链接。
2. 依赖特定 PG 版本的应用,必须保留旧版
对于闭源应用,要么:
- 保留旧版 PG 包不卸载(多版本并存)
- 或者在清旧版后像本文一样手动桥接
3. purge 旧软件包前,确认有没有下游还在用它
# 看看哪些二进制还硬编码了旧路径
strings /path/to/binary | grep "postgresql/15"
NAS 上的闭源应用尤其脆弱——它们不会因为你升级了系统服务就自动适配。
六、同样的坑可能怎么踩
任何依赖特定 PG 版本的 NAS 应用都可能遇到:
- 飞牛相册 → pgvector + 硬编码 PG 15 路径
- 其他 NAS 应用(监控、文档管理)如使用 PG 15,同样会炸
- Docker 里跑的应用除外——它们在容器内有自己独立的 PG
如果 pgdg 仓库里没有对应新版的扩展包怎么办?
自己编译 pgvector:
git clone https://github.com/pgvector/pgvector.git
cd pgvector
# 必须指定 PG 18 的 pg_config,否则会装到系统默认 PG 的 lib 目录
sudo make PG_CONFIG=/usr/lib/postgresql/18/bin/pg_config install
一句话总结:apt upgrade 之前,先把下游应用对系统库的隐藏依赖摸一遍——尤其是闭源二进制里硬编码的那些路径。
本文链接:apt upgrade 之后,飞牛相册挂了:PG 15 到 18 的血泪迁移 - https://h89.cn/archives/629.html
版权声明:原创文章 遵循 CC 4.0 BY-SA 版权协议,转载请附上原文链接和本声明。