

本文属于机器翻译版本。若本译文内容与英语原文存在差异，则一律以英文原文为准。

# 示例 6：创建文件
<a name="cookbooks-101-basics-files"></a>

**重要**  
该 AWS OpsWorks Stacks 服务于 2024 年 5 月 26 日终止，新客户和现有客户均已禁用。我们强烈建议客户尽快将其工作负载迁移到其他解决方案。如果您对迁移有疑问，请通过 re [AWS : Post 或通过 Pre](https://repost.aws/) mium Su [AWS pp](https://aws.amazon.com/support) ort 与 AWS 支持 团队联系。

创建目录后，通常需要用配置文件、数据文件等填充它们。本主题介绍了将文件安装在实例上的两种方法。

**Topics**
+ [从说明书安装文件](#cookbooks-101-basics-files-cookbook_file)
+ [从模板创建文件](#cookbooks-101-basics-files-template)

## 从说明书安装文件
<a name="cookbooks-101-basics-files-cookbook_file"></a>

将文件安装在实例上的最简单方法是使用 [https://docs.chef.io/chef/resources.html#cookbook-file](https://docs.chef.io/chef/resources.html#cookbook-file) 资源，它将文件从说明书复制到 Linux 和 Windows 系统实例上的指定位置。此实例扩展 [示例 3：创建目录](cookbooks-101-basics-directories.md) 中的配方，以便在创建目录后将数据文件添加至 `/srv/www/shared`。以下是原始配方，供您参考。

```
directory "/srv/www/shared" do
  mode 0755
  owner 'root'
  group 'root'
  recursive true
  action :create
end
```

**设置说明书**

1. 在 `opsworks_cookbooks` 目录中，创建名为 `createfile` 的实例并导航到其中。

1. 将包含以下内容的 `metadata.rb` 文件添加到 `createfile`。

   ```
   name "createfile"
   version "0.1.0"
   ```

1. 如[示例 1：安装软件包](cookbooks-101-basics-packages.md)中所述，初始化和配置 Test Kitchen，并从 `platforms` 列表中删除 CentOS。

1. 将 `recipes` 子目录添加 `createfile` 中。

要安装的文件包含以下 JSON 数据。

```
{
  "my_name" : "myname",
  "your_name" : "yourname",
  "a_number" : 42,
  "a_boolean" : true
}
```

**设置数据文件**

1. 将 `files` 子目录添加到 `createfile`，并将 `default` 子目录添加到 `files`。您随 `cookbook_file` 安装的任何文件必须位于 `files` 的子目录中，例如此示例中的 `files/default`。
**注意**  
如果要为不同的系统指定不同的文件，可以将每个特定于系统的文件放在根据系统命名的子文件夹中，例如 `files/ubuntu`。`cookbook_file` 资源会复制特定于系统的相应文件，如果该文件不存在，则会使用 `default` 文件。有关更多信息，请参阅 [cookbook\$1file](https://docs.chef.io/chef/resources.html#cookbook-file)。

1. 使用前面示例中的 JSON 创建名为 `example_data.json` 的文件，并将其添加至 `files/default`。

以下配方会将 `example_data.json` 复制到指定位置。

```
directory "/srv/www/shared" do
  mode 0755
  owner 'root'
  group 'root'
  recursive true
  action :create
end

cookbook_file "/srv/www/shared/example_data.json" do
  source "example_data.json"
  mode 0644
  action :create_if_missing
end
```

在目录资源创建 `/srv/www/shared` 后，`cookbook_file` 资源会将 `example_data.json` 复制到该目录中，并设置该文件的用户、组和模式。

**注意**  
`cookbook_file` 资源引入了一个新操作：`create_if_missing`。您也可以使用 `create` 操作，但是这样会覆盖现有文件。如果您不想覆盖任何内容，请使用 `create_if_missing`，这样会安装 `example_data.json` (如果该文件尚不存在)。

**运行配方**

1. 运行 `kitchen destroy`，以便从全新的实例开始。

1. 创建包含前面配方的 `default.rb` 文件，并将该文件保存至 `recipes`。

1. 运行 `kitchen converge`，然后登录到实例以验证 `/srv/www/shared` 包含 `example_data.json`。

## 从模板创建文件
<a name="cookbooks-101-basics-files-template"></a>

`cookbook_file` 资源对某些用途来说非常有用，但它只会安装您在说明书中所拥有的任何文件。[https://docs.chef.io/chef/resources.html#template](https://docs.chef.io/chef/resources.html#template) 资源通过从模板动态创建文件，从而提供了一种将文件安装在 Windows 或 Linux 实例上的更灵活方法。然后，您可以在运行时确定文件内容的详细信息，并根据需要进行更改。例如，在启动实例时，您可能希望配置文件具有特定设置，并在以后向堆栈中添加更多实例时修改该设置。

此示例会修改 `createfile` 说明书，以使用 `template` 资源安装略经修改的 `example_data.json` 版本。

下面是已安装文件的外观。

```
{
  "my_name" : "myname",
  "your_name" : "yourname",
  "a_number" : 42,
  "a_boolean" : true,
  "a_string" : "some string",
  "platform" : "ubuntu"
}
```

模板资源通常与属性文件结合使用，因此该示例使用其中一个来定义以下值。

```
default['createfile']['my_name'] = 'myname'
default['createfile']['your_name'] = 'yourname'
default['createfile']['install_file'] = true
```

**设置说明书**

1. 删除 `createfile` 说明书的 `files` 目录及其内容。

1. 将 `attributes` 子目录添加到 `createfile`，将 `default.rb` 文件添加到 `attributes` (其中包含前面的属性定义)。

模板是一个 `.erb` 文件，该文件基本上为最终文件的副本，其中某些内容由占位符表示。当 `template` 资源创建该文件时，它会将模板的内容复制到指定文件，并用其分配的值覆盖占位符。此处为 `example_data.json` 的模板。

```
{
  "my_name" : "<%= node['createfile']['my_name'] %>",
  "your_name" : "<%= node['createfile']['your_name'] %>",
  "a_number" : 42,
  "a_boolean" : <%= @a_boolean_var %>,
  "a_string" : "<%= @a_string_var %>",
  "platform" : "<%= node['platform'] %>"
}
```

`<%=...%>` 值为占位符。
+ `<%=node[...]%>` 表示节点属性值。

  在该示例中，“your\$1name”值为占位符，表示来自说明书的属性文件的其中一个属性值。
+ `<%=@...%>` 表示模板资源中定义的变量值 (稍后将进行讨论)。

**创建 模板文件**

1. 将 `templates` 子目录添加到 `createfile` 说明书，并将 `default` 子目录添加到 `templates`。
**注意**  
`templates` 目录的工作方式与 `files` 目录很相似。您可以将特定于系统的模板放在子目录 (例如根据系统命名的 `ubuntu`) 中。`template` 资源会使用特定于系统的适当模板 (如果该模板存在)，否则会使用 `default` 模板。

1. 创建名为 `example_data.json.erb` 的目录并将其放在 `templates/default` 目录中。模板名称是任意性的，但您通常可以通过将 `.erb` 附加到文件名 (包括任何扩展名) 来创建模板名称。

以下配方使用 `template` 资源来创建 `/srv/www/shared/example_data.json`。

```
directory "/srv/www/shared" do
  mode 0755
  owner 'root'
  group 'root'
  recursive true
  action :create
end

template "/srv/www/shared/example_data.json" do
  source "example_data.json.erb"
  mode 0644
  variables(
    :a_boolean_var => true,
    :a_string_var => "some string"
  )
  only_if {node['createfile']['install_file']}
end
```

`template` 资源会从模板创建 `example_data.json`，并将其安装在 `/srv/www/shared` 中。
+ 模板名称 `/srv/www/shared/example_data.json` 会指定所安装文件的路径和名称。
+ `source` 属性会指定用于创建文件的模板。
+ `mode` 属性会指定所安装文件的模式。
+ 资源会定义两个变量，即 `a_boolean_var` 和 `a_string_var`。

  当资源创建 `example_data.json` 时，它会用来自资源的相应值覆盖模板中的变量占位符。
+ 只有在 `only_if` 设置为 * 时，* `['createfile']['install_file']`guard`true` 属性才会指示资源创建文件。

**运行配方**

1. 运行 `kitchen destroy`，以便从全新的实例开始。

1. 将 `recipes/default.rb` 中的代码替换为前面的示例。

1. 运行 `kitchen converge`，然后登录到实例，以验证文件是否位于 `/srv/www/shared` 中以及是否拥有正确的内容。

完成后，运行 `kitchen destroy` 以关闭实例。下一节将使用新的说明书。