在 ruby 模板中以定义的顺序循环散列

loop over hash in defined order in ruby template

我有一个 ruby 模板 (.erb),我想对哈希进行迭代。每次 Puppet 代理运行时,它都应该生成相同的输出文件。

我目前拥有的是以下内容。这是我的模板(如果有人想知道的话,它是 rsyslog 配置的一部分):

<% log_files.each do |log_file, tag| -%>
# <%= log_file %>
$InputFileName <%= log_file %>
$InputFileTag <%= tag %>:

此模板使用如下所示的散列呈现:

log_files => {
  '/root/apache_auth.local' => 'httpd',
  '/root/install.log' => 'hugo',
}, 

(不是真正的日志文件)。这有效并生成我想要的配置文件。这样做的问题是,每次我调用 puppet 代理时,哈希中日志文件的顺序都会改变,因此配置文件会被重写,随后守护进程会重新启动。功能保持不变,但我不希望每次运行 puppet 代理时都重写配置文件和重新启动 rsyslog。

现在我假设这无法用哈希解决,因为它们的本质是它们没有定义的顺序。我还有哪些其他选择可以实现我想要的?

由于 ERB 模板中的小脚本由 Ruby 代码组成,因此这本质上是一个 Ruby 问题。因此,可能的答案取决于 Puppet 目录编译器下 Ruby 的 运行 版本。然而,尽管较新的 Ruby 中可能有更好的替代方案,但您的代码的这种变体将适用于自 Puppet 2.7 以来 Puppet 支持的任何 Ruby:

<% @log_files.sort.each do |log_file, tag| -%>
# <%= log_file %>
$InputFileName <%= log_file %>
$InputFileTag <%= tag %>:
<% end -%>

这里的关键(没有双关语意)是 sort