总结一下:如果 apt-get 检测到错误(例如,找不到源列表中的 repo),它就会崩溃。
导致该问题的原因在于 pythonsqlite3
共享对象具有未定义的符号 ( sqlite3_deserialize
)。可以从 中重现此问题python3 -c 'import sqlite3'
。
不幸的是,由于 aptitude 依赖于 python3,任何故障都可能导致 pythonCommandNotFound
功能尝试import sqlite3
崩溃(相关日志如下)。
在撰写本文时,似乎唯一可用的 python 包是 3.11.2-1,所以我无法升级/降级。
有问题的共享对象是/usr/lib/python3.11/lib-dynload/_sqlite3.cpython-311-x86_64-linux-gnu.so
。
apt-file 表明该文件是libpython3.11-stdlib
软件包的一部分。
我在网上没有看到任何关于此事的结论,所以也许我做错了什么,但我想象不出是什么。有没有人运行过 lunar 来验证这一点?
谢谢
sudo apt-get update
Hit:1 http://gb.archive.ubuntu.com/ubuntu lunar InRelease
Hit:2 http://gb.archive.ubuntu.com/ubuntu lunar-updates InRelease
Hit:3 http://gb.archive.ubuntu.com/ubuntu lunar-backports InRelease
Hit:4 http://gb.archive.ubuntu.com/ubuntu lunar-security InRelease
Traceback (most recent call last):
File "/usr/lib/cnf-update-db", line 9, in <module>
from CommandNotFound.db.creator import DbCreator
File "/usr/lib/python3/dist-packages/CommandNotFound/db/creator.py", line 7, in <module>
import sqlite3
File "/usr/lib/python3.11/sqlite3/__init__.py", line 57, in <module>
from sqlite3.dbapi2 import *
File "/usr/lib/python3.11/sqlite3/dbapi2.py", line 27, in <module>
from _sqlite3 import *
ImportError: /usr/lib/python3.11/lib-dynload/_sqlite3.cpython-311-x86_64-linux-gnu.so: undefined symbol: sqlite3_deserialize
Reading package lists... Done
E: Problem executing scripts APT::Update::Post-Invoke-Success 'if /usr/bin/test -w /var/lib/command-not-found/ -a -e /usr/lib/cnf-update-db; then /usr/lib/cnf-update-db > /dev/null; fi'
E: Sub-process returned an error code
答案1
本质上,这个问题是操作员错误。感谢steeldriver 向我指出了原因。以下是为遇到此问题的其他人员提供的解释:
正如steeldriver指出的那样,python3没有找到正确的共享对象,而是从我无意中添加的另一个安装中加载了一个共享对象。
在这种情况下,错误消息指向缺少的符号:sqlite3_deserialize
共享对象所需的(函数)/usr/lib/python3.11/lib-dynload/_sqlite3.cpython-311-x86_64-linux-gnu.so
错误不在于该共享对象,而在于它加载的共享对象都不包含该符号。
使用nm
命令我们可以看到库中存在的所有符号以及它需要的符号。需要的符号标记为U
。
nm -gD /usr/lib/python3.11/lib-dynload/_sqlite3.cpython-311-x86_64-linux-gnu.so | less
如果我们搜索反序列化,我们可以看到U sqlite3_deserialize
它需要这个符号。
使用ldd
我们可以命令 linux 加载器实际加载该库及其所有依赖库并找出实际正在加载的库:
ldd /usr/lib/python3.11/lib-dynload/_sqlite3.cpython-311-x86_64-linux-gnu.so
正如steeldriver指出的那样,它加载的/usr/local/lib/libsqlite3.so.0
版本不正确。nm
在错误的文件上运行显示该文件中不存在所需的符号,这就是问题的原因。
lunar 中正确的 sqlite3 包是libsqlite3-0
(这并不明显)。如果不确定,我们可以尝试从apt-cache search libsqlite3
或类似的东西中找到正确的包,然后筛选结果。
我们可以通过先安装然后运行来查看此包安装了哪些文件dpkg -L libsqlite3-0
。在返回的文件列表中,我们可以看到/usr/lib/x86_64-linux-gnu/libsqlite3.so.0
应该加载哪个文件。
那么我们如何确保 Linux 加载程序选择正确的共享对象版本?理想情况下,我们应该只有一个版本的 sqlite3,因此最好的解决方案是删除非标准版本。另一个潜在的解决方案是使用环境变量将加载程序指向正确的路径LD_LIBRARY_PATH
。类似这样的方法可能会有效export LD_LIBRARY_PATH=/usr/lib/x86_64-linux-gnu:$LD_LIBRARY_PATH
(添加到~/.bashrc
持久性)。请注意,将其放在前面会导致首先搜索该目录。如果问题仍然存在,只需ldd
再次运行以验证正在加载的内容。