跳到内容跳到页面导航:上一页 [access key p]/下一页 [access key n]
documentation.suse.com / SUSE Linux Enterprise Server 文档 / AutoYaST 指南 / 使用动态配置文件管理批量安装 / ERB 模板
适用范围 SUSE Linux Enterprise Server 15 SP4

7 ERB 模板

ERB 模板用于在 AutoYaST 配置文件内嵌入 Ruby 代码,以在安装期间修改配置文件。利用此方法,您可以通过设置值、添加或跳过某些部分等方式,来检查系统并调整配置文件。

要激活 ERB 处理,配置文件的扩展名必须为 .erb(例如,autoyast.xml.erb)。之后,它将无法合并规则/类和 ERB 模板。

7.1 什么是 ERB?

ERB 即嵌入式 Ruby (Embedded Ruby)。ERB 使用 Ruby 编程语言的功能来生成不同种类的内容。利用 ERB,您可以在配置文件中包含一些 Ruby 代码,以在运行时根据安装系统调整配置文件。

使用 ERB 时,Ruby 代码包含在 <%%> 符号之间。使用等号 = 可在最终的配置文件中包含命令输出。

例 7.1︰ 使用 ERB 包含文件
<bootloader>
  <% require "open-uri" %>
  <%= URI.open("http://192.168.1.1/profiles/bootloader-common.xml").read %>
</bootloader> <!-- this line gets replaced with the content of bootloader-common.xml -->

可以利用 Ruby 便利性来运行任意命令。如果想获得命令的输出,请将其包含在两个反引号之中。如果想知道命令成功与否,请使用 system 函数运行该命令。

例 7.2︰ 使用 Ruby 运行命令
<% files = `ls` %> <!-- files contains the output of the command (for instance "file1\nfile2\nfile3") -->
<% success = system("dmidecode | grep some-model") %> <!-- success contains true or false -->

此外,您还可使用更高级的 Ruby 代码结构(例如条件和循环)。

例 7.3︰ 使用 Ruby 结构
<% ip_forward = File.read("/proc/sys/net/ipv4/ip_forward").strip %>
<% if ip_forward == "1" %>
  <!-- something -->
<% end %>

<% files = `ls /tmp/config/*.xml` %>
<% files.split.each do |file| %>
  <%= file.read %>
<% end %>

AutoYaST 提供了一小组帮助程序函数,以从底层系统中检索信息(例如 disksnetwork_cards)。您可以在第 7.2 节 “模板帮助程序”中查看帮助程序及值列表。

7.2 模板帮助程序

模板帮助程序是 Ruby 方法的集合,可用于配置文件中以检索安装系统的相关信息。

7.2.1 boot_efi?

boot_efi? 是布尔帮助程序,将返回系统是否使用 EFI 引导的信息。在下面的示例中,配置文件会根据当前引导模式配置引导加载程序。

例 7.4︰ 配置引导加载程序
<% if env.boot_efi? %>
  <loader_type>grub2-efi</loader_type>
<% else %>
  <loader_type>grub2</loader_type>
<% end %>

7.2.2 disks

disks 帮助程序可返回检测到的磁盘列表。列表的每个元素包含一些基本信息,例如设备名称或大小。

类型

:device

字符串

设备内核名称(例如 sda)。

:model

字符串

磁盘型号

:serial

字符串

序列号

:size

整数

磁盘大小(以字节为单位)

:udev_names

字符串数组

磁盘 udev 名称列表。您可以使用其中的任何名称来表示设备。

:vendor

字符串

磁盘供应商名称

以下示例中的配置文件会在最大的磁盘上安装系统。它会按大小对现有磁盘列表排序,然后使用最后一个磁盘。之后,它会使用 :device 键作为 device 元素的值。

例 7.5︰ 使用最大的磁盘
<partitioning t="list">
  <drive>
    <% disk = disks.sort_by { |d| d[:size] }.last %> <!-- find the largest disk -->
    <device><%= disk[:device] %></device> <!-- print the disk device name -->
    <initialize t="boolean">true</initialize>
    <use>all</use>
  </drive>
</partitioning>

7.2.3 network_cards

network_cards 帮助程序可返回网卡列表,包括网卡名称,状态信息(例如,它们是否已连接)。

类型

:device

字符串

