

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

# 扩展层


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

有时，您需要通过修改 OpsWorks Stacks 属性或自定义模板来将内置层自定义到无法处理的程度。例如，假设您需要创建符号链接、设置文件或文件夹模式、安装其他程序包等。您必须扩展自定义层以提供最低限度功能之外的功能。在这种情况下，您将需要实施包含配方的一个或多个自定义说明书来处理自定义任务。本主题提供了一些介绍如何使用配方来扩展层的示例。

如果您在 Chef 方面是新手，您应当先阅读[说明书 101](cookbooks-101.md)，这是一个教程，旨在介绍关于如何实施说明书以执行各种常见任务的基本知识。有关如何实施自定义层的详细示例，请参阅[创建自定义 Tomcat 服务器层](create-custom.md)。

**Topics**
+ [

# 使用配方运行脚本
](workingcookbook-extend-scripts.md)
+ [

# 使用 Chef 部署挂钩
](workingcookbook-extend-hooks.md)
+ [

# 在 Linux 实例上运行 Cron 作业
](workingcookbook-extend-cron.md)
+ [

# 在 Linux 实例上安装和配置程序包
](workingcookbook-extend-package.md)

# 使用配方运行脚本


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

如果您已经有一个用于执行所需的自定义任务的脚本，则扩展层的最简单方法通常是实施一个运行该脚本的简单配方。您随后可以将该配方分配到相应的生命周期事件 (通常是设置或部署)，或者使用 `execute_recipes` 堆栈命令手动运行该配方。

以下示例在 Linux 实例上运行 shell 脚本，但您可以对其他类型的脚本（包括 Windows PowerShell 脚本）使用相同的方法。

```
cookbook_file "/tmp/lib-installer.sh" do
  source "lib-installer.sh"
  mode 0755
end

execute "install my lib" do
  command "sh /tmp/lib-installer.sh"
end
```

