拖了半年的 Ubuntu → Debian 迁移,AI 用 40 分钟帮我做完了

背景

我家有两台 PVE 服务器。一台 r86s 小主机跑 Home Assistant,一台主力机跑 TrueNAS、Windows 虚拟机、Docker 服务和 qBittorrent。

qBittorrent 那个 LXC 容器隔三差五 OOM,严重的时候连宿主机都一起拉下水。我早就想把它从 Ubuntu 22.04 重装成 Debian 12——更干净、更轻量、不用再操心 PPA 源的问题。但这件事涉及备份种子数据、重建容器、配置 NFS 挂载、调 systemd 依赖……每次想动手都觉得麻烦,一拖就是半年。

直到上周,r86s 又 OOM 了一次,整台物理机直接重启,服务全断。我决定让 AI 来处理这件事。

诊断过程

我给了 AI 一句话:"这台机器经常莫名其妙关机,前两天整台物理机 OOM 服务全断了,帮我看看。"

它 SSH 进 r86s,花了大概两分钟就定位了根因:

  • 物理机总共 7.5GB 内存,0 Swap
  • VM 106(Home Assistant OS)配了 4GB 固定内存,balloon: 0
  • 加上 PVE 自身服务和三个 LXC 容器,总分配 ~7.1GB
  • 剩余 ~500MB,任何波动都会触发 OOM killer

它翻了 7 天的 journalctl 日志,找到两次 OOM 记录(4/12 和 4/16),确认每次都是内核杀掉 VM 106 的 KVM 进程。然后它又 SSH 进 HAOS 内部,通过 ha core stats/proc/meminfo 发现 HA 实际只用了 ~1.25GB,剩下全是 Linux 磁盘缓存。

结论很清楚:4GB 分配完全没必要,2GB 绰绰有余。

宿主机可用内存: 修改前 ~1.5GB → 修改后 ~4.1GB
VM 106 内存: 4096MB → 2048MB (balloon: 1024)
CT 105 xray: 512MB → 128MB (实际用 48MB)
CT 111 truenas-iot: 512MB → 128MB (实际用 22MB)

从发出指令到 r86s 的 OOM 问题彻底解决,不到 10 分钟。

qBittorrent:真正的麻烦

r86s 修完,我顺便让它看看主力 PVE 上的 qBittorrent 容器。这才是我真正头疼的东西。

它查到了容器内部的 OOM 记录——2 月到 3 月之间,qBittorrent 被 cgroup OOM killer 杀了四次,还有两次 SEGV 崩溃。根因是:

  1. 加载了 544 个种子,且 QueueingSystemEnabled=false——所有种子可同时活跃
  2. Preallocation=true,在 NFS 挂载上预分配大文件,内存开销巨大
  3. qBittorrent v4.5.5,libtorrent 有已知的内存管理问题
  4. 容器分了 8GB 内存,然而 qBittorrent 自己就能吃满

我说:"要不你帮我重装成 Debian 顺便升级 qB 吧,这事我拖了半年了。"

40 分钟,从备份到上线

接下来发生的事情让我意识到,这个世界真的变了。

AI 的执行流程:

第一步:备份。 把 qBittorrent 的配置、544 个种子的 BT_backup、RSS feeds、VueTorrent UI、NFS fstab、systemd service、nftables 规则全部打包成 qb-backup-20260417.tar.gz(80MB),传到 PVE 宿主机的 /root/backups/

第二步:销毁重建。 停掉旧的 Ubuntu 22.04 容器,pct destroy 销毁,然后用 Debian 12 模板重新 pct create。保持相同的 CTID(10023)、MAC 地址(保证 DHCP 分配到同一个 IP)、NFS 挂载特性。内存从 8GB 降到 4GB(后来又降到 2GB)。

第三步:安装。 Debian 12 默认仓库的 qBittorrent 只有 4.5.2,太旧。它查了 GitHub releases,直接下载了 userdocs/qbittorrent-nox-static 的 v5.1.4 静态二进制。没有 PPA,没有依赖,一个文件解决。

第四步:恢复数据。 把备份包 push 进新容器,解压恢复。所有种子、配置、UI 主题原样还原。

第五步:配置优化。 这一步是关键——它不只是"恢复原样",而是修掉了导致 OOM 的配置:

Session\Preallocation=false          # 关闭 NFS 上的文件预分配
Session\QueueingSystemEnabled=true   # 启用队列系统
Session\MaxActiveDownloads=5         # 最多同时下载 5 个
Session\MaxActiveTorrents=20         # 最多 20 个活跃种子
Session\MaxActiveUploads=15          # 最多 15 个上传
Session\DiskCacheSize=256            # 磁盘缓存上限 256MB

第六步:NFS 依赖链。 我提醒它 TrueNAS 有时候启动很慢,NFS 还没挂载 qB 就会启动,导致文件下载进容器本地磁盘。它把 check-nfs-mount.service 设为 Requires 前置依赖,检查脚本最多等 150 秒。

第七步:SSH 密钥。 新容器的 SSH host key 变了,它自动清理了 known_hosts,找到 SSH config 里对应的 id_ed25519_pve-universal 密钥,注入到新容器的 authorized_keys

最终状态:

系统: Debian 12 (bookworm)
qBittorrent: v5.1.4 (从 v4.5.5 升级)
种子: 544 个全部恢复
内存: 实际使用 124MB / 分配 2GB
NFS: 4 个挂载点正常
WebUI: HTTP 200, VueTorrent 正常
SSH: ssh pve-qbittorrent 直连正常

感受

从我说"帮我重装"到所有东西验证通过,大约 40 分钟。这里面包含备份、销毁、重建、安装、恢复、优化、调试 SSH 密钥问题。

如果是我自己做,首先我得回忆 qBittorrent 的数据目录在哪、哪些文件需要备份,然后对着 Debian wiki 查 NFS 配置,再去 GitHub 找静态二进制的下载链接,调 systemd 的依赖顺序……保守估计一下午,还不算中间被打断的时间。这就是为什么我拖了半年。

不是懒,是那种"知道怎么做但就是不想花时间做"的事情。步骤不难,但繁琐。而繁琐的事情最容易拖延。

AI 不会觉得繁琐。它查日志、写配置、调依赖,每一步都是确定性的执行。它不会中途去刷 Reddit,不会因为一个 SSH 密钥问题就烦躁地关掉终端明天再说。它只是继续执行下一步。

这才是 AI 对我而言最大的价值——不是它能做我做不到的事,而是它能帮我做掉那些我一直"以后再说"的事。

半年的拖延,40 分钟结束。