这也算是用deb包管理系统的发行版会遇到的一个常见的问题。我就来介绍一下这个问题的成因以及应对方法。不想看细节的可以直接跳到最后的总结部分
===== 成因 =====
首先考虑一个场景:
有一个软件包中,包含了若干文件。如果我对其中的配置文件进行过了修改,我肯定是不希望今后在软件升级/重装时,用软件包里的初始配置文件不声不响地覆盖掉我改过的配置文件的。但对于软件包中的其他文件,我又是希望能够自动覆盖的。
这样一来,在deb包管理系统的设计中,自然会把软件包中要安装的文件分成两类:配置文件和非配置文件。接触过deb打包/解包的人,可能会知道包中有一个conffiles元文件,这个文件就是用来记录哪些文件是属于配置文件的。可以在/var/lib/dpkg/info下面看到系统上已经安装了的软件包的这个配置文件列表,文件名是“软件包名.conffiles”或“软件包名:架构名.conffiles”。不过,就算没有这个conffiles文件,安装到/etc下面的文件也都会被默认视作配置文件。
这就是删除了/etc下面的配置文件后,再次用apt install --reinstall xxx不会恢复的原因:不会覆盖被修改过的配置文件(删除也是一种修改)。
也许你会觉得把删除文件视作修改而不是文件缺失有点傻,但这也是有一定道理的:软件包中的配置文件可能包含打包人员定制优化后的设置,而非软件开发者的默认设置。如果要想体验默认设置下原汁原味的软件,只需要删一次配置文件即可。
===== 应对 =====
dpkg有一个参数--force-confmiss,可以在安装软件包时将被删除的配置文件视为缺失而非已修改。
代码: 全选
sudo dpkg -i --force-confmiss XXX.deb
代码: 全选
sudo apt -o Dpkg::Options::=--force-confmiss install --reinstall XXX
sudo apt-get -o Dpkg::Options::=--force-confmiss install --reinstall XXX
sudo aptitude install -o Dpkg::Options::=--force-confmiss XXX
代码: 全选
dpkg-query -S 文件名
===== 关于 ucf =====
如果你看了上面的内容,兴冲冲用dpkg-query -S smb.conf去找哪个包里包含了/etc/samba/smb.conf文件,会发现不存在这样的包。
这是因为samba的配置文件是交由ucf(Update Configuration Files)来管理的。用ucf的好处在于,它不是无脑认为被改过的旧配置文件就不能动,而是会向用户询问是保留改动过的配置还是换用软件包里的原生配置,而且还可以对比新旧文件之间的差异让用户更好决策。
可以在/var/lib/dpkg/info/samba-common.postinst中看到这样的代码
代码: 全选
CONFIG=/etc/samba/smb.conf
.....
ucf --three-way --debconf-ok /usr/share/samba/smb.conf "$CONFIG"
代码: 全选
UCF_FORCE_CONFFMISS=1
代码: 全选
ucfq /etc/samba/smb.conf
代码: 全选
grep smb /var/lib/ucf/registry
===== 复盘 =====
看了上面的内容,就能分析出那个帖子里的其他人给的命令为什么没有用了
单纯的install --reinstall并不会恢复已被删除的配置文件
smb.conf是由samba-common包提供的,仅仅彻底删除并重装samba包并不会影响samba-common包。
这也是新人常常弄不清楚的事:如果包A依赖包B,那么安装包A时,包B也会自动被一并安装;但删除包A时,包B并不会被一并删除。A需要B,没有B的话A也活不下去,但B并不需要A,就算没有A,B自个儿也能活。
要删除那些被自动安装上的依赖包,可以使用autoremove机制:给apt/apt-get的remove/purge子命令添加--auto-remove参数或者在删除后用autoremove子命令
代码: 全选
apt purge --auto-remove samba
或者
apt purge samba
apt autoremove --purge
可以用
代码: 全选
apt-mark auto 软件包名
===== 总结 =====
综合一下上面的内容,可以得到以下安装软件包恢复缺失配置文件的命令
代码: 全选
sudo UCF_FORCE_CONFFMISS=1 dpkg -i --force-confmiss 软件包文件名.deb
sudo UCF_FORCE_CONFFMISS=1 apt -o Dpkg::Options::=--force-confmiss install --reinstall 软件包名
sudo UCF_FORCE_CONFFMISS=1 apt-get -o Dpkg::Options::=--force-confmiss install --reinstall 软件包名
sudo UCF_FORCE_CONFFMISS=1 aptitude install -o Dpkg::Options::=--force-confmiss 软件包名
代码: 全选
dpkg-query -S 文件名
grep 文件名 /var/lib/ucf/registry