`cookbook_file` 资源表示一个存储在说明书的 `files` 目录的子目录中的文件，然后将该文件传输到实例上的指定位置。本示例会将 shell 脚本 `lib-installer.sh` 传输到实例的 `/tmp` 目录并将该文件的模式设置为 `0755`。有关更多信息，请参阅 [cookbook\$1file](https://docs.chef.io/chef/resources.html#cookbook-file)。

`execute` 资源表示一个命令，如 shell 命令。此示例运行 `lib-installer.sh`。有关更多信息，请参阅 [execute](https://docs.chef.io/chef/resources.html#execute)。

您还可以通过将脚本集成到配方中来运行脚本。以下示例将运行 bash 脚本，但 Chef 还支持 Csh、Perl、Python 和 Ruby。

```
script "install_something" do
  interpreter "bash"
  user "root"
  cwd "/tmp"
  code <<-EOH
    #insert bash script
  EOH
end
```

`script` 资源表示一个脚本。该示例指定了 bash 解释器，将用户设置为 `"root"`，并将工作目录设置为 `/tmp`。然后，它在 `code` 块中运行了 bash 脚本，该块可根据需要包含任意数量的行。有关更多信息，请参阅[脚本](https://docs.chef.io/chef/resources.html#script)。

有关如何使用配方运行脚本的更多信息，请参阅[示例 7：运行命令和脚本](cookbooks-101-basics-commands.md)。有关如何在 Windows 实例上运行 PowerShell 脚本的示例，请参阅[运行 Windows PowerShell 脚本](cookbooks-101-opsworks-opsworks-powershell.md)。

# 使用 Chef 部署挂钩


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

您可以实施自定义配方来执行所需的任务并将该配方分配到相应层的部署事件，从而自定义部署。一个替代方法是使用 Chef 部署挂钩运行您的自定义代码，这个方法有时候更简单，尤其是在您出于其他原因无需实施说明书时。此外，在部署后运行的自定义部署配方已由内置配方执行。利用部署挂钩，您可以在部署期间进行交互，例如，在已将应用程序的代码从存储库签出但尚未重新启动 Apache 时。

Chef 分四个阶段部署应用程序：
+ **签出**-从存储库下载文件
+ **迁移**-根据需要运行迁移
+ **符号链接**-创建符号链接
+ **重新启动**-重新启动应用程序

Chef 部署挂钩提供了一种自定义部署的简单方法，即在每个阶段完成后选择性地运行用户提供的 Ruby 应用程序。要使用部署挂钩，请实施一个或多个 Ruby 应用程序，然后将其放在您的应用程序的 `/deploy` 目录中。(如果您的应用程序没有 `/deploy` 目录，请在 `APP_ROOT` 级别创建一个。) 该应用程序必须具有以下名称之一，该名称决定了应用程序运行的时间。
+ `before_migrate.rb` 在签出阶段已完成但迁移尚未开始时运行。
+ `before_symlink.rb` 在迁移阶段已完成但符号链接尚未开始时运行。
+ `before_restart.rb` 在符号链接阶段已完成但重新启动尚未开始时运行。
+ `after_restart.rb` 在重新启动阶段完成后运行。

Chef 部署挂钩可使用标准节点语法访问节点对象，就像配方一样。部署挂钩还可访问您已指定的任何[应用程序环境变量](workingapps-creating.md#workingapps-creating-environment)的值。但是，您必须使用 `new_resource.environment["VARIABLE_NAME"] ` 访问该变量的值，而不是使用 `ENV["VARIABLE_NAME"]`。

# 在 Linux 实例上运行 Cron 作业


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

Linux cron 作业指示 cron 守护程序按指定的时间表运行一个或多个命令。例如，假设您的堆栈支持某个 PHP 电子商务应用程序。您可以设置一个 cron 作业来让服务器在每周的指定时间向您发送销售报告。有关 cron 的更多信息，请参阅 Wikipedia 上的 [cron](http://en.wikipedia.org/wiki/Cron)。有关如何直接在基于 Linux 的计算机或实例上运行 cron 任务的更多信息，请参阅印第安纳大学知识库网站上的[什么是 cron 和 crontab 以及如何使用它们？](https://kb.iu.edu/d/afiz)

尽管您可以通过使用 SSH 连接到 `cron` 任务并编辑其 `crontab` 条目来在各个基于 Linux 的实例上手动设置这些任务，但 OpsWorks Stacks 的关键优势在于您可以指示它跨整层的实例运行该任务。以下过程将介绍如何在 PHP App Server 层的实例上设置 `cron` 任务，但您可以对任何层使用同一方法。

**在层的实例上设置 `cron` 作业**

1. 使用设置作业的 `cron` 资源实施一个包含配方的说明书。该示例假定配方已命名为 `cronjob.rb`；实施详细信息如下文所述。有关说明书和配方的更多信息，请参阅[说明书和诀窍](workingcookbook.md)。

1. 在堆栈上安装说明书。有关更多信息，请参阅 [安装自定义说明书](workingcookbook-installingcustom-enable.md)。

1. 通过将配方分配给以下生命周期事件，让 OpsWorks Stacks 在层的实例上自动运行配方。有关更多信息，请参阅 [自动运行配方](workingcookbook-assigningcustom.md)。
   + **设置** — `cronjob.rb` 为该事件分配指示 OpsWorks Stacks 在所有新实例上运行配方。
   + **部署**-分配`cronjob.rb`给此事件会指示 OpsWorks Stacks 在您将应用程序部署或重新部署到该层时在所有在线实例上运行配方。

   您也可以使用 `Execute Recipes` 堆栈命令来在联机实例上手动运行该配方。有关更多信息，请参阅 [运行堆栈命令](workingstacks-commands.md)。

下面是 `cronjob.rb` 示例，该示例设置了一个 cron 作业来每周运行一次用户实施的 PHP 应用程序，该应用程序将从服务器收集销售数据并通过电子邮件发送报告。有关如何使用 cron 资源的更多示例，请参阅 [cron](https://docs.chef.io/chef/resources.html#cron)。

```
cron "job_name" do
  hour "1"
  minute "10"
  weekday "6"
  command "cd /srv/www/myapp/current && php .lib/mailing.php"
end
```

`cron` 是一种表示 `cron` 作业的 Chef 资源。当 OpsWorks Stacks 在实例上运行配方时，相关的提供商会处理设置任务的细节。
+ `job_name` 是 `cron` 作业的用户定义的名称（如 `weekly report`）。
+ `hour`/`minute`/`weekday` 指定这些命令应在何时运行。本示例在每周六凌晨 1:10 运行这些命令。
+ `command` 指定要运行的命令。

  本示例运行两个命令。首先导航到 `/srv/www/myapp/current` 目录。第二个命令运行用户实施的 `mailing.php` 应用程序，该应用程序将收集销售数据并发送报告。

**注意**  
默认情况下，`bundle` 命令不适用于 `cron` 作业。原因是 OpsWorks Stacks 在目录中安装了`/usr/local/bin`捆绑器。要将 `bundle` 与 `cron` 作业结合使用，您必须将路径 `/usr/local/bin` 显式添加到 cron 作业。此外，由于 \$1PATH 环境变量不能在 `cron` 作业中扩展，因此最佳实践是将所有必需的路径信息显式添加到该作业而不依赖于 \$1PATH 变量的扩展。以下示例显示了在 `cron` 中使用 `bundle` 作业的两种方法。  

```
cron "my first task" do
  path "/usr/local/bin"
  minute "*/10"
  command "cd /srv/www/myapp/current && bundle exec my_command"
end
```

```
cron_env = {"PATH" => "/usr/local/bin"}
cron "my second task" do
  environment cron_env
  minute "*/10"
  command "cd /srv/www/myapp/current && /usr/local/bin/bundle exec my_command"
end
```

如果您的堆栈具有多个应用程序服务器，则将 `cronjob.rb` 分配到 PHP App Server 层的生命周期事件可能不是理想方法。例如，配方在层的所有实例上运行，因此您将收到多个报告。更好的方法是使用自定义层来确保只有一台服务器发送报告。

**仅在层的其中一个实例上运行配方**

1. 例如，创建一个名为的自定义层， PHPAdmin 并将其分配`cronjob.rb`给其设置和部署事件。自定义层不一定要执行很多操作。在这种情况下， PHPAdmin 只需在其实例上运行一个自定义配方即可。

1. 将其中一个 PHP 应用服务器实例分配给 AdminLayer。如果一个实例属于多个图层， OpsWorks Stacks 会运行每个层的内置和自定义配方。

由于只有一个实例属于 PHP App Server 和 PHPAdmin 层，因此只能在该实例上`cronjob.rb`运行，并且您只会收到一份报告。

# 在 Linux 实例上安装和配置程序包


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

内置层仅支持特定程序包。有关更多信息，请参阅 [图层](workinglayers.md)。您可以通过实施处理关联的设置、配置和部署任务的自定义配方来安装其他程序包 (如 Redis 服务器)。在某些情况下，最佳方法是扩展内置层以便让该层在其实例上安装该程序包以及该层的标准程序包。例如，如果您有一个支持 PHP 应用程序的堆栈，并且您想要包含 Redis 服务器，则可以扩展 PHP App Server 层以在该层的实例上安装和配置 Redis 服务器以及 PHP 应用程序服务器。

程序包安装配方通常需要执行如下任务：
+ 创建一个或多个目录并设置其模式。
+ 基于模板创建配置文件。
+ 运行安装程序以在实例上安装程序包。
+ 启动一个或多个服务。

有关如何安装 Tomcat 服务器的示例，请参阅[创建自定义 Tomcat 服务器层](create-custom.md)。该主题介绍了如何设置自定义 Redis 层，但您可使用大致相同的代码在内置层上安装和配置 Redis。有关如何安装其他软件包的示例，请参阅 [https://github.com/aws/op](https://github.com/aws/opsworks-cookbooks) sworks-cookbooks 上的内置食谱。