在这个问题我描述了查找安装命令最终目标的包时遇到的问题/usr/bin/rename
。dpkg -S /usr/bin/rename
没有给出结果,但在第一次发现那是一个链接后,我找到了一个通用的解决方案。
既然/usr/bin/rename
指向/etc/alternatives/rename
我知道如何这特定链接由 管理update-alternatives
。
如果我没有这种知识,我如何找出哪个包实际安装了符号链接?如果没有简单的命令来执行此操作,那么找出哪个命令设置了符号链接的一般策略是什么?
答案1
dpkg -S
无法告诉您哪个包安装了符号链接,因为它只查看从包中解压的文件。此信息由*.list
中的文件提供/var/lib/dpkg/info/*.list
。
Debian 系统上的每个文件只能由一个软件包拥有。如果您尝试安装的软件包包含另一个软件包已提供的文件,则会发生以下情况之一:
dpkg
将拒绝安装第二个包。dpkg
将在安装第二个包之前删除第一个包(如果第二个包指定与第一个包的Breaks
或关系)。Conflicts
dpkg
将第一个包升级到较新版本,该版本在安装第二个包之前不再提供该文件(如果第二个包指定了 /Conflicts
以及Breaks
与Replaces
第一个包的关系)。dpkg
将与第一个包一起安装第二个包,并用第二个包提供的文件覆盖该文件(如果第二个包指定Replaces
与第一个包的关系)。
显然,这实际上并不允许提供相同命令并且可以同时安装的多个软件包,因此这就是alternatives
Debian系统这些软件包为它们的文件提供了不同的名称,例如:
host ~ # dpkg -S /usr/bin/prename
perl: /usr/bin/prename
包postinst
脚本 ( /var/lib/dpkg/info/perl.postinst
) 将其注册为替代方案:
# util-linux has an alternate rename
update-alternatives --install /usr/bin/rename rename /usr/bin/prename 60 \
--slave /usr/share/man/man1/rename.1.gz rename.1.gz \
/usr/share/man/man1/prename.1.gz
dpkg -S
这就是为什么不知道的原因/usr/bin/rename
。
如果我没有这种知识,我怎样才能找出哪个包实际安装了符号链接?
Debian 软件包能提供符号链接,因此只要它不是符号链接(或由于其他原因alternatives
创建的符号链接),就可以正常工作。postinst
dpkg -S
对于系统alternatives
,只需遵循符号链接路径即可:
host ~ # dpkg -S $(readlink -f /usr/bin/rename)
perl: /usr/bin/prename
当然,这可能会导致您得出错误的结论,例如,当包在其中创建postinst
指向另一个文件提供的文件的符号链接时。在这种情况下,没有通用方法可以找出负责的包 - 您将必须做一些侦探工作,例如通过grep
ping*.postinst
文件。