设备名称(例如 eth0enp3s0

:mac

字符串

MAC 地址

:active

布尔

设备是否处于活动状态

:link

布尔

设备是否已连接

:vendor

字符串

磁盘供应商名称

下面的示例会找到最先连接网络的网卡,并将其配置为使用 DHCP。

例 7.6︰ 配置连接的网卡
<interfaces t="list">
  <% with_link = netword_cards.sort_by { |n| n[:name] }.find { |n| n[:link] } %>
  <% if with_link %>
    <interface>
      <device><%= with_link[:device] %></device>
      <startmode>auto</startmode>
      <bootproto>dhcp</bootproto>
      </interface>
  <% end >
</interfaces>

7.2.4 os_release

os_release 帮助程序可返回操作系统信息,这些信息包含在 /etc/os-release 文件中。

类型

:id

字符串

发行套件 ID(例如 slesopensuse-tumbleweed

:name

字符串

发行套件名称(例如 SLESopenSUSE Tumbleweed

:version

字符串

发行套件版本(例如 15.2

您可以使用这些信息决定要安装的产品,对所有发行套件(SLE 或 openSUSE 发行套件)使用几乎相同的配置文件。

例 7.7︰ 对不同的发行套件重复使用相同的配置文件
<products t="list">
  <% if os_release[:id] == 'sle' %>
  <product>SLES</product>
  <% else %>
  <product>openSUSE</product>
  <% end %>
</products>

7.2.5 hardware

hardware 帮助程序提供其他硬件信息。它会返回 hwinfo 命令返回的所有信息。当通过所述帮助程序获取的信息不足时,您可以使用此帮助程序作为后备手段。下一个示例中使用 hardware 帮助程序来过滤 USB 设备。请查看 第 7.3 节 “运行 ERB 帮助程序” 了解如何检查 hardware 帮助程序提供的所有信息。

例 7.8︰ 过滤 USB 设备
<% usb_disks = hardware["disk"].select { |d| d["driver"] != "usb-storage" } %>

7.3 运行 ERB 帮助程序

您可以使用 Ruby 控制台运行 AutoYaST ERB 帮助程序,并了解它们可提供哪些功能。所有 ERB 帮助程序都可通过 Y2Autoinstallation::Y2ERB::TemplateEnvironment 类实例来访问。以 root 身份运行 irb -ryast -rautoinstall/y2erb 可启动 Ruby 交互式解释器。

例 7.9︰ 运行帮助程序
irb > env = Y2Autoinstallation::Y2ERB::TemplateEnvironment.new  # the env variable gives access to the helpers

irb > env.disks
=>
[{:vendor=>"WDC", :device=>"sda", ...},
 {:vendor=>"TOSHIBA", :device=>"sdb", ...},
...]

irb > env.hardware.keys
=>
["architecture",
 "bios",
 "bios_video",
 ...]

irb > env.hardware["architecture"]
=>
"x86_64"

7.4 呈现 ERB 配置文件

AutoYaST 命令行提供了 check-profile 命令,可用于基于 ERB 文件生成配置文件。此命令会要求 AutoYaST 分析、运行 ERB 代码,并生成最终的配置文件。您可以检查呈现的配置文件,确定所有功能均按预期工作。请查看命令帮助了解该命令支持的所有选项:autoyast check-profile --help。在下面的示例中,check-profile 要求 AutoYaST 下载并分析配置文件,解释 ERB 并运行前脚本。结果将转储到 result.xml 文件中。

例 7.10︰ 呈现配置文件
 > sudo yast2 autoyast check-profile filename=http://192.168.1.100/autoinst.erb output=result.xml run-scripts=true run-erb=true
警告
警告:check-profile 权限

大多数情况下,check-profile 都需要 root 权限,因此在以 root 身份运行安装前脚本和 ERB 配置文件时请务必保持谨慎。请仅使用您信任的配置文件。

7.5 调试 ERB 配置文件

在有些情况下,您需要停止 ERB 评估并检查发生了什么情况,为此 YaST 提供了与 byebug 调试器的集成。安装 rubygem(byebug) 软件包并将 Y2DEBUGGER 环境变量设为 1。

例 7.11︰ 准备调试环境
> sudo zypper --non-interactive in "rubygem(byebug)"
> sudo Y2DEBUGGER=1 yast2 autoyast check-profile ...

在想要停止的位置添加断点就像添加 <% byebug %> 一样容易。有关 byebug 的详细信息,请参见 https://github.com/deivid-rodriguez/byebug

例 7.12︰ 添加断点
<% byebug %>
<% if system("dmidecode | grep some-model") %>
  <!-- do something -->
%<% end %>

7.6 ERB 与规则和类的对比

尽管 ERB 和规则/类都能实现动态生成配置文件的功能,但一般而言,ERB 配置文件更容易阅读和理解。一个重要的不同之处是规则和类可以合并配置文件,而 ERB 则不能。请参见第 6 章 “规则和类了解有关合并配置文件的更多信息。另一方面,ERB 具有高级别语言 Ruby 的所有优势。我们来看一个使用了两种方式的示例。在下面的示例中,我们想将 /home 目录放在 /dev/sdb 中(如果该目录存在)。

例 7.13︰ 规则和类
<rule>
  <custom1>
    <script>
if blkid | grep /dev/sdb > /dev/null; then
echo -n "yes"
else
echo -n "no"
fi;
    </script>
    <match>yes</match>
    <match_type>exact</match_type>
  </custom1>
  <result>
    <profile>classes/sdb_home.xml</profile>
    <dont_merge config:type="list">
      <element>partition</element>
    </dont_merge>
  </result>
</rule>
例 7.14︰ ERB
<% home_in_sdb = disks.map { |d| d[:device] }.include?("sdb") %>

<partitioning config:type="list">
  <drive>
    ...
  </drive>
  <% if home_in_sdb %>
  <drive>
    <device>/dev/sdb</device>
    <disklabel>none</disklabel>
    <partitions t="list">
      <partition>
        <format t="boolean">true</format>
        <filesystem t="symbol">xfs</filesystem>
        <mount>/home</mount>
      </partition>
    </partitions>
  </drive>
  <% end %>
</partitioning>