yum仓库内部原理

本文是yum repository internals的翻译。

TL;DR

这篇博客将会检查各种yum仓库中的索引文件,从而深入了解yum仓库的细节。我们将介绍每个索引文件的含义,并研究用户如何检查这些元数据。

什么是yum仓库?

Yum仓库就是一些RPM包的集合,加上一些yum命令能够读取的元数据。有一个yum仓库能够让你安装、删除、升级软件包或者软件组。

yum仓库对于存储、管理、交付软件非常重要。

使用createrepo命令创建一个yum仓库

在详细了解yum仓库元数据之前,先让我们看看如何用开源命令行工具createrepo架设一个yum仓库。

使用命令行工具createrepo,你能创建一个yum仓库。你能在CentOS或Red Hat系统中使用如下命令安装这个工具:

1
$ sudo yum install createrepo

createrepo 最简单的用法就是使用一个命令行参数:yum仓库元数据的保存目录。

假设你在当前目录有一些RPM文件,那你就能一条命令来生成一个yum仓库:

1
$ createrepo .

这个命令会创建一个名字为repodata的文件夹,包含了yum仓库的元数据。我们接下来会深入了解这些元数据。

你还可以使用GPG来签名这些元数据。这样就能保证yum仓库的用户使用的是你生成的元数据。这个和rpmrpmsigin不一样:

1
$ gpg --detach-sign --armor myrepo/repodata/repomd.xml

关于GPG签名RPM包和yum仓库的更多细节,你可以在之前的文章找到。

如果你也想让其他用户访问你的yum仓库,你要假设Apache,nginx或者其他web服务器,并将网站目录指向到仓库的根目录。当然,我们推荐你获取一个SSL证书,确保软件包能安全的传输到最终系统上。

当然,使用packagecloud是更加快速、简单的解决办法,而且自带SSL、GPG支持,可以与其他人协作等特性。

yum仓库元数据

yum仓库元数据是由一系列XML文件组成的。这些文件包含了其他文件的校验和包含的包。

通常,在yum仓库中能找到的元数据文件有这几种:

  • repomd.xml:包含了其他XML元数据文件的位置、校验和和时间戳的一个索引文件。
  • repomd.xml.asc:只有仓库创建者使用GPG签名了repomd.xml文件时,才会生成这个文件。如前所述,如果用户安装了pygpgme包,那么yum就会下载并校验这个文件。
  • primary.xml.gz:包含了仓库里每个包的详细信息,比如名字、版本、授权协议、依赖信息、时间戳、大小等信息。
  • filelists.xml.gz:包含了每个包的每个文件和目录。
  • other.xml.gz:包含了每个包的changelog记录,这些记录来自RPM SPEC文件。

还有一些其他文件,但是它们没有得到广泛应用。对于大多数yum仓库,上面这些文件就足够了。

典型的,yum仓库的元数据存储在repodata URL下,或者repodata目录下。

将相同架构的软件存放在一起,这是一个常用的实践。这样,你的软件仓库的元数据就能够按照架构类型分开,从而减少服务端到客户端的流量。

一个典型的x86_64和i386架构的repomd.xml链接(来自packagecloud)一般是:

大多数公开的软件仓库也有同样的结构。比如CentOS 7的repomd.xml文件:

检查并校验yum仓库的元数据

你可以使用一些命令行工具来检查yum仓库的元数据、计算校验和、校验GPG签名。

让我们以位于https://packagecloud.io/computology/packagecloud-cookbook-test-public/el/7 的CentOS 7仓库为例:

首先检查 repomd.xml

你必须首先用curl命令检查repomd.xml文件。其他的索引文件以及校验和都在这个文件中:

1
2
$ curl -Ls \
https://packagecloud.io/computology/packagecloud-cookbook-test-public/el/7/x86_64/repodata/repomd.xml

(提示: 如果你需要更详细的信息,或者需要调试信息,你可以使用curl的-Lv命令来开启详细输出模式。)

校验repomd.xml的GPG签名

