恢复 dpkg info 目录

事情是这样的, 大概去年 11 或者 12 月份的时候, 忘记在折腾啥东西, 看到网上说要把 /var/lib/dpkg/info 里的东西备份一下, 然后什么什么的, 之后他还提了一句, 就算把 info 里的东西全删了也完全不影响系统, 于是, 我一个手贱, 删了…… 虽然说平常用着确实没有大的影响, 但是, 每次装包 dpkg 都会给一万个 warning. 终于, 我受不了了, 开始解决这个烦人的东西.

一开始我是一头雾水的, dpkg 明明知道我安装了什么, 为啥安装其他包的时候, 他要说我没有安装? 后来发现, 这玩意直接查 info 文件夹里有没有安装过的包的信息. 那自然, 我都给删了, 肯定没有了… 我的期望是, 既然你知道我装了什么, 那肯定能恢复我的信息吧? 结果搜了半天, 答案是, 不能. info 里保存了包的安装信息:

  • .conffiles 记录了软件包的配置文件列表
  • .list 保存软件包中的文件列表, 用户可以从 .list 的信息中找到软件包中文件的具体安装位置.
  • .md5sums 记录了软件包的 md5 信息, 这个信息是用来进行包验证的.
  • .prerm 脚本在 Debian 报解包之前运行, 主要作用是停止作用于即将升级的软件包的服务, 直到软件包安装或升级完成.
  • .postinst 脚本是完成 Debian 包解开之后的配置工作, 通常用于执行所安装软件包相关命令和服务重新启动.

这么重要的信息, 你和我说删了也没关系??? CSDN 真完全不能信了 (我原来以为只是良莠不齐, 仔细筛是能够筛出好东西的, 现在想想, 算了, 涉及到 “删除” 的操作, 除了官方文档, 任何说法都保持怀疑态度好了)…

那到这里, 也能够想得到, 解决问题的唯一方式, 就是重装. 啊不是重装系统, 是重装所有包.

在奇奇怪怪的地方, 找到了 14 年前的帖子(啊看来很久以前就有和我一样蠢的人了…), 里面有一段简单一点的 shell 代码能够执行这个操作.

1
2
3
for package in $(apt-get upgrade 2>&1 | grep "warning: files list file for package '" | grep -Po "[^'\n ]+'" | grep -Po "[^']+"); do
    apt-get install --reinstall "$package";
done

apt-get upgrade 会显示 dpkg 的 warning, 将 stderr 输出到 stdout, 然后一番 grep, 得到包名, 重装.

在等待数小时以后, 终于重一万条警告变成几十条了.

剩下这些警告, 还是因为没有重新安装成功导致的. 尝试手动解决问题.

经过一系列的试探, 发现有这样几个问题:

仓库里找不到包.

比如自己下 .deb 装的东西, 这些就再去找到 .deb 文件然后装一下就解决了.

访问不到仓库.

多半是因为仓库被墙了, 挂个代理重装就行.

重装还是有警告

原因不明, 有些换成 apt 再装就好了.

其他

剩下十几个无论怎么搞也解决不了警告. 之后, 我索性卸载重装, 而不是加选项 --reinstall. 果然解决了问题. 不过需要注意, 卸载的时候, 无论是 dpkg -r 还是 apt pruge 或者 apt-get pruge, 你看起来他好像卸载了, 实际上, 他啥都没删, 所有文件都在原来的位置躺得好好的, 这些软件也可以运行. 重装一遍, 再卸载, 这时才会成功卸载.

需要注意的是, shell 脚本里获得警告的那个 apt-get 不能换成 apt, 因为 apt 输出的不是纯文本, 带有颜色和字体格式, 后面的那些 grep 就抓不到包名了. 再一个就是用 aptitude reinstall 重装成功了也不能消除 dpkg 的警告.

终于修好了… 累死了… 教训就是, 不要乱删东西.