

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

# AppSpec 文件结构
<a name="reference-appspec-file-structure"></a>

以下是用于部署到 AWS Lambda 和 EC2/本地计算平台的 AppSpec 文件的高级结构。

除非另有说明，否则 YAML 格式 AppSpec 文件中的字符串值不得用引号 (“”) 括起来。

## AppSpec Amazon ECS 部署的文件结构
<a name="ecs-appspec-structure"></a>

**注意**  
这个 AppSpec 文件是用 YAML 编写的，但你可以使用相同的结构用 JSON 写一个。JSON 格式 AppSpec 文件中的字符串总是用引号 (“”) 括起来。

```
version: 0.0
resources: 
  ecs-service-specifications
hooks: 
  deployment-lifecycle-event-mappings
```

在此结构中：

** **版本** **  
本节指定 AppSpec 文件的版本。请勿更改此值。这是必需的。当前，允许的唯一值为 **0.0**。它由保留 CodeDeploy 以备将来使用。  
使用字符串指定 **version**。

** **resources** **  
此部分指定有关要部署的 Amazon ECS 应用程序的信息。  
有关更多信息，请参阅 [AppSpec Amazon ECS 部署的 “资源” 部分](reference-appspec-file-structure-resources.md#reference-appspec-file-structure-resources-ecs)。

** **hooks** **  
此部分指定用于运行特定部署生命周期事件挂钩以验证部署的 Lambda 函数。  
有关更多信息，请参阅 [用于 Amazon ECS 部署的生命周期事件挂钩的列表](reference-appspec-file-structure-hooks.md#reference-appspec-file-structure-hooks-list-ecs)。

## AppSpec AWS Lambda 部署的文件结构
<a name="lambda-appspec-structure"></a>

**注意**  
此 AppSpec 文件是用 YAML 编写的，但您可以使用相同的结构为 JSON 的 Lambda 部署写入 AppSpec 文件。JSON 格式 AppSpec 文件中的字符串总是用引号 (“”) 括起来。

```
version: 0.0
resources: 
  lambda-function-specifications
hooks: 
  deployment-lifecycle-event-mappings
```

在此结构中：

** **版本** **  
本节指定 AppSpec 文件的版本。请勿更改此值。这是必需的。当前，允许的唯一值为 **0.0**。它由保留 CodeDeploy 以备将来使用。  
使用字符串指定 **version**。

** **resources** **  
此部分指定有关要部署的 Lambda 函数的信息。  
有关更多信息，请参阅 [AppSpec “资源” 部分（仅限 Amazon ECS 和 AWS Lambda 部署）](reference-appspec-file-structure-resources.md)。

** **hooks** **  
此部分指定用于运行特定部署生命周期事件以验证部署的 Lambda 函数。  
有关更多信息，请参阅 [AppSpec “挂钩” 部分](reference-appspec-file-structure-hooks.md)。

## AppSpec EC2/本地部署的文件结构
<a name="server-appspec-structure"></a>

```
version: 0.0
os: operating-system-name
files:
  source-destination-files-mappings
permissions:
  permissions-specifications
hooks:
  deployment-lifecycle-event-mappings
```

在此结构中：

** **版本** **  
本节指定 AppSpec 文件的版本。请勿更改此值。这是必需的。当前，允许的唯一值为 **0.0**。它由保留 CodeDeploy 以备将来使用。  
使用字符串指定 **version**。

** **os** **  
本部分指定您部署到的实例的操作系统值。这是必需的。可以指定以下值：  
+ **linux** - 实例是 Amazon Linux, Ubuntu Server 或 RHEL 实例。
+ **windows** - 实例是 Windows Server 实例。
使用字符串指定 **os**。

** **files** **  
此部分指定应在部署的 **Install** 事件期间复制到实例的文件的名称。  
有关更多信息，请参阅 [AppSpec “文件” 部分（仅限 EC2/本地部署）](reference-appspec-file-structure-files.md)。

** **permissions** **  
此部分指定在将 `files` 部分中的文件复制到实例时，应如何向这些文件应用特殊权限（如果有）。本节仅适用于 Amazon Linux、Ubuntu Server 和 Red Hat Enterprise Linux（RHEL）实例。  
有关更多信息，请参阅[AppSpec “权限” 部分（仅限 EC2/本地部署）](reference-appspec-file-structure-permissions.md)。

** **hooks** **  
此部分指定在部署期间的特定部署生命周期事件处运行的脚本。  
有关更多信息，请参阅 [AppSpec “挂钩” 部分](reference-appspec-file-structure-hooks.md)。

**Topics**
+ [AppSpec Amazon ECS 部署的文件结构](#ecs-appspec-structure)
+ [AppSpec AWS Lambda 部署的文件结构](#lambda-appspec-structure)
+ [AppSpec EC2/本地部署的文件结构](#server-appspec-structure)
+ [AppSpec “文件” 部分（仅限 EC2/本地部署）](reference-appspec-file-structure-files.md)
+ [AppSpec “资源” 部分（仅限 Amazon ECS 和 AWS Lambda 部署）](reference-appspec-file-structure-resources.md)
+ [AppSpec “权限” 部分（仅限 EC2/本地部署）](reference-appspec-file-structure-permissions.md)
+ [AppSpec “挂钩” 部分](reference-appspec-file-structure-hooks.md)

# AppSpec “文件” 部分（仅限 EC2/本地部署）
<a name="reference-appspec-file-structure-files"></a>

提供 CodeDeploy 有关在部署的 In **stall** 事件期间应在实例上安装应用程序修订版中的哪些文件的信息。仅当您要在部署期间将修订中的文件复制到实例上的位置时，才需要此部分。

此部分具有以下结构：

```
files:
  - source: source-file-location-1
    destination: destination-file-location-1
file_exists_behavior: DISALLOW|OVERWRITE|RETAIN
```

可以设置多个 `destination` 和 `source` 对。

`source` 指令标识要从修订复制到实例的文件或目录：
+ 如果 `source` 指的是文件，则仅将指定的文件复制到实例。
+ 如果 `source` 指的是目录，则将该目录中的所有文件都复制到实例。
+ 如果 `source` 是一个单斜杠（对于 Amazon Linux、RHEL 和 Ubuntu Server 实例，为“/”；对于 Windows Server 实例，为“\$1”），则将修订中的所有文件都复制到实例。

`source` 中使用的路径是相对于 `appspec.yml` 文件的路径，该文件应位于修订的根目录。有关修订文件结构的详细信息，请参阅[为 CodeDeploy 规划修订](application-revisions-plan.md)。

`destination` 指令标识应将文件复制到的实例上的位置。这必须是完全限定的路径，例如 `/root/destination/directory`（在 Linux、RHEL 和 Ubuntu 上）或 `c:\destination\folder`（在 Windows 上）。

`source` 和 `destination` 分别使用字符串指定。

该`file_exists_behavior`指令是可选的，它指定如何 CodeDeploy处理已存在于部署目标位置但不属于先前成功部署的文件。此设置可以是以下值之一：
+ DISALLOW：部署失败。这也是未指定选项时的默认行为。
+ OVERWRITE：当前正在部署的应用程序修订的文件版本将替换实例上已有的版本。
+ RETAIN：保留实例上已有的文件版本，并将其用作新部署的一部分。

使用 `file_exists_behavior` 设置时，请了解此设置：
+ 只能指定一次，并且适用于 `files:` 下列出的所有文件和目录。
+ 优先于`--file-exists-behavior` AWS CLI 选项和 `fileExistsBehavior` API 选项（两者也是可选的）。

以下是 Amazon Linux、Ubuntu Server 或 RHEL 实例的示例 `files` 部分。

```
files:
  - source: Config/config.txt
    destination: /webapps/Config
  - source: source
    destination: /webapps/myApp
```

在此示例中，将在 **Install** 事件期间执行下面两个操作：

1. 将修订中的 `Config/config.txt` 文件复制到实例上的 `/webapps/Config/config.txt` 路径中。

1. 以递归方式将修订的 `source` 目录中的所有文件复制到实例上的 `/webapps/myApp` 目录中。

## “files”部分示例
<a name="reference-appspec-file-structure-files-examples"></a>

以下示例显示了如何指定 `files` 部分。尽管这些示例描述的是 Windows Server 文件和目录（文件夹）结构，但是它们可轻松适合于 Amazon Linux、Ubuntu Server 和 RHEL 实例。

**注意**  
只有 EC2/本地部署使用 `files` 部分。它不适用于 AWS Lambda 部署。

对于以下示例，我们假设这些文件出现在 `source` 的根的捆绑包中：
+ `appspec.yml`
+ `my-file.txt`
+ `my-file-2.txt`
+ `my-file-3.txt`

```
# 1) Copy only my-file.txt to the destination folder c:\temp.
#
files:
  - source: .\my-file.txt
    destination: c:\temp
#
# Result:
#   c:\temp\my-file.txt
#
# ---------------------
#
# 2) Copy only my-file-2.txt and my-file-3.txt to the destination folder c:\temp.
#
files:
  - source: my-file-2.txt
    destination: c:\temp
  - source: my-file-3.txt
    destination: c:\temp
#
# Result:
#   c:\temp\my-file-2.txt
#   c:\temp\my-file-3.txt
#
# ---------------------
#
# 3) Copy my-file.txt, my-file-2.txt, and my-file-3.txt (along with the appspec.yml file) to the destination folder c:\temp.
#
files:
  - source: \
    destination: c:\temp
#
# Result:
#   c:\temp\appspec.yml
#   c:\temp\my-file.txt
#   c:\temp\my-file-2.txt
#   c:\temp\my-file-3.txt
```

对于以下示例，我们假设 `appspec.yml` 与包含三个文件的名为 `my-folder` 的文件夹一起出现在 `source` 的根的捆绑包中：
+ `appspec.yml`
+ `my-folder\my-file.txt`
+ `my-folder\my-file-2.txt`
+ `my-folder\my-file-3.txt`

```
# 4) Copy the 3 files in my-folder (but do not copy my-folder itself) to the destination folder c:\temp. 
#
files:
  - source: .\my-folder
    destination: c:\temp
#
# Result:
#   c:\temp\my-file.txt
#   c:\temp\my-file-2.txt
#   c:\temp\my-file-3.txt
#
# ---------------------
#
# 5) Copy my-folder and its 3 files to my-folder within the destination folder c:\temp.
#
files:
  - source: .\my-folder
    destination: c:\temp\my-folder
#
# Result:
#   c:\temp\my-folder\my-file.txt
#   c:\temp\my-folder\my-file-2.txt
#   c:\temp\my-folder\my-file-3.txt
#
# ---------------------
#
# 6) Copy the 3 files in my-folder to other-folder within the destination folder c:\temp.
#
files:
  - source: .\my-folder
    destination: c:\temp\other-folder
#
# Result:
#   c:\temp\other-folder\my-file.txt
#   c:\temp\other-folder\my-file-2.txt
#   c:\temp\other-folder\my-file-3.txt	
#
# ---------------------
#
# 7) Copy only my-file-2.txt and my-file-3.txt to my-folder within the destination folder c:\temp.
#
files:
  - source: .\my-folder\my-file-2.txt
    destination: c:\temp\my-folder
  - source: .\my-folder\my-file-3.txt
    destination: c:\temp\my-folder
#
# Result:
#   c:\temp\my-folder\my-file-2.txt
#   c:\temp\my-folder\my-file-3.txt
#
# ---------------------
#
# 8) Copy only my-file-2.txt and my-file-3.txt to other-folder within the destination folder c:\temp.
#
files:
  - source: .\my-folder\my-file-2.txt
    destination: c:\temp\other-folder
  - source: .\my-folder\my-file-3.txt
    destination: c:\temp\other-folder
#
# Result:
#   c:\temp\other-folder\my-file-2.txt
#   c:\temp\other-folder\my-file-3.txt
#
# ---------------------
#
# 9) Copy my-folder and its 3 files (along with the appspec.yml file) to the destination folder c:\temp. If any of the files already exist on the instance, overwrite them.
#
files:
  - source: \
    destination: c:\temp
file_exists_behavior: OVERWRITE
#
# Result:
#   c:\temp\appspec.yml
#   c:\temp\my-folder\my-file.txt
#   c:\temp\my-folder\my-file-2.txt
#   c:\temp\my-folder\my-file-3.txt
```

# AppSpec “资源” 部分（仅限 Amazon ECS 和 AWS Lambda 部署）
<a name="reference-appspec-file-structure-resources"></a>

 AppSpec 文件`'resources'`部分的内容因部署的计算平台而异。Amazon ECS 部署的 `'resources'` 部分包含 Amazon ECS 任务定义、用于将流量路由到更新的 Amazon ECS 任务集的容器和端口以及其他可选信息。 AWS Lambda 部署`'resources'`部分包含 Lambda 函数的名称、别名、当前版本和目标版本。

**Topics**
+ [AppSpec AWS Lambda 部署的 “资源” 部分](#reference-appspec-file-structure-resources-lambda)
+ [AppSpec Amazon ECS 部署的 “资源” 部分](#reference-appspec-file-structure-resources-ecs)

## AppSpec AWS Lambda 部署的 “资源” 部分
<a name="reference-appspec-file-structure-resources-lambda"></a>

`'resources'` 部分指定要部署的 Lambda 函数，并具有以下结构：

YAML：

```
resources:
  - name-of-function-to-deploy:
      type: "AWS::Lambda::Function"
      properties:
        name: name-of-lambda-function-to-deploy
        alias: alias-of-lambda-function-to-deploy
        currentversion: version-of-the-lambda-function-traffic-currently-points-to
        targetversion: version-of-the-lambda-function-to-shift-traffic-to
```

JSON:

```
"resources": [
    {
        "name-of-function-to-deploy" {
            "type": "AWS::Lambda::Function",
            "properties": {
                "name": "name-of-lambda-function-to-deploy",
                "alias": "alias-of-lambda-function-to-deploy",
                "currentversion": "version-of-the-lambda-function-traffic-currently-points-to",
                "targetversion": "version-of-the-lambda-function-to-shift-traffic-to"
            }
        }
    }
]
```

每个属性均使用字符串指定。
+ `name` – 必需。这是要部署的 Lambda 函数的名称。
+ `alias` – 必需。这是 Lambda 函数的别名。
+ `currentversion` – 必需。这是流量当前定向到的 Lambda 函数版本。此值必须为有效的正整数。
+ `targetversion` – 必需。这是流量要转移到的 Lambda 函数版本。此值必须为有效的正整数。

## AppSpec Amazon ECS 部署的 “资源” 部分
<a name="reference-appspec-file-structure-resources-ecs"></a>

 `'resources'` 部分指定要部署的 Amazon ECS 服务，并具有以下结构：

YAML：

```
Resources:
  - TargetService:
      Type: AWS::ECS::Service
      Properties:
        TaskDefinition: "task-definition-arn"
        LoadBalancerInfo: 
          ContainerName: "ecs-container-name" 
          ContainerPort: "ecs-application-port"
# Optional properties
        PlatformVersion: "ecs-service-platform-version"
        NetworkConfiguration:
          AwsvpcConfiguration:
            Subnets: ["ecs-subnet-1","ecs-subnet-n"] 
            SecurityGroups: ["ecs-security-group-1","ecs-security-group-n"] 
            AssignPublicIp: "ENABLED | DISABLED"
        CapacityProviderStrategy:
          - Base: integer
            CapacityProvider: "capacityProviderA"
            Weight: integer
          - Base: integer
            CapacityProvider: "capacityProviderB"
            Weight: integer
```

JSON:

```
"Resources": [
    {
        "TargetService": {
            "Type": "AWS::ECS::Service",
            "Properties": {
                "TaskDefinition": "task-definition-arn",
                "LoadBalancerInfo": {
                    "ContainerName": "ecs-container-name",
                    "ContainerPort": "ecs-application-port"
                },
                "PlatformVersion": "ecs-service-platform-version",
                "NetworkConfiguration": {
                    "AwsvpcConfiguration": {
                        "Subnets": [
                            "ecs-subnet-1",
                            "ecs-subnet-n"
                        ],
                        "SecurityGroups": [
                            "ecs-security-group-1",
                            "ecs-security-group-n"
                        ],
                        "AssignPublicIp": "ENABLED | DISABLED"
                    }
                },
                "CapacityProviderStrategy": [
                    {
                        "Base": integer,
                        "CapacityProvider": "capacityProviderA",
                        "Weight": integer
                    },
                    {
                        "Base": integer,
                        "CapacityProvider": "capacityProviderB",
                        "Weight": integer
                    }
                ]
            }
        }
    }
]
```

每个属性都使用字符串指定，但 `ContainerPort` 除外，它是一个数字。
+ `TaskDefinition` – 必需。这是要部署的 Amazon ECS 服务的任务定义。它是使用任务定义的 ARN 指定的。ARN 格式为 `arn:aws:ecs:aws-region:account-id:task-definition/task-definition-family:task-definition-revision`。有关更多信息，请参阅 [Amazon 资源名称 (ARNs) 和 AWS 服务命名空间](https://docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html)。
**注意**  
ARN 的 `:task-definition-revision` 部分是可选的。如果省略该部分，则 Amazon ECS 将使用任务定义的最新 ACTIVE 修订。
+ `ContainerName` – 必需。这是包含 Amazon ECS 应用程序的 Amazon ECS 容器名称。它必须是在 Amazon ECS 任务定义中指定的容器。
+ `ContainerPort` – 必需。这是流量将被路由到的容器上的端口。
+ `PlatformVersion`: 可选。已部署的 Amazon ECS 服务中 Fargate 任务的平台版本。有关平台版本的更多信息，请参阅 [AWS Fargate 平台版本](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/platform_versions.html)。如果没有指定任何版本，将默认使用 `LATEST`。
+  `NetworkConfiguration`: 可选。在 `AwsvpcConfiguration` 下，您可以指定以下设置。有关更多信息，请参阅 *Amazon ECS 容器服务 API 参考[AwsVpcConfiguration](https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_AwsVpcConfiguration.html)*中的。
  + `Subnets`: 可选。Amazon ECS 服务中一个或多个子网的逗号分隔列表。
  + `SecurityGroups`: 可选。Amazon Elastic Container Service 中一个或多个安全组的逗号分隔列表。
  + `AssignPublicIp`: 可选。一个字符串，它指定 Amazon ECS 服务的弹性网络接口是否接收公有 IP 地址。有效值为 `ENABLED` 和 `DISABLED`。
**注意**  
 必须指定 `NetworkConfiguration` 下的所有设置或不指定任何设置。例如，如果您要指定 `Subnets`，那么还必须指定 `SecurityGroups` 和 `AssignPublicIp`。如果未指定，则 CodeDeploy 使用当前的网络 Amazon ECS 设置。
+ `CapacityProviderStrategy`: 可选。您要用于部署的 Amazon ECS 容量提供程序的列表。有关更多信息，请参阅《Amazon Elastic Container Service 开发人员指南》**中的 [Amazon ECS 容量提供程序](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/cluster-capacity-providers.html)。对于每个容量提供程序，您可以指定以下设置。有关这些设置的详细信息，请参阅《*AWS CloudFormation 用户指南》[AWS::ECS::ServiceCapacityProviderStrategyItem](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ecs-service-capacityproviderstrategyitem.html)*中的
  + `Base`: 可选。基准值指明在指定的容量提供程序上至少运行多少个任务。在一个容量提供程序策略中，只能有一个容量提供程序策略定义了基准。如果未指定值，则使用默认值 0。
  + `CapacityProvider`: 可选。容量提供程序的简称。示例：*capacityProviderA*
  + `Weight`: 可选。

    *权重* 值指明应使用指定容量提供程序的已启动任务总数的相对百分比。在满足了 `base` 值（如果定义）之后，将考虑 `weight` 值。

    如果未指定 `weight` 值，则使用默认值 `0`。如果在容量提供程序策略中指定了多个容量提供程序，则至少有一个容量提供程序的权重值必须大于零，且任何权重为 `0` 的容量提供程序都不会被用来放置任务。如果您在策略中指定的多个容量提供程序的权重全部为 `0`，则使用该容量提供程序策略的任何 `RunTask` 或 `CreateService` 操作都将失败。

     下面是使用权重的示例情景：定义的策略包含两个容量提供程序，并且两个容量提供程序的权重均为 `1`，那么当满足 `base` 时，这些任务将在两个容量提供程序之间均匀分配。按照相同的逻辑，如果您为 *capacityProviderA* 指定权重 `1`，并为 *capacityProviderB* 指定权重 `4`，那么运行的每一个任务均使用 *capacityProviderA*，四个任务将使用 *capacityProviderB*。

# AppSpec “权限” 部分（仅限 EC2/本地部署）
<a name="reference-appspec-file-structure-permissions"></a>

该`'permissions'`部分指定了应如何将特殊权限（如果有）应用于文件以及 directories/folders 将文件复制到实例后的`'files'`部分。您可以指定多个 `object` 指令。此部分是可选的。它仅适用于 Amazon Linux、Ubuntu Server 和 RHEL 实例。

**注意**  
`'permissions'` 部分仅用于 EC2/本地部署。它不用于 AWS Lambda 或 Amazon ECS 部署。

此部分具有以下结构：

```
permissions:
  - object: object-specification
    pattern: pattern-specification
    except: exception-specification
    owner: owner-account-name
    group: group-name
    mode: mode-specification
    acls: 
      - acls-specification 
    context:
      user: user-specification
      type: type-specification
      range: range-specification
    type:
      - object-type
```

这些指令如下所示：
+ `object` – 必需。这是一组文件系统对象（文件或目录/文件夹），这些文件系统对象复制到实例之后，将向其应用指定的权限。

  使用字符串指定 `object`。
+ `pattern`：可选。指定权限应用模式。如果未指定或使用特殊字符 **"\$1\$1"** 指定，则权限将应用于所有匹配的文件或目录，具体取决于 `type`。

  使用带引号（""）的字符串指定 `pattern`。
+ `except`：可选。指定对于 `pattern` 而言例外的所有文件或目录。

  使用包含在方括号内的一组逗号分隔的字符串指定 `except`。
+ `owner`：可选。`object` 所有者的名称。如果未指定，则在执行复制操作之后，应用于原始文件或目录/文件夹结构的所有现有所有者将保持不变。

  使用字符串指定 `owner`。
+ `group`：可选。`object` 组的名称。如果未指定，则在执行复制操作之后，应用于原始文件或目录/文件夹结构的所有现有组将保持不变。

  使用字符串指定 `group`。
+ `mode`：可选。一个数值，用于指定要应用于 `object` 的权限。模式设置遵循 Linux chmod 命令语法。
**重要**  
如果该值包含前导零，则必须用双引号将其括起来，或者删除前导零，以便只保留三位数字。
**注意**  
`mode` 设置不支持诸如 **u\$1x** 之类的符号。

  示例：
  + `mode: "0644"` 向对象的所有者授予读写权限（6），为群组授予只读权限（4），向所有其他用户授予只读权限（4）。
  + `mode: 644` 授予与 `mode: "0644"` 相同的权限。
  + `mode: 4755` 设置 setuid 属性（4），向所有者授予完全控制权限（7），向群组授予读取和执行权限（5），并向所有其他用户授予读取和执行权限（5）。

    （有关更多示例，请参阅 Linux chmod 命令文档。）

    如果未指定 mode，则在执行复制操作之后，应用于原始文件或文件夹结构的所有现有模式将保持不变。
+ `acls`：可选。一个字符串列表，表示应用于 `object` 的一个或多个访问控制列表（ACL）条目。例如，**u:bob:rw** 代表用户 **bob** 的读写权限。（有关更多示例，请参阅 Linux `setfacl` 命令文档中的 ACL 条目格式示例。） 您可以指定多个 ACL 条目。如果未指定，`acls`则在执行复制操作后， ACLs 应用于原始文件或 directory/folder 结构的任何现有文件或结构将保持不变。它们取代了任何现有 ACLs的。

  使用短划线（-）后跟空格和字符串的形式指定 `acls`（例如，`- u:jane:rw`）。如果您有多个 ACL，每个 ACL 在单独的行中指定。
**注意**  
设置未命名的用户、未命名的群组或其他类似的 ACL 条目会导致 AppSpec 文件失败。可改用 `mode` 指定这些类型的权限。
+ `context`：可选。对于启用了安全增强型 Linux (SELinux) 的实例，将列出要应用于复制对象的安全相关上下文标签。标签被指定为包含 `user`、`type` 和 `range` 的关键字。（有关更多信息，请参阅 SELinux 文档。） 每个关键字使用一个字符串输入。如果未指定，则在执行复制操作后，应用于原始文件或 directory/folder 结构的所有现有标签将保持不变。
  + `user`：可选。 SELinux 用户。
  + `type`：可选。 SELinux 类型名称。
  + `range`：可选。 SELinux 范围说明符。这在计算机上启用 Multi-Level Security（MLS）和 Multi-Category Security（MCS）之后才生效。如果未启用，则 `range` 默认为 **s0**。

  使用字符串指定 `context`（例如， `user: unconfined_u`）。每个 `context` 在单独的行中指定。
+ `type`：可选。将指定权限应用到的对象类型。`type` 是可设置为 **file** 或 **directory** 的字符串。如果指定了 **file**，则在执行复制操作之后，权限将仅应用于 `object` 中直接包含的文件（不应用于 `object` 自身）。如果**directory**指定，则权限将递归地应用于复制操作`object`后任何位置的所有 directories/folders 内容（但不适用于其`object`本身）。

  使用短划线（-）后跟空格和字符串的形式指定 `type`（例如，`- file`）。

## “Permissions”部分示例
<a name="reference-appspec-file-structure-permissions-example"></a>

以下示例显示了如何使用 `object`、`pattern`、`except`、`owner`、`mode` 和 `type` 指令来指定 `'permissions'` 部分。此示例仅适用于 Amazon Linux、Ubuntu Server 和 RHEL 实例。在此示例中，假设以下文件和文件夹按此层次结构复制到实例：

```
/tmp
  `-- my-app
       |-- my-file-1.txt
       |-- my-file-2.txt
       |-- my-file-3.txt
       |-- my-folder-1
       |     |-- my-file-4.txt
       |     |-- my-file-5.txt
       |     `-- my-file-6.txt
       `-- my-folder-2
             |-- my-file-7.txt
             |-- my-file-8.txt
             |-- my-file-9.txt
	           `-- my-folder-3
```

以下 AppSpec 文件显示了如何在复制这些文件和文件夹后对其设置权限：

```
version: 0.0
os: linux
# Copy over all of the folders and files with the permissions they
#  were originally assigned.
files:
  - source: ./my-file-1.txt
    destination: /tmp/my-app
  - source: ./my-file-2.txt
    destination: /tmp/my-app
  - source: ./my-file-3.txt
    destination: /tmp/my-app
  - source: ./my-folder-1
    destination: /tmp/my-app/my-folder-1
  - source: ./my-folder-2
    destination: /tmp/my-app/my-folder-2
# 1) For all of the files in the /tmp/my-app folder ending in -3.txt
#  (for example, just my-file-3.txt), owner = adm, group = wheel, and
#  mode = 464 (-r--rw-r--).
permissions:
  - object: /tmp/my-app
    pattern: "*-3.txt"
    owner: adm
    group: wheel
    mode: 464
    type:
      - file
# 2) For all of the files ending in .txt in the /tmp/my-app
#  folder, but not for the file my-file-3.txt (for example,
#  just my-file-1.txt and my-file-2.txt),
#  owner = ec2-user and mode = 444 (-r--r--r--).
  - object: /tmp/my-app
    pattern: "*.txt"
    except: [my-file-3.txt]
    owner: ec2-user
    mode: 444
    type:
      - file
# 3) For all the files in the /tmp/my-app/my-folder-1 folder except
#  for my-file-4.txt and my-file-5.txt, (for example,
#  just my-file-6.txt), owner = operator and mode = 646 (-rw-r--rw-).
  - object: /tmp/my-app/my-folder-1
    pattern: "**"
    except: [my-file-4.txt, my-file-5.txt]
    owner: operator
    mode: 646
    type:
      - file
# 4) For all of the files that are immediately under
#  the /tmp/my-app/my-folder-2 folder except for my-file-8.txt,
#  (for example, just my-file-7.txt and
#  my-file-9.txt), owner = ec2-user and mode = 777 (-rwxrwxrwx).
  - object: /tmp/my-app/my-folder-2
    pattern: "**"
    except: [my-file-8.txt]
    owner: ec2-user
    mode: 777
    type:
      - file
# 5) For all folders at any level under /tmp/my-app that contain
#  the name my-folder but not
#  /tmp/my-app/my-folder-2/my-folder-3 (for example, just
#  /tmp/my-app/my-folder-1 and /tmp/my-app/my-folder-2),
#  owner = ec2-user and mode = 555 (dr-xr-xr-x).
  - object: /tmp/my-app
    pattern: "*my-folder*"
    except: [tmp/my-app/my-folder-2/my-folder-3]
    owner: ec2-user
    mode: 555
    type:
      - directory
# 6) For the folder /tmp/my-app/my-folder-2/my-folder-3,
#  group = wheel and mode = 564 (dr-xrw-r--).
  - object: /tmp/my-app/my-folder-2/my-folder-3
    group: wheel
    mode: 564
    type:
      - directory
```

生成的权限如下所示：

```
-r--r--r-- ec2-user root  my-file-1.txt
-r--r--r-- ec2-user root  my-file-2.txt
-r--rw-r-- adm      wheel my-file-3.txt

dr-xr-xr-x ec2-user root  my-folder-1
-rw-r--r-- root     root  my-file-4.txt
-rw-r--r-- root     root  my-file-5.txt
-rw-r--rw- operator root  my-file-6.txt

dr-xr-xr-x ec2-user root  my-folder-2
-rwxrwxrwx ec2-user root  my-file-7.txt
-rw-r--r-- root     root  my-file-8.txt
-rwxrwxrwx ec2-user root  my-file-9.txt

dr-xrw-r-- root     wheel my-folder-3
```

以下示例显示了如何通过添加 `acls` 和 `context` 指令来指定 `'permissions'` 部分。此示例仅适用于 Amazon Linux、Ubuntu Server 和 RHEL 实例。

```
permissions:
  - object: /var/www/html/WordPress
    pattern: "**"
    except: [/var/www/html/WordPress/ReadMe.txt]
    owner: bob
    group: writers
    mode: 644
    acls: 
      - u:mary:rw
      - u:sam:rw
      - m::rw
    context:
      user: unconfined_u
      type: httpd_sys_content_t
      range: s0
    type:
      - file
```

# AppSpec “挂钩” 部分
<a name="reference-appspec-file-structure-hooks"></a>

 AppSpec 文件`'hooks'`部分的内容因部署的计算平台而异。EC2/本地部署的 `'hooks'` 部分包含将部署生命周期事件挂钩链接到一个或多个脚本的映射。Lambda 或 Amazon ECS 部署的 `'hooks'` 部分指定在部署生命周期事件期间运行的 Lambda 验证函数。如果某个事件的挂钩不存在，则不会对该事件执行任何操作。仅当您将在部署过程中运行脚本或 Lambda 验证函数时，才需要此部分。

**Topics**
+ [AppSpec 亚马逊 ECS 部署的 “挂钩” 部分](#appspec-hooks-ecs)
+ [AppSpec AWS Lambda 部署的 “挂钩” 部分](#appspec-hooks-lambda)
+ [AppSpec EC2/本地部署的 “挂钩” 部分](#appspec-hooks-server)

## AppSpec 亚马逊 ECS 部署的 “挂钩” 部分
<a name="appspec-hooks-ecs"></a>

**Topics**
+ [用于 Amazon ECS 部署的生命周期事件挂钩的列表](#reference-appspec-file-structure-hooks-list-ecs)
+ [钩子在 Amazon ECS 部署中的运行顺序。](#reference-appspec-file-structure-hooks-run-order-ecs)
+ [“hooks”部分的结构](#reference-appspec-file-structure-hooks-section-structure-ecs)
+ [Lambda“hooks”函数示例](#reference-appspec-file-structure-hooks-section-structure-ecs-sample-function)

### 用于 Amazon ECS 部署的生命周期事件挂钩的列表
<a name="reference-appspec-file-structure-hooks-list-ecs"></a>

 AWS Lambda 挂钩是一个 Lambda 函数，在生命周期事件名称后的新行中使用字符串指定。对于每次部署，每个挂钩将执行一次。以下是在 Amazon ECS 部署期间可以运行挂钩的生命周期事件的描述。
+  `BeforeInstall` – 用于在创建替换任务集之前运行任务。一个目标组与原始任务集相关联。如果指定了可选的测试侦听器，则它与原始任务集相关联。此时，无法执行回滚。
+  `AfterInstall` – 用于在创建替换任务集并且其中一个目标组与之关联后运行任务。如果指定了可选的测试侦听器，则它与原始任务集相关联。在此生命周期事件时挂钩函数的运行结果可能会触发回滚。
+  `AfterAllowTestTraffic` – 用于在测试侦听器为替换任务集提供流量后运行任务。此时挂钩函数的运行结果可能会触发回滚。
+  `BeforeAllowTraffic` – 用于在第二个目标组与替换任务集关联之后但在流量转移到替换任务集之前运行任务。在此生命周期事件时挂钩函数的运行结果可能会触发回滚。
+  `AfterAllowTraffic` – 用于在第二个目标组为替换任务集提供流量后运行任务。在此生命周期事件时挂钩函数的运行结果可能会触发回滚。

有关更多信息，请参阅[在 Amazon ECS 部署过程中发生的事件](deployment-steps-ecs.md#deployment-steps-what-happens)和[教程：部署具有验证测试的 Amazon ECS 服务](tutorial-ecs-deployment-with-hooks.md)。

### 钩子在 Amazon ECS 部署中的运行顺序。
<a name="reference-appspec-file-structure-hooks-run-order-ecs"></a>

在 Amazon ECS 部署中，事件挂钩按以下顺序运行：

![\[事件钩子在 Amazon ECS 部署中的顺序。\]](http://docs.aws.amazon.com/zh_cn/codedeploy/latest/userguide/images/lifecycle-event-order-ecs.png)


**注意**  
部署中的 “**开始**” **TestTraffic**AllowTraffic****、“**安装**” 和 “**结束**” 事件无法编写脚本，这就是它们在此图中以灰色显示的原因。

### “hooks”部分的结构
<a name="reference-appspec-file-structure-hooks-section-structure-ecs"></a>

以下示例说明了 `'hooks'` 部分的结构。

使用 YAML：

```
Hooks:
  - BeforeInstall: "BeforeInstallHookFunctionName"
  - AfterInstall: "AfterInstallHookFunctionName"
  - AfterAllowTestTraffic: "AfterAllowTestTrafficHookFunctionName"
  - BeforeAllowTraffic: "BeforeAllowTrafficHookFunctionName"
  - AfterAllowTraffic: "AfterAllowTrafficHookFunctionName"
```

使用 JSON：

```
"Hooks": [
		{
			"BeforeInstall": "BeforeInstallHookFunctionName"
		},
		{
			"AfterInstall": "AfterInstallHookFunctionName"
		},
		{
			"AfterAllowTestTraffic": "AfterAllowTestTrafficHookFunctionName"
		},
		{
			"BeforeAllowTraffic": "BeforeAllowTrafficHookFunctionName"
		},
		{
			"AfterAllowTraffic": "AfterAllowTrafficHookFunctionName"
		}
	]
}
```

### Lambda“hooks”函数示例
<a name="reference-appspec-file-structure-hooks-section-structure-ecs-sample-function"></a>

使用该`'hooks'`部分指定一个 Lambda 函数，该函数 CodeDeploy 可以调用该函数来验证 Amazon ECS 部署。对于 `BeforeInstall`、`AfterInstall`、`AfterAllowTestTraffic`、`BeforeAllowTraffic` 和 `AfterAllowTraffic` 部署生命周期事件，您可以使用相同函数或不同的函数。验证测试完成后，Lambda `AfterAllowTraffic` 函数会回调 CodeDeploy并提供或的结果。`Succeeded` `Failed`

**重要**  
如果 Lambda 验证功能 CodeDeploy 未在一小时内发出通知，则认为部署已失败。

 在调用 Lambda 挂钩函数之前，必须使用 `putLifecycleEventHookExecutionStatus` 命令向服务器通知部署 ID 和生命周期事件挂钩执行 ID。

 下面是一个使用 Node.js 编写的 Lambda 挂钩函数示例。

```
'use strict';

const aws = require('aws-sdk');
const codedeploy = new aws.CodeDeploy({apiVersion: '2014-10-06'});

exports.handler = (event, context, callback) => {
    //Read the DeploymentId from the event payload.
    var deploymentId = event.DeploymentId;

    //Read the LifecycleEventHookExecutionId from the event payload
    var lifecycleEventHookExecutionId = event.LifecycleEventHookExecutionId;

    /*
     Enter validation tests here.
    */

    // Prepare the validation test results with the deploymentId and
    // the lifecycleEventHookExecutionId for CodeDeploy.
    var params = {
        deploymentId: deploymentId,
        lifecycleEventHookExecutionId: lifecycleEventHookExecutionId,
        status: 'Succeeded' // status can be 'Succeeded' or 'Failed'
    };
    
    // Pass CodeDeploy the prepared validation test results.
    codedeploy.putLifecycleEventHookExecutionStatus(params, function(err, data) {
        if (err) {
            // Validation failed.
            callback('Validation test failed');
        } else {
            // Validation succeeded.
            callback(null, 'Validation test succeeded');
        }
    });
};
```

## AppSpec AWS Lambda 部署的 “挂钩” 部分
<a name="appspec-hooks-lambda"></a>

**Topics**
+ [AWS Lambda 部署的生命周期事件挂钩列表](#reference-appspec-file-structure-hooks-list-lambda)
+ [挂钩在 Lambda 函数版本部署中的运行顺序](#reference-appspec-file-structure-hooks-run-order-lambda)
+ [“hooks”部分的结构](#reference-appspec-file-structure-hooks-section-structure-lambda)
+ [Lambda“hooks”函数示例](#reference-appspec-file-structure-hooks-section-structure-lambda-sample-function)

### AWS Lambda 部署的生命周期事件挂钩列表
<a name="reference-appspec-file-structure-hooks-list-lambda"></a>

 AWS Lambda 挂钩是一个 Lambda 函数，在生命周期事件名称后的新行中使用字符串指定。对于每次部署，每个挂钩将执行一次。以下是可在您的 AppSpec 文件中使用的挂钩的描述。
+ **BeforeAllowTraffic**— 用于在流量转移到已部署的 Lambda 函数版本之前运行任务。
+ **AfterAllowTraffic**— 用于在所有流量转移到已部署的 Lambda 函数版本后运行任务。

### 挂钩在 Lambda 函数版本部署中的运行顺序
<a name="reference-appspec-file-structure-hooks-run-order-lambda"></a>

在无服务器 Lambda 函数版本部署中，事件挂钩按以下顺序运行：

![\[事件钩子在 Lambda 部署中的顺序。\]](http://docs.aws.amazon.com/zh_cn/codedeploy/latest/userguide/images/lifecycle-event-order-lambda.png)


**注意**  
部署中的 “**开始**” **AllowTraffic**、“**结束**” 事件无法编写脚本，这就是它们在此图中以灰色显示的原因。

### “hooks”部分的结构
<a name="reference-appspec-file-structure-hooks-section-structure-lambda"></a>

以下示例说明了“hooks”部分的结构。

使用 YAML：

```
hooks:
   - BeforeAllowTraffic: BeforeAllowTrafficHookFunctionName
   - AfterAllowTraffic: AfterAllowTrafficHookFunctionName
```

使用 JSON：

```
"hooks": [{
    "BeforeAllowTraffic": "BeforeAllowTrafficHookFunctionName"
    },
    {
    "AfterAllowTraffic": "AfterAllowTrafficHookFunctionName"
}]
```

### Lambda“hooks”函数示例
<a name="reference-appspec-file-structure-hooks-section-structure-lambda-sample-function"></a>

使用 “挂钩” 部分指定一个 Lambda 函数，该函数 CodeDeploy 可以调用该函数来验证 Lambda 部署。对于 `BeforeAllowTraffic` 和 `AfterAllowTraffic` 部署生命周期事件，您可以使用相同函数或不同的函数。验证测试完成后，Lambda 验证函数会回调 CodeDeploy 并提供或的结果。`Succeeded` `Failed`

**重要**  
如果 Lambda 验证功能 CodeDeploy 未在一小时内发出通知，则认为部署已失败。

 在调用 Lambda 挂钩函数之前，必须使用 `putLifecycleEventHookExecutionStatus` 命令向服务器通知部署 ID 和生命周期事件挂钩执行 ID。

 下面是一个使用 Node.js 编写的 Lambda 挂钩函数示例。

```
'use strict';

const aws = require('aws-sdk');
const codedeploy = new aws.CodeDeploy({apiVersion: '2014-10-06'});

exports.handler = (event, context, callback) => {
    //Read the DeploymentId from the event payload.
    var deploymentId = event.DeploymentId;

    //Read the LifecycleEventHookExecutionId from the event payload
    var lifecycleEventHookExecutionId = event.LifecycleEventHookExecutionId;

    /*
     Enter validation tests here.
    */

    // Prepare the validation test results with the deploymentId and
    // the lifecycleEventHookExecutionId for CodeDeploy.
    var params = {
        deploymentId: deploymentId,
        lifecycleEventHookExecutionId: lifecycleEventHookExecutionId,
        status: 'Succeeded' // status can be 'Succeeded' or 'Failed'
    };
    
    // Pass CodeDeploy the prepared validation test results.
    codedeploy.putLifecycleEventHookExecutionStatus(params, function(err, data) {
        if (err) {
            // Validation failed.
            callback('Validation test failed');
        } else {
            // Validation succeeded.
            callback(null, 'Validation test succeeded');
        }
    });
};
```

## AppSpec EC2/本地部署的 “挂钩” 部分
<a name="appspec-hooks-server"></a>

**Topics**
+ [生命周期事件挂钩的列表](#reference-appspec-file-structure-hooks-list)
+ [生命周期事件挂钩可用性](#reference-appspec-file-structure-hooks-availability)
+ [挂钩在部署中的运行顺序](#reference-appspec-file-structure-hooks-run-order)
+ [“hooks”部分的结构](#reference-appspec-file-structure-hooks-section-structure)
+ [在挂钩脚本中引用文件](#codedeploy-agent-working-directory)
+ [挂钩的环境变量可用性](#reference-appspec-file-structure-environment-variable-availability)
+ [挂钩示例](#reference-appspec-file-structure-hooks-example)

### 生命周期事件挂钩的列表
<a name="reference-appspec-file-structure-hooks-list"></a>

对于实例的每次部署，EC2/本地部署挂钩执行一次。在一个挂钩中，可以指定运行一个或多个脚本。生命周期事件的每个挂钩在单独的行中使用字符串指定。以下是可在您的 AppSpec 文件中使用的挂钩的描述。

有关哪些生命周期事件挂钩对哪些部署和回滚类型有效的信息，请参阅[生命周期事件挂钩可用性](#reference-appspec-file-structure-hooks-availability)。
+ `ApplicationStop` – 此部署生命周期事件发生在下载应用程序修订之前。您可以为此事件指定脚本，以便从容地停止应用程序或在部署准备过程中删除当前已安装的软件包。用于此部署生命周期事件 AppSpec 的文件和脚本来自先前成功部署的应用程序修订版。
**注意**  
在部署到实例之前， AppSpec 文件不存在于该实例。因此，`ApplicationStop` 挂钩在您首次部署到实例时不会运行。您可以在第二次部署到实例时使用 `ApplicationStop` 挂钩。

   要确定上次成功部署的应用程序修订版的位置， CodeDeploy 代理会查找`deployment-group-id_last_successful_install`文件中列出的位置。此文件位于：

   Amazon Linux、Ubuntu Server 和 RHEL Amazon EC2 实例上的 `/opt/codedeploy-agent/deployment-root/deployment-instructions` 文件夹。

  Windows Server Amazon EC2 实例上的 `C:\ProgramData\Amazon\CodeDeploy\deployment-instructions` 文件夹。

  要对在 `ApplicationStop` 部署生命周期事件期间失败的部署进行故障排除，请参阅 [对失败 ApplicationStop BeforeBlockTraffic、或 AfterBlockTraffic 部署生命周期事件进行故障排除](troubleshooting-deployments.md#troubleshooting-deployments-lifecycle-event-failures)。
+ `DownloadBundle`— 在此部署生命周期事件中， CodeDeploy 代理会将应用程序修订文件复制到临时位置：

  Amazon Linux、Ubuntu Server 和 RHEL Amazon EC2 实例上的 `/opt/codedeploy-agent/deployment-root/deployment-group-id/deployment-id/deployment-archive` 文件夹。

  Windows Server Amazon EC2 实例上的 `C:\ProgramData\Amazon\CodeDeploy\deployment-group-id\deployment-id\deployment-archive` 文件夹。

  此事件是为 CodeDeploy 代理保留的，不能用于运行脚本。

  要对在 `DownloadBundle` 部署生命周期事件期间失败的部署进行故障排除，请参阅 [使用以下命令对失败的 DownloadBundle 部署生命周期事件进行故障排除 UnknownError：未打开供读取](troubleshooting-deployments.md#troubleshooting-deployments-downloadbundle)。
+ `BeforeInstall` – 您可以使用此部署生命周期事件执行预安装任务，例如解密文件和创建当前版本的备份。
+ `Install`— 在此部署生命周期事件中， CodeDeploy代理将修订文件从临时位置复制到最终目标文件夹。此事件是为 CodeDeploy 代理保留的，不能用于运行脚本。
+ `AfterInstall` – 您可以使用此部署生命周期事件执行配置应用程序或更改文件权限等任务。
+ `ApplicationStart` – 此部署生命周期事件通常用于重新启动在 `ApplicationStop` 期间停止的服务。
+ `ValidateService` – 这是最后一个部署生命周期事件。它用于验证部署已成功完成。
+ `BeforeBlockTraffic` – 在从负载均衡器取消注册实例之前，您可以使用此部署生命周期事件在这些实例上运行任务。

  要对在 `BeforeBlockTraffic` 部署生命周期事件期间失败的部署进行故障排除，请参阅 [对失败 ApplicationStop BeforeBlockTraffic、或 AfterBlockTraffic 部署生命周期事件进行故障排除](troubleshooting-deployments.md#troubleshooting-deployments-lifecycle-event-failures)。
+ `BlockTraffic` – 在此部署生命周期事件期间，阻止互联网流量访问当前正在处理流量的实例。此事件是为 CodeDeploy 代理保留的，不能用于运行脚本。
+ `AfterBlockTraffic` – 在从相应的负载均衡器取消注册实例之后，您可以使用此部署生命周期事件在这些实例上运行任务。

  要对在 `AfterBlockTraffic` 部署生命周期事件期间失败的部署进行故障排除，请参阅 [对失败 ApplicationStop BeforeBlockTraffic、或 AfterBlockTraffic 部署生命周期事件进行故障排除](troubleshooting-deployments.md#troubleshooting-deployments-lifecycle-event-failures)。
+ `BeforeAllowTraffic` – 在将实例注册到负载均衡器之前，您可以使用此部署生命周期事件在这些实例上运行任务。
+ `AllowTraffic` – 在此部署生命周期事件期间，允许互联网流量在部署后访问实例。此事件是为 CodeDeploy 代理保留的，不能用于运行脚本。
+ `AfterAllowTraffic` – 在将实例注册到负载均衡器之后，您可以使用此部署生命周期事件在这些实例上运行任务。

### 生命周期事件挂钩可用性
<a name="reference-appspec-file-structure-hooks-availability"></a>

下表列出了适用于每个部署和回滚方案的生命周期事件挂钩。


| 生命周期事件名称 | Auto Scaling 启动部署¹ | Auto Scaling 终止部署¹ | 就地部署² | 蓝/绿部署：原始实例 | 蓝/绿部署：替换实例 | 蓝/绿部署回滚：原始实例 | 蓝/绿部署回滚：替换实例 | 
| --- | --- | --- | --- | --- | --- | --- | --- | 
| ApplicationStop | ✓ | ✓ | ✓ |  | ✓ |  |  | 
| DownloadBundle³ | ✓ |  | ✓ |  | ✓ |  |  | 
| BeforeInstall | ✓ |  | ✓ |  | ✓ |  |  | 
| Install³ | ✓ |  | ✓ |  | ✓ |  |  | 
| AfterInstall | ✓ |  | ✓ |  | ✓ |  |  | 
| ApplicationStart | ✓ |  | ✓ |  | ✓ |  |  | 
| ValidateService | ✓ |  | ✓ |  | ✓ |  |  | 
| BeforeBlockTraffic |  | ✓ | ✓ | ✓ |  |  | ✓ | 
| BlockTraffic³ |  | ✓ | ✓ | ✓ |  |  | ✓ | 
| AfterBlockTraffic |  | ✓ | ✓ | ✓ |  |  | ✓ | 
| BeforeAllowTraffic | ✓ |  | ✓ |  | ✓ | ✓ |  | 
| AllowTraffic³ | ✓ |  | ✓ |  | ✓ | ✓ |  | 
| AfterAllowTraffic | ✓ |  | ✓ |  | ✓ | ✓ |  | 
|  ¹ 有关 Amazon EC2 Auto Scaling 部署的信息，请参阅 [Amazon EC2 Auto Scaling 是如何使用的 CodeDeploy](integrations-aws-auto-scaling.md#integrations-aws-auto-scaling-behaviors)。 ² 也适用于就地部署的回滚。 ³ 预留用于 CodeDeploy 操作。不能用于运行脚本。  | 

### 挂钩在部署中的运行顺序
<a name="reference-appspec-file-structure-hooks-run-order"></a>

**Auto Scaling 启动部署**

在 Auto Scaling 启动部署期间，按以下顺序 CodeDeploy 运行事件挂钩。

有关 Auto Scaling 启动部署的更多信息，请参阅 [Amazon EC2 Auto Scaling 是如何使用的 CodeDeploy](integrations-aws-auto-scaling.md#integrations-aws-auto-scaling-behaviors)。

![\[自动扩缩启动部署期间事件钩子的顺序。\]](http://docs.aws.amazon.com/zh_cn/codedeploy/latest/userguide/images/lifecycle-event-order-scale-out.png)


**注意**  
部署中的 “**开始**” **AllowTraffic**、“**安装**” 和 “**结束**” 事件无法编写脚本，这就是它们在此图中以灰色显示的原因。**DownloadBundle****但是，您可以编辑 AppSpec 文件`'files'`部分以指定在安装事件期间安装的内容。**

**Auto Scaling 终止部署**

在 Auto Scaling 终止部署期间，按以下顺序 CodeDeploy 运行事件挂钩。

有关 Auto Scaling 终止部署的更多信息，请参阅 [在 Auto Scaling 横向缩减事件期间启用终止部署](integrations-aws-auto-scaling.md#integrations-aws-auto-scaling-behaviors-hook-enable)。

![\[自动扩缩终止部署期间事件钩子的顺序。\]](http://docs.aws.amazon.com/zh_cn/codedeploy/latest/userguide/images/lifecycle-event-order-scale-in.png)


**注意**  
部署中的 “**开始**” **BlockTraffic**、“**结束**” 事件无法编写脚本，这就是它们在此图中以灰色显示的原因。

**就地部署**

在就地部署中（包括就地部署的回滚），事件挂钩按以下顺序运行：

**注意**  
对于就地部署，与阻止和允许流量相关的六个挂钩仅当您在部署组中指定 Elastic Load Balancing 中的经典负载均衡器、应用程序负载均衡器或网络负载均衡器时适用。

![\[就地部署回滚期间事件钩子的顺序。\]](http://docs.aws.amazon.com/zh_cn/codedeploy/latest/userguide/images/lifecycle-event-order-in-place.png)


**注意**  
部署中的 “**开始**”、“**安装**” 和 “**结束**” 事件无法编写脚本，这就是它们在此图中以灰色显示的原因。**DownloadBundle****但是，您可以编辑 AppSpec 文件`'files'`部分以指定在安装事件期间安装的内容。**

**蓝/绿部署**

在 blue/green 部署中，事件挂钩按以下顺序运行：

![\[blue/green 部署中事件挂钩的顺序。\]](http://docs.aws.amazon.com/zh_cn/codedeploy/latest/userguide/images/lifecycle-event-order-blue-green.png)


**注意**  
部署中的 “**开始**”、“**安装**” **BlockTraffic**AllowTraffic****、“、” 和 “**结束**” 事件无法编写脚本，这就是它们在此图中以灰色显示的原因。**DownloadBundle**但是，您可以编辑文件的 “文件” 部分， AppSpec 以指定在安装事件期间**安装**的内容。

### “hooks”部分的结构
<a name="reference-appspec-file-structure-hooks-section-structure"></a>

`'hooks'` 部分具有以下结构：

```
hooks:
   deployment-lifecycle-event-name:
     - location: script-location
       timeout: timeout-in-seconds
       runas: user-name
```

可以在 **hook** 条目中的部署生命周期事件名称后包括以下元素：

** 地点 **  
必需。修订的脚本文件包的位置。您在 `hooks` 部分中指定的脚本的位置是应用程序修订包根目录的相对路径。有关更多信息，请参阅 [为 CodeDeploy 规划修订](application-revisions-plan.md)。

** timeout **  
可选。在脚本被视为失败之前允许其执行的秒数。默认值为 3600 秒（1 小时）。  
3600 秒（1 小时）是允许每个部署生命周期事件脚本执行的最长时间。如果脚本超过此限制，则部署将停止，并且部署到实例将失败。确保在 **timeout** 中为每个部署生命周期事件的所有脚本指定的总秒数不超过此限制。

** runas **  
可选。运行脚本时要模拟的用户。默认情况下，这是在实例上运行的 CodeDeploy 代理。 CodeDeploy 不存储密码，因此，如果 **runas** 用户需要密码，则无法模拟该用户。此元素仅适用于 Amazon Linux 和 Ubuntu Server 实例。

### 在挂钩脚本中引用文件
<a name="codedeploy-agent-working-directory"></a>

如果您要按中所述将脚本连接到 CodeDeploy 生命周期事件[AppSpec “挂钩” 部分](#reference-appspec-file-structure-hooks)，并且想要在脚本中引用文件（例如`helper.sh`），则需要`helper.sh`使用以下命令进行指定：
+ （推荐）绝对路径。请参阅[使用绝对路径](#codedeploy-agent-working-dir-absolute)。
+ 相对路径。请参阅[使用相对路径](#codedeploy-agent-working-dir-relative)。

#### 使用绝对路径
<a name="codedeploy-agent-working-dir-absolute"></a>

要使用文件的*绝对*路径来引用文件，可以执行以下任一操作：
+ 在 AppSpec 文件`files`部分的`destination`属性中指定绝对路径。然后，在挂钩脚本中指定相同的绝对路径。有关更多信息，请参阅 [AppSpec “文件” 部分（仅限 EC2/本地部署）](reference-appspec-file-structure-files.md)。
+ 在挂钩脚本中指定一个动态绝对路径。有关更多信息，请参阅[部署存档位置](#codedeploy-agent-working-dir-archive)。

**部署存档位置**

在[DownloadBundle](#reference-appspec-file-structure-hooks-list)生命周期事件期间， CodeDeploy 代理会将要部署的[修订](application-revisions.md)提取到以下格式的目录中：

`root-directory/deployment-group-id/deployment-id/deployment-archive`

路径*root-directory*部分始终设置为下表所示的默认路径，或者由`:root_dir`配置设置控制。有关配置设置的更多信息，请参阅[CodeDeploy 代理配置参考](reference-agent-configuration.md)。


| 代理平台 | 默认根目录 | 
| --- | --- | 
| Linux – 所有 rpm 发行版 |  /opt/codedeploy-agent/deployment-root  | 
| Ubuntu Server – 所有 deb 发行版 |  /opt/codedeploy-agent/deployment-root  | 
| Windows Server |  %ProgramData%\$1Amazon\$1CodeDeploy  | 

从挂钩脚本中，您可以使用根目录路径以及 `DEPLOYMENT_ID` 和 `DEPLOYMENT_GROUP_ID` 环境变量访问当前的部署存档。有关您能使用的变量的更多信息，请参阅[挂钩的环境变量可用性](#reference-appspec-file-structure-environment-variable-availability)。

下面的示例介绍了如何在 Linux 上访问位于修订根目录下的 `data.json` 文件：

```
#!/bin/bash

rootDirectory="/opt/codedeploy-agent/deployment-root" # note: this will be different if you
                                                      # customize the :root_dir configuration
dataFile="$rootDirectory/$DEPLOYMENT_GROUP_ID/$DEPLOYMENT_ID/deployment-archive/data.json"
data=$(cat dataFile)
```

再举一个例子，介绍了如何在 Windows 上使用 Powershell 访问位于修订根目录下的 `data.json` 文件：

```
$rootDirectory="$env:ProgramData\Amazon\CodeDeploy" # note: this will be different if you
                                                    # customize the :root_dir configuration
$dataFile="$rootDirectory\$env:DEPLOYMENT_GROUP_ID\$env:DEPLOYMENT_ID\deployment-archive\data.json"
$data=(Get-Content $dataFile)
```

#### 使用相对路径
<a name="codedeploy-agent-working-dir-relative"></a>

要使用文件的*相对*路径来引用文件，你需要知道 CodeDeploy 代理的工作目录。文件路径是相对于该目录的。

下表显示了 CodeDeploy 代理的每个支持平台的工作目录。

[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/codedeploy/latest/userguide/reference-appspec-file-structure-hooks.html)

### 挂钩的环境变量可用性
<a name="reference-appspec-file-structure-environment-variable-availability"></a>

在每个部署生命周期事件期间，挂钩脚本可以访问以下环境变量：

** APPLICATION\$1NAME **  
属于当前部署一部分 CodeDeploy 的应用程序的名称（例如，`WordPress_App`）。

** DEPLOYMENT\$1ID **  
ID CodeDeploy 已分配给当前部署（例如，`d-AB1CDEF23`）。

** DEPLOYMENT\$1GROUP\$1NAME **  
属于当前部署一部分 CodeDeploy 的部署组的名称（例如`WordPress_DepGroup`）。

** DEPLOYMENT\$1GROUP\$1ID **  
属于当前部署一部分的部署组的 ID（例如，`b1a2189b-dd90-4ef5-8f40-4c1c5EXAMPLE`）。 CodeDeploy 

** LIFECYCLE\$1EVENT **  
当前部署生命周期事件的名称（例如 `AfterInstall`）。

这些是每个部署生命周期事件的本地环境变量。

 根据部署包的来源，还有其他环境变量可用于挂接脚本：

**来自 Amazon S3 的捆绑包**
+ **BUNDLE\$1BUCKET**

  从中下载部署包的 Amazon S3 存储桶的名称（例如 `my-s3-bucket`）。
+ **BUNDLE\$1KEY**

  Amazon S3 存储桶中下载的捆绑包的对象键（例如 `WordPress_App.zip`）。
+ **BUNDLE\$1VERSION**

  捆绑包的对象版本（例如 `3sL4kqtJlcpXroDTDmJ+rmSpXd3dIbrHY+MTRCxf3vjVBH40Nr8X8gdRQBpUMLUo`）。只有在 Amazon S3 存储桶启用了[对象版本控制](https://docs.aws.amazon.com/AmazonS3/latest/userguide/Versioning.html)时，才会设置此变量。
+ **BUNDLE\$1ETAG**

  捆绑包的对象 etag（例如，`b10a8db164e0754105b7a99be72e3fe5-4`）。

**捆绑包来自 GitHub**
+ **BUNDLE\$1COMMIT**

  Git 生成的捆绑包的 SHA256 提交哈希值（例如`d2a84f4b8b650937ec8f73cd8be2c74add5a911ba64df27458ed8229da804a26`）。

如果 **DEPLOYMENT\$1GROUP\$1NAME** 的值等于 `Staging`，则以下脚本会将 Apache HTTP 服务器上的侦听端口更改为 9090 而非 80。必须在 `BeforeInstall` 部署生命周期事件期间调用此脚本：

```
if [ "$DEPLOYMENT_GROUP_NAME" == "Staging" ]
then
    sed -i -e 's/Listen 80/Listen 9090/g' /etc/httpd/conf/httpd.conf
fi
```

如果 **DEPLOYMENT\$1GROUP\$1NAME** 环境变量的值等于 `Staging`，则以下脚本示例会将其错误日志中记录的消息的详细级别从警告更改为调试。必须在 `BeforeInstall` 部署生命周期事件期间调用此脚本：

```
if [ "$DEPLOYMENT_GROUP_NAME" == "Staging" ]
then
    sed -i -e 's/LogLevel warn/LogLevel debug/g' /etc/httpd/conf/httpd.conf
fi
```

以下脚本示例将指定网页中的文本替换为显示这些环境变量值的文本。必须在 `AfterInstall` 部署生命周期事件期间调用此脚本：

```
#!/usr/bin/python

import os
 
strToSearch="<h2>This application was deployed using CodeDeploy.</h2>"
strToReplace="<h2>This page for "+os.environ['APPLICATION_NAME']+" application and "+os.environ['DEPLOYMENT_GROUP_NAME']+" deployment group with "+os.environ['DEPLOYMENT_GROUP_ID']+" deployment group ID was generated by a "+os.environ['LIFECYCLE_EVENT']+" script during "+os.environ['DEPLOYMENT_ID']+" deployment.</h2>"
 
fp=open("/var/www/html/index.html","r")
buffer=fp.read()
fp.close()
 
fp=open("/var/www/html/index.html","w")
fp.write(buffer.replace(strToSearch,strToReplace))
fp.close()
```

### 挂钩示例
<a name="reference-appspec-file-structure-hooks-example"></a>

以下是 **hooks** 条目的示例，该条目为 `AfterInstall` 生命周期事件指定两个挂钩：

```
hooks:
   AfterInstall:
     - location: Scripts/RunResourceTests.sh
       timeout: 180
     - location: Scripts/PostDeploy.sh
       timeout: 180
```

`Scripts/RunResourceTests.sh` 脚本在部署过程的 `AfterInstall` 阶段运行。如果该脚本的运行时间超过 180 秒（3 分钟），则部署将失败。

您在“hooks”部分中指定的脚本的位置是应用程序修订包根目录的相对路径。在上述示例中，名为 `RunResourceTests.sh` 的文件位于名为 `Scripts` 的目录中。该 `Scripts` 目录位于包的根级别。有关更多信息，请参阅 [为 CodeDeploy 规划修订](application-revisions-plan.md)。