

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

# 示例 3：创建目录
<a name="cookbooks-101-basics-directories"></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 支持 团队联系。

当您在实例上安装软件包时，通常需要创建一些配置文件，并将这些配置文件放在适当的目录中。但是，这些目录可能尚不存在。您可能还需要针对数据、日志文件等创建目录。例如，首先启动您用于大多数示例的 Ubuntu 系统，`/srv` 目录没有子目录。如果您要安装应用程序服务器，则可能需要一个 `/srv/www/` 目录，并且可能还需要用于数据文件、日志等的一些子目录。以下配方会在实例上创建 `/srv/www/`。

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

您使用 [`directory` 资源](https://docs.chef.io/chef/resources.html#directory)同时在 Linux 和 Windows 系统上创建和配置目录，但某些属性的用法不同。资源名称是资源的 `path` 属性的默认值，因此该示例会创建 `/srv/www/`，并指定其 `mode`、`owner` 和 `group` 属性。

**运行配方**

1. 在 `opsworks_cookbooks` 中创建名为 `createdir` 的目录并导航到该目录。

1. 如[示例 1：安装软件包](cookbooks-101-basics-packages.md)中所述，初始化和配置 Test Kitchen，然后将 `recipes` 目录添加到 `createdir` 内。

1.  将 `default.rb` 文件连同配方代码一起添加到说明书的 `recipes` 子目录中。

1. 运行 `kitchen converge` 以执行该配方。

1. 运行 `kitchen login`，导航到 `/srv` 并验证它是否拥有 `www` 子目录。

1. 运行 `exit` 以返回到您的工作站，但让实例保持运行状态。

**注意**  
要在实例上创建相对于主目录的目录，请使用 `#{ENV['HOME']}` 表示主目录。例如，以下内容会创建 `~/shared` 目录。  

```
directory "#{ENV['HOME']}/shared" do
  ...
end
```

假设您要创建一个更深层嵌套的目录，例如 `/srv/www/shared`。您可以按如下所示修改前面的配方。

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

**运行配方**

1.  用前面的配方替换 `default.rb` 中的代码。

1. 从 `kitchen converge` 目录运行 `createdir`。

1. 要验证是否确实已创建目录，请运行 `kitchen login`，导航到 `/srv/www`，并验证它是否包含 `shared` 子目录。

1. 运行 `kitchen destroy` 以关闭实例。

您将注意到 `kitchen converge` 命令运行速度更快。这是因为该实例已在运行，因此不需要启动实例、安装 Chef 等。Test Kitchen 直接将更新的说明书复制到实例中并开始运行 Chef。

现在，再次运行 `kitchen converge`，这将会在全新实例上执行配方。现在，您将看到以下结果。

```
Chef Client failed. 0 resources updated in 1.908125788 seconds       
[2014-06-20T20:54:26+00:00] ERROR: directory[/srv/www/shared] (createdir::default line 1) had an error: Chef::Exceptions::EnclosingDirectoryDoesNotExist: Parent directory /srv/www does not exist, cannot create /srv/www/shared       
[2014-06-20T20:54:26+00:00] FATAL: Chef::Exceptions::ChildConvergeError: Chef run process exited unsuccessfully (exit code 1)       
>>>>>> Converge failed on instance <default-ubuntu-1204>.
>>>>>> Please see .kitchen/logs/default-ubuntu-1204.log for more details
>>>>>> ------Exception-------
>>>>>> Class: Kitchen::ActionFailed
>>>>>> Message: SSH exited (1) for command: [sudo -E chef-solo --config /tmp/kitchen/solo.rb --json-attributes /tmp/kitchen/dna.json  --log_level info]
>>>>>> ----------------------
```

发生了什么？ 问题在于，默认情况下，`directory` 资源一次只能创建一个目录；它无法创建一系列目录。配方之前能够正常工作的原因是，您在实例上运行的第一个配方已经创建了 `/srv/www`，因此创建 `/srv/www/shared` 时仅创建了一个子目录。

**注意**  
在运行 `kitchen converge` 时，请确保了解您是在新实例上还是在现有实例上运行配方。您可能会得到不同的结果。

要创建一系列子目录，请将 `recursive` 属性添加到 `directory` 中，并将其设置为 `true`。以下配方会直接在干净的实例上创建 `/srv/www/shared`。

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