如果repo_gpgcheck设置为1的话,yum会自动尝试校验仓库的GPG签名,但是你也可以手动校验。

如果仓库是GPG签名过的,而且你已经导入了GPG公钥,那你可以通过gpg --verify来校验下载下来的repomd.xml文件和repomd.xml.asc文件:

1
2
3
4
5
6
7
8
9
10
$ curl -Ls \
https://packagecloud.io/computology/packagecloud-cookbook-test-public/el/7/x86_64/repodata/repomd.xml
> repomd.xml
$ curl -Ls \
https://packagecloud.io/computology/packagecloud-cookbook-test-public/el/7/x86_64/repodata/repomd.xml.asc
> repomd.xml.asc
$ gpg --verify repomd.xml.asc repomd.xml
gpg: Signature made Sun Oct 12 11:07:54 2014 PDT using RSA key ID 7AD95B3F
gpg: Good signature from "packagecloud ops (production key)
<[email protected]>"

检查primary.xml.gz

接下来,让我们检查primary.xml.gz。如前所述,这个文件包含了仓库中的包信息。

repomd.xml文件指出了这个文件的位置:

1
2
3
4
5
6
<data type="primary">
<location href="repodata/primary.xml.gz"/>
<checksum type="sha">6eb7ecc041f69a5ffeabdebcb466c443aa5e8028</checksum>
<timestamp>1413137274</timestamp>
<open-checksum type="sha">0b08c81e46081059cbe56d2f0871017ef8073d93</open-checksum>
</data>

注意:这个文件的路径不总是这么简单明了。有的时候,这个URL会包含SHA或MD5校验和。

这个位置是相对于仓库根目录的。

首先检验SHA校验和是不是和repomd.xml中的匹配。_open-checksum_节点列出的校验和是压缩之后的文件的校验和。

1
2
$ curl -Ls https://packagecloud.io/computology/packagecloud-cookbook-test-public/el/7/x86_64/repodata/primary.xml.gz | shasuma
6eb7ecc041f69a5ffeabdebcb466c443aa5e8028 -

很好!校验和是一致的!让我们用zless 来浏览它:

1
2
3
$ curl -Ls \
https://packagecloud.io/computology/packagecloud-cookbook-test-public/el/7/x86_64/repodata/primary.xml.gz \\
| zless

primary.xml.gz中的示例数据如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<package type="rpm">
<name>jake</name>
<arch>x86_64</arch>
<version epoch="87" rel="3.el6" ver="1.0"/>
<checksum pkgid="YES" type="sha">ea721867eb0389e28bcd32e2deef7d4472c6ced8</checksum>
<summary>jake douglas is a very nice young man.</summary>
<description>as it so happens, jake douglas is a very nice young man.</description>
<packager></packager>
<url>https://twitter.com/jakedouglas</url>
<time build="1401650103" file="1413137269"/>
<size archive="4536" installed="4280" package="3740"/>
<location href="jake-1.0-3.el6.x86_64.rpm"/>
<format>
<rpm:license>GPL</rpm:license>

filelists.xml.gz 和 other.xml.gz

对filelists.xml.gz和other.xml.gz重复上述过程,来检查这些文件:

  1. 从repomd.xml中获取文件路径和校验和。
  2. 使用 curl -Ls <url> | shasum 来检查校验和是否和repomd.xml中的匹配。
  3. 使用 curl -Ls <url> | zless 来查看文件内容。

结论

yum仓库的元数据由一组XML文件、校验和以及某些情况下的GPG签名组成。元数据描述在存储库中可以找到哪些包、每个包的各种属性、文件和目录清单,以及变更日志信息。

yum仓库的元数据可以通过curl, less/zless, gpgshasum命令来查看和校验。如果你要排查一些yum仓库的问题话(包缺失、依赖缺失、错误的版本等),或者你对操作系统最重要的一部分之一好奇的话,那这些工具是非常有用的。

作者

Robert Lu

发布于

2019-06-29

许可协议

评论