背景

在系统从 Ubuntu 22.04 升级至 24.04 后,一个长期运行的 Anki Sync Server 服务无法启动。该服务基于 Python 虚拟环境(venv)运行,并通过 systemd 管理。升级完成后,systemd 显示服务反复启动失败。

本文记录一次完整的排查与修复过程,重点在于 Python 虚拟环境在系统升级后发生版本断代 的问题,以及如何在不影响业务数据的前提下,安全、可回溯地恢复服务。

本文为工程记录,已严格脱敏,不包含路径、主机名、账号或端口等可识别信息。


一、故障现象

systemd 服务状态显示:

  • 服务启动后立即退出(exit-code 1)
  • 多次重启触发 Start request repeated too quickly

手动执行启动脚本时,出现错误:

ModuleNotFoundError: No module named 'anki'

这表明 Python 运行环境无法找到 anki 模块。


二、初步检查:虚拟环境异常

检查虚拟环境中的 Python 解释器信息:

  • 当前执行的 Python 版本为 Python 3.12(系统自带)
  • sys.path 指向 /usr/lib/python3.12
  • 虚拟环境内无法使用 pip

进一步检查虚拟环境目录结构后发现:

  • site-packages 实际位于 lib/python3.10/
  • 其中包含完整的 anki

即:

venv 中保留的是 Python 3.10 时期的库,而解释器已经切换到 Python 3.12

这是一次典型的 虚拟环境断代问题

  • 系统升级导致 Python 主版本变化
  • 旧 venv 未被重新创建
  • 解释器与库路径不再匹配

三、修复策略选择

核心原则

  • 不修改、不迁移业务数据目录
  • 将虚拟环境视为“可丢弃的运行层”
  • 修复过程必须可回溯

策略

  • 旧虚拟环境完整归档(按目录自身时间戳命名)
  • 在原目录原地重建 venv
  • 重新安装 Anki 运行依赖

四、旧虚拟环境归档

原有虚拟环境目录包含:

  • bin/
  • include/
  • lib/
  • pyvenv.cfg

将其整体移动到统一归档目录,例如:

old_version.YYYYMMDD/

归档后目录结构示意:

Anki/
├─ anki.sh
├─ data/
├─ bin/
├─ lib/
├─ include/
├─ pyvenv.cfg
└─ old_version.YYYYMMDD/
   ├─ bin.YYYYMMDD/
   ├─ lib.YYYYMMDD/
   ├─ include.YYYYMMDD/
   └─ pyvenv.cfg.YYYYMMDD

这种方式同时满足:

  • 历史可追溯
  • 新旧环境完全隔离
  • 目录本身时间即为语义信息

五、原地重建虚拟环境

在原目录直接创建新的 Python 虚拟环境:

python3 -m venv .

随后升级基础工具链并安装 Anki:

./bin/python -m pip install -U pip setuptools wheel
./bin/python -m pip install anki

验证模块可用:

./bin/python -c "import anki"

至此,Python 运行层恢复正常。


六、Sync Server 启动失败的第二个原因

在验证 anki.syncserver 时,出现新提示:

No users defined; SYNC_USER1 env var should be set

这是 新版本 Anki Sync Server 的正常行为

  • 服务启动前必须通过环境变量定义至少一个同步用户

该问题并非异常,而是由于直接运行模块测试时未加载启动脚本中的环境变量。


七、验证启动脚本

通过启动脚本运行服务后,日志显示:

INFO listening addr=HOST:PORT

说明:

  • 虚拟环境正常
  • Anki Sync Server 成功监听
  • 用户配置与数据目录加载无误

八、交回 systemd 管理

在确认脚本可正常前台运行后,仅需:

  • 重载 systemd 配置
  • 重启原有服务

服务状态恢复为:

Active: active (running)

整个修复过程中:

  • systemd service 文件未被重写
  • 数据目录未发生任何变化

九、经验总结

  1. Python 虚拟环境在系统升级后极易断代
  2. venv 的官方定位就是:可删除、可重建的运行层
  3. 业务数据与运行环境必须严格分离
  4. 出现模块缺失问题时,应首先核对解释器与 site-packages 的版本一致性
  5. 归档旧环境比“修补旧环境”更安全、更可维护

结语

本次问题的本质并不复杂,但如果误判为“依赖缺失”或“配置错误”,容易在旧环境中反复打补丁,反而增加不确定性。

通过 归档 → 原地重建 → 手动验证 → 交回 systemd 的流程,可以在最小风险下恢复服务,同时保留完整历史,为后续系统升级提供清晰参考。

Leave a Reply

Your email address will not be published. Required fields are marked *