在这个问题中,我描述了我在找出安装/usr/bin/rename
命令最终目标的包时遇到的问题。dpkg -S /usr/bin/rename
没有给出结果,但在首先发现这是一个链接之后,我找到了一个通用的解决方案。
由于/usr/bin/rename
指向/etc/alternatives/rename
我知道此特定链接是如何由update-alternatives
.
如果我没有那种知识,我怎么能找出哪个包实际安装了符号链接?如果没有简单的命令可以这样做,那么找出哪个命令确实设置了符号链接的一般策略是什么?
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
Run Code Online (Sandbox Code Playgroud)
并且包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
Run Code Online (Sandbox Code Playgroud)
这就是为什么dpkg -S
不知道的原因/usr/bin/rename
。
如果我没有那种知识,我怎么能找出哪个包实际安装了符号链接?
Debian 软件包可以提供符号链接,因此只要它不是alternatives
符号链接(或由postinst
出于其他原因创建的符号链接),dpkg -S
就可以正常工作。
在alternatives
系统的情况下,只需遵循符号链接路径:
host ~ # dpkg -S $(readlink -f /usr/bin/rename)
perl: /usr/bin/prename
Run Code Online (Sandbox Code Playgroud)
当然,这可能会导致您得出错误的结论,例如当一个包创建一个符号链接时,它postinst
指向另一个文件提供的文件。在这种情况下,没有通用的方法来找出负责的包 - 您必须做一些侦探工作,例如通过grep
ping*.postinst
文件。