(1)关于 linux 主机上的 RPM 数据库
RPM 在 linux 机器上工作原来是比较明确的,首先有实际的rpm解压缩并且安装后的文件;另外有Rpm 的DB文件,
存储这些安装了的 rpm 的信息,这些库中信息在 RPM进行安装,升级和卸载时进行更新。
RPM命令对两者的操作有: (1):对DB库进行增删查该 (2):对文件系统进行增加和删除和读取。
结合起来看:
(1): RPM的安装/升级,写入DB库,写文件系统,生成安装列表和服务,配置等,执行安装时脚本。
(2): RPM卸载,删除DB库,删除文件系统中归属于该软件包的文件,执行卸载时脚本。
(3): RPM查询, 读取DB库/文件并且显示。
RPM 的在主机上的数据库有好多个,根据不同的应用类型,采用不同的访问方法,可以看下: file /var/lib/rpm/* | grep Berkeley
/var/lib/rpm/Basenames: Berkeley DB (Hash, version 8, native byte-order)
/var/lib/rpm/Conflictname: Berkeley DB (Hash, version 8, native byte-order)
/var/lib/rpm/Dirnames: Berkeley DB (Btree, version 9, native byte-order)
/var/lib/rpm/Filemd5s: Berkeley DB (Hash, version 8, native byte-order)
/var/lib/rpm/Group: Berkeley DB (Hash, version 8, native byte-order)
/var/lib/rpm/Installtid: Berkeley DB (Btree, version 9, native byte-order)
/var/lib/rpm/Name: Berkeley DB (Hash, version 8, native byte-order)
/var/lib/rpm/Packages: Berkeley DB (Hash, version 8, native byte-order)
/var/lib/rpm/Providename: Berkeley DB (Hash, version 8, native byte-order)
/var/lib/rpm/Provideversion: Berkeley DB (Btree, version 9, native byte-order)
/var/lib/rpm/Pubkeys: Berkeley DB (Hash, version 8, native byte-order)
/var/lib/rpm/Requirename: Berkeley DB (Hash, version 8, native byte-order)
/var/lib/rpm/Requireversion: Berkeley DB (Btree, version 9, native byte-order)
/var/lib/rpm/Sha1header: Berkeley DB (Hash, version 8, native byte-order)
/var/lib/rpm/Sigmd5: Berkeley DB (Hash, version 8, native byte-order)
/var/lib/rpm/Triggername: Berkeley DB (Hash, version 8, native byte-order)
复制代码能够看到,主要是 HASH 和 BTREE 这两种访问方式。(很奇怪,version 8 的是 HASH, version 9的是BTREE ?是应用相关,还纯粹是作者爱好呢?)
RPM 的所有DB,都是从 /var/lib/rpm/Packages 生成的。可以做个实验,把除了 Packages 以外的其它文件全部删掉。
然后重新 rpm --rebuilddb -vv
这些文件都会一一生成,因为构成这几个新的db文件的信息都在Packages中包含了。(如果你把这个文件干掉了,那就悲催了,
曾经遇到有人把这个文件给删掉了,只好从同组配置接近的机器给他拷贝了一个os和arch一样的机器的Packages,重新生成了下db,还好,能继续用,呵呵)。因为这个文件中记录了你的机器安装的所有RPM和文件列表,一旦这个文件丢失了,rpm就不知道你的机器上有哪些rpm了,当你通过
rpm -qf path 查询某个二进制文件属于哪个rpm时,也不会有结果输出。
关于 /var/lib/rpm/Packages 这个 DB 文件的最初来源,我分析(结合猜测)是这样的:
首先,在安装(或者OS安装时)每一个 rpm 文件的时候,rpm 命令都会把要安装的 rpm 包的信息分析出来,包括我们在第一篇看到的所有TAG还有文件列表等信息;
然后会把这些信息写入 /var/lib/rpm/Packages 文件中,如果这个文件不存在,就创建;当删除包时,就会从 /var/lib/rpm/Packages 中
删除与该包相关的所有信息。该文件中记录了所有 rpm 的全量信息,因此,我们通过 rpm 命令查询时,才能够看到那么多灿烂和丰富的信息。
以rpm -qf 和 rpm -ql 为例:
比如,为了能从 xshell 拷贝文件到windows机器,我经常会用 sz/rz命令,但是有些机器上就是没这个命令,
要安装,又不知道它在哪个包,怎么办,这时就需要用 rpm -qf 来查询了:
找一台安装了 sz/rz 命令的机器: # which sz
/usr/bin/sz
# rpm -qf /usr/bin/sz
lrzsz-0.12.20-22.1
复制代码喔,我们发现sz和rz是在 lrzsz 这个包中的,然后在需要的机器上 rpm/yum 安装 lrzsz 包即可。
那么,rpm -qf 命令路径 就能查到这个命令属于那个包,这是怎么做到的呢?
首先我们知道安装 lrzsz 时 rpm 会把 这个包的所有信息写入 /var/lib/rpm/Packages 文件,这个包包含的文件列表也会写入
到 这个文件中,然后才会更新生成 /var/lib/rpm 中的其它DB文件(个人理解,其它DB文件就是为了查询加速而用生成的cache.)
然后,当执行 rpm -qf /usr/bin/sz
复制代码时,rpm 就会去 /var/lib/rpm/Packages 中(或者其它cache文件中)查询包含 /usr/bin/sz 这个路径的
包,当然就查到了是 lrzsz.
有人说,可能查到多个包么?这个是不可能的,因为 rpm 在安装 rpm 文件的时候,也就是往 /var/lib/rpm/Packages
中写数据的时候,会检查这个rpm 中包含的文件列表是否已经在本机安装的其它包中出现了,如果找到了,就会警告: 这个文件和其它某个包中的
某某文件冲突了的错误信息,这个现象做SA的同学应该都见过。
实验: ls -alt /var/lib/rpm/Packages
-rw-r--r-- 1 rpm rpm 19234816 Dec 27 09:30 /var/lib/rpm/Packages
复制代码我们能够看到,这个文件只对root 可以写,我们尝试改下它的属性: chattr +i /var/lib/rpm/Packages
复制代码设置不可改变属性,然后尝试安装包: rpm -ivh RPMS/i386/test-baby-1.1-1.i386.rpm
error: cannot open Packages index using db3 - Permission denied (13)
error: cannot open Packages database in /var/lib/rpm
复制代码因为rpm 没有权限去写 Packages 这个数据库文件。 # chattr -i /var/lib/rpm/Packages
rpm -ivh RPMS/i386/test-baby-1.1-1.i386.rpm
Preparing... ########################################### [100%]
1:test-baby ########################################### [100%]
复制代码这下就成功了,再次验证了 rpm 在包安装时对 /var/lib/rpm/Packages 的写操作确实是存在的。
同样,你也可以同样方法测试下卸载包时对 /var/lib/rpm/Packages 文件的写操作是否存