Debian 12 装不上 tmux:一次被”未来版” libtinfo6 卡住的依赖死锁排查
在 Debian 12 (bookworm) 上想装个 tmux,结果 apt-get install tmux 直接报了一串依赖冲突,绕了好几个弯才解决。把整个坑和最终解法记下来,给后面踩同样坑的人参考。
📑 目录
一、现象:一装就报”破坏依赖”
$ apt-get install tmux 正在读取软件包列表... 完成 正在分析软件包的依赖关系树... 完成 正在读取状态信息... 完成 有一些软件包无法被安装。... 下列软件包有未满足的依赖关系: libtinfo6 : 破坏: tmux (< 3.3a-4) 但是 3.3a-3 正要被安装 E: 无法修正错误,因为您要求某些软件包保持现状,就是它们破坏了软件包间的依赖关系。
乍一看像是”系统无法达到您要求的状态”(Debian unstable 常见提示),但其实是另一回事。
二、定位:libtinfo6 是从”未来”装来的
先查 libtinfo6 到底装的是哪个版本:
$ dpkg -l libtinfo6 && apt-cache policy libtinfo6
ii libtinfo6:amd64 6.6+20251231-1+b1 amd64 shared low-level terminfo library
libtinfo6:
已安装:6.6+20251231-1+b1
候选: 6.6+20251231-1+b1
版本列表:
*** 6.6+20251231-1+b1 100
100 /var/lib/dpkg/status
6.4-4 500
500 http://deb.debian.org/debian bookworm/main amd64 Packages
关键信息有两点:
- 版本号
6.6+20251231-1+b1—— 日期戳是 2025-12-31,这显然是 testing/trixie 时代构建的新包,不属于 bookworm。 - 它的优先级是
100 /var/lib/dpkg/status,也就是本地 dpkg 状态里登记的手动包,而不是从源候选进来的。说明之前有人(或某次操作)手动dpkg -i或从一个临时源把它拉进来了。
矛盾点:bookworm 自带的 tmux 3.3a-3 明确写了 Breaks: libtinfo6 (>= 新版),它只能配旧版 6.4;而系统里被手动顶成了 6.6。两边对不上。
三、绕一圈才发现:系统里混了一整批”跨版本”的包
试着把 libtinfo6 单独降回 bookworm 的 6.4-4,又报 ncurses-bin 要求 libtinfo6 >= 6.6,形成循环依赖。再试着降级,apt 提示要连带卸载 45 个包(包括 python3、openssh-server、cmake、google-chrome、libncursesw6 等),根本不能这么干。
真正的问题是:这台机器上混装了一整批非 bookworm 来源的包(systemd、openssh、libtinfo、ncurses、coreutils 等来自 testing/trixie 的构建),它们互相咬住,跟 bookworm 的 tmux 依赖链彻底对不上。
把所有”非 bookworm”的包揪出来(注意 dpkg -l 里带 bpo 或异常日期戳的版本):
$ dpkg -l | grep -Ei 'bpo|20251|~rc' ii e2fsprogs 1.47.2-3~bpo12+1 amd64 ext2/ext3/ext4 file system utilities ii iproute2 6.15.0-1~bpo12+1 amd64 networking and traffic control tools ii libbpf1:amd64 1:1.4.6-1~bpo12+1 amd64 eBPF helper library ii libelf1:amd64 0.192-4~bpo12+1 amd64 library to read and write ELF files ii libext2fs2:amd64 1.47.2-3~bpo12+1 amd64 ext2/ext3/ext4 file system libraries ii libsystemd-shared:amd64 254.26-1~bpo12+1 amd64 systemd shared private library ii libsystemd0:amd64 254.26-1~bpo12+1 amd64 systemd utility library ii libudev1:amd64 254.26-1~bpo12+1 amd64 libudev shared library ii openssh-client 1:10.0p1-7~bpo12+1 amd64 secure shell (SSH) client rc openssh-server 1:10.0p1-7~bpo12+1 amd64 secure shell (SSH) server ii openssh-sftp-server 1:10.0p1-7~bpo12+1 amd64 sftp server module ii systemd 254.26-1~bpo12+1 amd64 system and service manager ii systemd-sysv 254.26-1~bpo12+1 amd64 system and service manager - SysV compatibility ii sysv-rc 3.08-3~bpo12+2 all System-V-like runlevel change mechanism ii udev 254.26-1~bpo12+1 amd64 /dev/ and hotplug management daemon # 另外还有 coreutils 9.10-1、libncursesw6 6.6 等,比 bookworm 更新
rc 状态:openssh-server 显示为 rc(已卸但配置文件保留),说明之前被删过一次又试图装回来,这也是依赖混乱的佐证之一。结论:得把这整批包一次性降回 bookworm 原生版本,依赖链才能对齐。
四、正确姿势:逐个查可用版本,别瞎猜版本号
很多人(包括一开始的我)直接凭记忆写版本号,结果 apt-cache policy 一看,本地压根没那个版本。正确做法是先查再写:
$ apt-cache policy coreutils e2fsprogs iproute2 libbpf1 libelf1 libext2fs2 sysv-rc
# 每个包会列出「已安装 / 候选 / 版本列表」,抄 bookworm 源里(优先级 500)那一行的版本号
# 例如:
e2fsprogs:
已安装:1.47.2-3~bpo12+1
候选: 1.47.2-3~bpo12+1
版本列表:
*** 1.47.2-3~bpo12+1 100
100 /var/lib/dpkg/status
1.47.0-2+b2 500
500 http://deb.debian.org/debian bookworm/main amd64 Packages
↑ 这就是要写的版本号:1.47.0-2+b2
确认好每个包在 bookworm main 源里的精确版本后,拼一条降级命令:
$ apt-get install -y --allow-downgrades \
coreutils=9.1-1 \
e2fsprogs=1.47.0-2+b2 \
libext2fs2=1.47.0-2+b2 \
iproute2=6.1.0-3 \
libbpf1=1:1.1.2-0+deb12u1 \
libelf1=0.188-2.1 \
openssh-client=1:9.2p1-2+deb12u10 \
openssh-sftp-server=1:9.2p1-2+deb12u10 \
openssh-server=1:9.2p1-2+deb12u10 \
systemd=252.39-1~deb12u2 \
systemd-sysv=252.39-1~deb12u2 \
libsystemd-shared=252.39-1~deb12u2 \
libsystemd0=252.39-1~deb12u2 \
libudev1=252.39-1~deb12u2 \
udev=252.39-1~deb12u2
要点:
--allow-downgrades是必须的,否则 apt 拒绝降级。- 配套包要一起写全:
e2fsprogs和libext2fs2是配套的两个包,只降一个会卡在「预依赖 libext2fs2 (= 1.47.0-2+b2) 但 1.47.2 正要被安装」。 coreutils这种核心工具降级前先确认有别的救援手段(云控制台 VNC / 其他环境),因为ls/cp/mv/rm会被替换,中途失败可能影响系统。- openssh 要client / server / sftp-server 三个一起降到同一个
9.2p1-2+deb12u10,版本不一致就又咬上了。
五、收尾:重启服务 + 验证
# 重启 SSH(刚才卸过 openssh-server,确认能起来)
$ systemctl restart ssh && systemctl status ssh | head -5
● ssh.service - OpenBSD Secure Shell server
Loaded: loaded (/lib/systemd/system/ssh.service; enabled; preset: enabled)
Active: active (running) since Sun 2026-10-25 17:47:31 CST; 26ms ago
# 验证 tmux 和 python3 都在
$ tmux -V
tmux 3.3a
$ which python3
/usr/bin/python3
SSH 服务恢复 active (running),tmux 3.3a 正常,基础工具链也回来了。
六、一句话复盘
这次折腾的根源不是 tmux 本身,而是系统里混入了跨版本(testing/trixie 构建)的 libtinfo6、ncurses、systemd、openssh 等一大批包,它们和 bookworm 的依赖矩阵对不上。
给后面人的三条铁律:
- 别跨版本手动装包:同一台机器上不要一会儿 bookworm、一会儿从 testing/trixie 拉包,混装必炸。临时需要新包,用
virtualenv/docker隔离,别往系统里塞。 - 动手前先
apt-cache policy <pkg>查可用版本,按源里真实存在的精确版本号写,别凭记忆。 - 降级要成组:把”被污染的整批包”列全(
dpkg -l | grep -Ei 'bpo|20251|~rc'),一条命令统一降回原生版本,配--allow-downgrades,并保证配套包(server/client、e2fsprogs/libext2fs2)版本一致。
七、快速排查命令速查表
下次再遇到”装了个包却报破坏依赖 / 依赖对不上”,按这张表从上往下查,基本能定位是不是混版本包。
1. 先看依赖冲突到底卡在哪
# 模拟安装,不真正装,看会牵连哪些包 / 报什么冲突 apt-get -s install tmux # 查某个包的依赖关系(谁需要它、它需要什么、谁破坏它) apt-cache depends tmux apt-cache showpkg tmux # 反向:哪些包依赖 tmux
2. 揪出”非本版本”的包(关键一步)
# 列出所有带 bpo / 异常日期戳 / rc 的包
dpkg -l | grep -Ei 'bpo|2025|2024|~rc'
# 或更精准:找出版本号里带「未来日期」或「rc/rc4」的
dpkg -l | awk '{print $1,$2,$3}' | grep -E '20[0-9]{4}|rc'
# 反查某个包在源里到底有哪些版本(哪一行是 bookworm 原生 500 优先级)
apt-cache policy libtinfo6
3. 确认某包”哪来的”
# 包的安装/移除历史(看是不是手动 dpkg -i 或临时源拉的) grep 'libtinfo6' /var/log/dpkg.log | tail -20 # 本地是否残留手动装的 deb 文件 find /var/cache/apt/archives/ /tmp /root -name 'libtinfo*.deb' 2>/dev/null
4. 成组降级前,先把可用版本号抄齐
# 一次查全,抄「bookworm/main 那行(优先级 500)」的版本号
apt-cache policy coreutils e2fsprogs iproute2 libbpf1 libelf1 \
libext2fs2 openssh-client openssh-server systemd
5. 一条命令成组降回原生版本
# 用第 4 步抄到的版本号拼成一条;--allow-downgrades 必带
apt-get install -y --allow-downgrades \
coreutils=9.1-1 \
e2fsprogs=1.47.0-2+b2 \
libext2fs2=1.47.0-2+b2 \
iproute2=6.1.0-3 \
openssh-client=1:9.2p1-2+deb12u10 \
openssh-server=1:9.2p1-2+deb12u10 \
openssh-sftp-server=1:9.2p1-2+deb12u10 \
systemd=252.39-1~deb12u2
# 配套包(server/client、e2fsprogs/libext2fs2)务必同一批、版本一致
6. 收尾验证
# 依赖是否还有未解决的 apt-get check # 关键服务 / 工具能不能正常跑 systemctl restart ssh && systemctl status ssh | head -3 tmux -V which python3
排查口诀(五步法)
apt-get -s install模拟看冲突dpkg -l | grep -Ei 'bpo|20[0-9]{4}'揪混版本包apt-cache policy抄原生版本号apt-get install --allow-downgrades成组降回apt-get check+ 重启服务验证
全程别跨版本手动塞包,需要新特性就用 docker / virtualenv 隔离。