Debian 12 装不上 tmux:一次被”未来版”libtinfo6 卡住的依赖死锁排查记录

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 的依赖矩阵对不上。

给后面人的三条铁律:

  1. 别跨版本手动装包:同一台机器上不要一会儿 bookworm、一会儿从 testing/trixie 拉包,混装必炸。临时需要新包,用 virtualenv / docker 隔离,别往系统里塞。
  2. 动手前先 apt-cache policy <pkg> 查可用版本,按源里真实存在的精确版本号写,别凭记忆。
  3. 降级要成组:把”被污染的整批包”列全(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

排查口诀(五步法)

  1. apt-get -s install 模拟看冲突
  2. dpkg -l | grep -Ei 'bpo|20[0-9]{4}' 揪混版本包
  3. apt-cache policy 抄原生版本号
  4. apt-get install --allow-downgrades 成组降回
  5. apt-get check + 重启服务验证

全程别跨版本手动塞包,需要新特性就用 docker / virtualenv 隔离。

发布者

ChiuYut

咦? 我是谁? 这是什么地方? Ya ha! 我是ChiuYut! 这里是我的小破站!