在 我们的最新 sprint 报告 中,我们承诺会额外发布一篇关于我们最近用来操作配置文件的技术文章。等待结束了!这里是 Michal Filka 撰写的详细说明,解释了您需要了解的一切,以便开始使用 CFA。
欢迎使用 CFA
如您所知,如果您关注我们的博客(我们会不时重复一遍
),YaST 已经从一种名为 YCP 的自定义编程语言转换为 Ruby。但是,这种转换是基于语言进行的。一些旧的设计决策和原则仍然存在,例如使用 SCR 来访问底层系统。
SCR 是与 YaST 一起设计的。它使用“代理”的概念来访问配置文件。这些代理包含使用其自身格式的配置文件描述。此外,SCR 提供位置透明性。例如,您可以处理执行系统中的文件或在 chrooted 环境中的文件。但是,这段代码是专有的,并且代理的质量水平不一致。此外,它是用 C++ 编写的,仅在 SUSE 内部开发,并且不幸的是,设计得不太好。您不能轻易地只使用解析器或位置透明性功能。在解析输入时,您始终必须经过完整的 SCR 堆栈。同样,在使用位置透明性(设置新位置)时,所有后续的 SCR 调用都会受到其影响。出于这些和其他原因,我们决定用其他东西替换专有的 SCR。这就是我们开始开发和使用“配置文件 API”的原因。
配置文件 API (CFA) 是一个用 Ruby 编写的库,用于访问各种配置文件。您可以从 rubygems.org 下载它。它也作为 OpenSUSE 42.3 构建服务中的一组 RPM 包 提供。它被结构化为几个层,并创建配置文件的内部抽象。它是在 SUSE 的 YaST 团队中设计和开发的。但是,这次它使用(或可以使用)第三方解析器。CFA 为底层解析器提供位置透明性,并为应用程序提供统一的 API。位置透明性通过一个众所周知的 File 接口实现,因此您可以使用实现该接口的任何代码。实现对新解析器的支持要复杂一些。在最坏的情况下,您可能需要实现 Ruby 绑定。但是,一旦您拥有绑定,实现其他需要在 CFA 堆栈中使其正常工作的部分就会很简单。
让我们详细了解一下这些层。
底层:文件访问
负责直接访问配置文件。在最简单的情况下,它使用 Ruby 的 File 类 访问本地配置文件,但它可以适应访问远程、chrooted 或内存文件。开发人员只需提供实现相应 read 和 write 方法的文件处理程序。CFA 常用框架已经提供了内存和 chrooted 环境中的文件处理程序。
中间层:解析器
此层解析由底层加载的配置文件。它了解文件的结构,并将其转换为抽象表示。该库通常使用外部工具进行解析,例如 Augeas。因此,如果外部工具有特定要求,则必须满足这些要求才能使其正常工作。例如,如果使用 Augeas,则需要提供适当的透镜(Augeas 术语,用于文件格式描述符)来解析特定的配置文件。
顶层:配置文件模型
最后一层创建配置文件的模型——一种语义上有意义的 API,用于从应用程序访问配置。它基本上是在另一个抽象之上创建“抽象”。这意味着它统一了可用于访问和解析配置文件的各种工具的使用。
限制
上述模型有一些缺点,主要影响开发人员,但有时对用户也可见。
喂饱野兽
如果您是计划使用 CFA 来操作给定配置文件的开发人员,则必须考虑到您需要提供解析器并满足其所有要求。因此,您至少需要知道每个文件使用哪个解析器以及使解析器与您感兴趣的文件一起工作需要什么。
这对于非标准/自定义配置文件尤其重要。可能需要一些预先的工作来评估可用的选项。
驯服野兽
由于库和/或第二层上的解析器提供配置文件上的抽象,因此也存在一些限制。这种抽象将配置文件转换为更方便和更有意义的模型,并在文件和模型之间建立关系。
但是,问题在于使用大多数解析器(特别是使用 Augeas)这种关系不是双射的。这意味着配置文件的某些不相关部分未在模型中表示。例如,如果它们从语法角度不需要,则某些空格可能会被省略。这可能导致自定义填充丢失。
另一个例子是注释。您经常会看到,如果您的文件使用例如 # 作为注释标记,那么某些解析器可以将包含这些标记的行(一些开发人员将其用作一种分隔符)压缩为单个 #。
作为一个更具体的例子,某些 Augeas 透镜不会将初始注释标记存储在模型中。这在允许使用多种不同注释标记的文件透镜中很常见。但是,某些透镜会在开头返回包含其标记的注释,因此需要在 CFA 的上层或应用程序级别进行额外的处理。
最后但并非最不重要的一点是,某些解析器在添加没有定义值的键时会使用默认值。如果未由上层处理,这当然可能导致配置文件外观的不一致。
实际示例
如前所述,CFA 正在被用作 YaST 中旧的 SCR 的替代品。因此,我们可以真正地查看这种替代的结果,例如 yast2-network 中的 /etc/hosts 处理。撇开代码现在更易于阅读的事实不谈,我们还收集了一些性能数据。
测试是在一个包含 10,000 个条目的示例 /etc/hosts 文件上运行的(信不信由你,实验基于用户报告的真实用例)。测试使用 YaST 的命令行界面进行,并使用经典的 time 实用程序进行测量。由于命令行界面当前不支持输入主机条目,因此仅测试读取操作。
| time | SCR | CFA |
|---|---|---|
| real | 1m15.735s | 0m19.079s |
| user | 1m15.076s | 0m18.348s |
| sys | 0m0.164s | 0m0.244s |
如您所见,这段代码现在比以前快大约四倍,因此实际结果看起来非常有希望。此外,CFA 的代码设计更好,并且受自动化测试的覆盖范围更广。
这就是 YaST 团队投资于同一枚硬币的两面——CFA 开发和将 YaST 的代码从 SCR 转换为 CFA 的原因。