

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

# 自定义 Linux 服务器上的软件
<a name="customize-containers-ec2"></a>

本节介绍您可以在配置文件中包含的信息类型，以便在运行 Linux 的 EC2 实例上自定义软件。有关自定义和配置 Elastic Beanstalk 环境的一般信息，请参阅[配置 Elastic Beanstalk 环境](customize-containers.md)。有关在运行 Windows 的 EC2 实例上自定义软件的信息，请参阅[自定义 Windows Server 上的软件](customize-containers-windows-ec2.md)。

建议自定义和配置您的应用程序所依赖的软件。您可以添加要在实例预置期间执行的命令；定义 Linux 用户和组；以及下载文件或直接在环境实例上创建文件。这些文件可能是应用程序所需的依赖项（例如 yum 存储库中的其他包），也可能是配置文件（例如代理配置的替代项，用于覆盖 Elastic Beanstalk 默认的特定设置）。

**注意**  
在 Amazon Linux 2 平台上，我们强烈建议您使用 *Buildfile*，而不是在 .ebextensions 配置文件中提供文件和命令。*Procfile* 和*平台挂钩*，（如果可能）用于在实例预置期间在环境实例上配置和运行自定义代码。有关这些机制的详细信息，请参阅[扩展 Elastic Beanstalk Linux 平台](platforms-linux-extend.md)。
YAML 依赖一致的缩进。当替换示例配置文件中的内容时，应匹配缩进级别，并且确保您的文本编辑器使用空格而不是字符来进行缩进。

配置文件支持以下键，它们影响运行您的应用程序的 Linux 服务器。

**Topics**
+ [软件包](#linux-packages)
+ [组](#linux-groups)
+ [Users](#linux-users)
+ [来源](#linux-sources)
+ [文件](#linux-files)
+ [命令](#linux-commands)
+ [Services](#linux-services)
+ [容器命令](#linux-container-commands)
+ [示例：使用自定义 Amazon CloudWatch 指标](customize-containers-cw.md)

将按键在此处列出的顺序对其进行处理。

观察您的环境的[事件](using-features.events.md)，同时开发和测试配置文件。Elastic Beanstalk 将忽略包含验证错误的配置文件（例如“密钥无效”），并且不会处理同一文件中的任何其他密钥。出现这种情况时，Elastic Beanstalk 将警告事件添加到事件日志中。

## 软件包
<a name="linux-packages"></a>

您可以使用 `packages` 键下载并安装预先打包的应用程序和组件。

### 语法
<a name="linux-packages-syntax"></a>

```
packages: 
  {{name of package manager}}:
    {{package name}}: {{version}}
    ...
  {{name of package manager}}:
    {{package name}}: {{version}}
    ...
  ...
```

您可以在每个程序包管理器密钥下指定多个软件包。

### 支持的软件包格式
<a name="linux-packages-support"></a>

目前，Elastic Beanstalk 支持以下包管理器：yum、rubygems、python 和 rpm。包的处理顺序如下：rpm、yum、rubygems 和 python。rubygems 和 python 之间没有处理顺序。在每个包管理器内，不保证包安装顺序。请使用您的操作系统支持的包管理器。

**注意**  
Elastic Beanstalk 支持两个用于 Python 的基础包管理器：pip 和 easy\_install。但是，在配置文件语法中，您必须将包管理器名称指定为 `python`。当您使用配置文件指定 Python 包管理器时，Elastic Beanstalk 会使用 Python 2.7。如果您的应用程序依赖于不同的 Python 版本，可以在 `requirements.txt` 文件中指定要安装的包。有关更多信息，请参阅 [在 Elastic Beanstalk 上使用要求文件指定依赖项](python-configuration-requirements.md)。

### 指定版本
<a name="linux-packages-versions"></a>

在每个包管理器内，会使用包名和一系列版本对每个包进行指定。版本可以是字符串、一系列版本、空字符串或者空列表。空字符串或者空列表表示您需要最新的版本。对于 rpm 管理器，版本是以磁盘或 URL 上的文件的路径的方式指定的。不支持相对路径。

如果您指定包的版本，Elastic Beanstalk 会尝试安装该版本，即使实例上已经安装了较新的包版本。如果已经安装了较新的版本，那么部署会失败。一些包管理器支持多个版本，但其他的包管理器可能不支持。有关更多信息，请查看相关的包管理器文档。如果您没有指定版本且已安装了某种版本的包，那么 Elastic Beanstalk 不会安装新的版本，因为它会认为您希望保留并使用现有的版本。

### 示例代码段
<a name="linux-packages-snippet"></a>

下面的代码段为 rpm 指定版本 URL，从 yum 请求最新版本并从 rubygems 请求 chef 的版本 0.10.2。

```
packages: 
  yum:
    libmemcached: [] 
    ruby-devel: []
    gcc: []
  rpm:
    epel: http://download.fedoraproject.org/pub/epel/5/i386/epel-release-5-4.noarch.rpm
  rubygems: 
    chef: '0.10.2'
```

## 组
<a name="linux-groups"></a>

您可以使用`groups`密钥创建 Linux/UNIX 群组和分配群组 IDs。要创建组，请添加新的密钥值对，将新的组名映射到可选组 ID。组键可以包含一个或多个组名。下表列出了可用的密钥。

### 语法
<a name="linux-groups-syntax"></a>

```
groups:
  {{name of group}}: {}
  {{name of group}}:
    gid: "{{group id}}"
```

### 选项
<a name="linux-groups-options"></a>

`gid`  
组 ID 编号。  
如果指定了组 ID，且存在该名称的组，那么创建组将失败。如果另一个组已拥有所指定的组 ID，那么操作系统可能会拒绝创建组。

### 示例代码段
<a name="linux-groups-snippet"></a>

以下代码段指定了一个名为“groupOne”、但没有分配组 ID 的组，以及一个名为“groupTwo”、但指定了组 ID 值为 45 的组。

```
groups:
  groupOne: {}
  groupTwo:
    gid: "{{45}}"
```

## Users
<a name="linux-users"></a>

您可以使用`users`密钥在 EC2 实例上创建 Linux/UNIX 用户。

### 语法
<a name="linux-users-syntax"></a>

```
users:
  {{name of user}}:
    groups:
      - {{name of group}}
    uid: "{{id of the user}}"
    homeDir: "{{user's home directory}}"
```

### 选项
<a name="linux-users-options"></a>

`uid`  
用户 ID。如果用户名还有另一个用户 ID，那么此创建过程会失败。如果用户 ID 已指定给现有的用户，那么操作系统可能会拒绝该创建请求。

`groups`  
一系列组名。用户会添加到列表中的每个组。

`homeDir`  
用户的主目录。

创建的用户属于非交互式系统用户，带有 `/sbin/nologin` Shell。这是特意设计的，无法修改。

### 示例代码段
<a name="linux-users-snippet"></a>

```
users:
  myuser:
    groups:
      - {{group1}}
      - {{group2}}
    uid: "{{50}}"
    homeDir: "{{/tmp}}"
```

## 来源
<a name="linux-sources"></a>

您可以使用`sources`密钥从公共 URL 下载存档文件，然后将其解压缩到 EC2 实例的目标目录中。

### 语法
<a name="linux-sources-syntax"></a>

```
sources:
  {{target directory}}: {{location of archive file}}
```

### 支持的格式
<a name="linux-sources-support"></a>

支持的格式有 tar、tar\+gzip、tar\+bz2 和 Zip。只要该 URL 可公开访问，您就可以引用 Amazon Simple Storage Service (Amazon S3) 等外部位置 (例如，`https://amzn-s3-demo-bucket.s3.amazonaws.com/myobject`)。

### 示例代码段
<a name="linux-sources-example"></a>

以下示例会从 Amazon S3 存储桶下载一个公有 .zip 文件并将其解压到 `/etc/myapp` 中：

```
sources:  
  /etc/myapp: https://amzn-s3-demo-bucket.s3.amazonaws.com/myobject
```

**注意**  
多个提取不应重用相同的目标路径。将其他源提取到项目的相同目标路径上将替换内容而不是附加到内容上。

## 文件
<a name="linux-files"></a>

您可以使用`files`密钥在 EC2 实例上创建文件。该内容可以內嵌在配置文件中，也可以从 URL 中提取。这些文件会按词典顺序写入磁盘。

您可以提供一个用于授权的实例配置文件，从而使用 `files` 密钥从 Amazon S3 下载私有文件。

如果您指定的文件路径已在实例上存在，则将保留现有文件，并在其名称后附加扩展名 `.bak`。

### 语法
<a name="linux-files-syntax"></a>

```
files:  
  "{{target file location on disk}}": 
     mode: "{{six-digit octal value}}"
     owner: {{name of owning user for file}}
     group: {{name of owning group for file}}
     source: {{URL}}
     authentication: {{authentication name}}:

  "{{target file location on disk}}": 
     mode: "{{six-digit octal value}}"
     owner: {{name of owning user for file}}
     group: {{name of owning group for file}}
     content: |
      {{# this is my}}
      {{# file content}}
     encoding: {{encoding format}}
     authentication: {{authentication name}}:
```

### 选项
<a name="linux-files-options"></a>

`content`  
要添加到文件的字符串内容。指定 `content` 或 `source`，但不能同时指定两者。

`source`  
要下载的文件的 URL。指定 `content` 或 `source`，但不能同时指定两者。

`encoding`  
使用 `content` 选项指定的字符串的编码格式。  
有效值：`plain` \| `base64`

`group`  
拥有文件的 Linux 组。

`owner`  
拥有文件的 Linux 用户。

`mode`  
是一个六位数的八进制值，表示这个文件的模式。在 Windows 系统中不受支持。将前三位数用于符号链接，将后三位数用于设置权限。要创建符号链接，请指定 `120{{xxx}}`，其中 `xxx` 定义目标文件的权限。要指定文件的权限，请使用最后三位，例如 `000644`。

`authentication`  
要使用的 [Amazon CloudFormation 身份验证方法](https://docs.amazonaws.cn/AWSCloudFormation/latest/UserGuide/aws-resource-authentication.html)的名称。您可以使用资源键将身份验证方法添加到 Auto Scaling 组元数据。有关示例，请参阅以下内容。

### 示例代码段
<a name="linux-files-snippet"></a>

```
files:
  "/home/ec2-user/myfile" :
    mode: "000755"
    owner: root
    group: root
    source: http://foo.bar/myfile
 
  "/home/ec2-user/myfile2" :
    mode: "000755"
    owner: root
    group: root
    content: |
      this is my
      file content
```

使用符号链接的示例。这会创建指向现有文件 `/tmp/myfile2.txt` 的链接 `/tmp/myfile1.txt`。

```
files:
  "/tmp/myfile2.txt" :
    mode: "120400"
    content: "/tmp/myfile1.txt"
```

以下示例使用资源键添加名为 S3Auth 的身份验证方法并使用该方法从 Amazon S3 存储桶下载私有文件：

```
Resources:
  AWSEBAutoScalingGroup:
    Metadata:
      AWS::CloudFormation::Authentication:
        {{S3Auth}}:
          type: "s3"
          buckets: ["{{amzn-s3-demo-bucket2}}"]
          roleName:
            "Fn::GetOptionSetting":
              Namespace: "aws:autoscaling:launchconfiguration"
              OptionName: "IamInstanceProfile"
              DefaultValue: "aws-elasticbeanstalk-ec2-role"

files:
  "{{/tmp/data.json}}" :
    mode: "000755"
    owner: root
    group: root
    authentication: "{{S3Auth}}"
    source: {{https://elasticbeanstalk-us-west-2-123456789012.s3-us-west-2.amazonaws.com/data.json}}
```

## 命令
<a name="linux-commands"></a>

您可以使用该`commands`密钥在 EC2 实例上执行命令。这些命令在应用程序之前运行，设置 Web 服务器以及提取应用程序版本文件。

指定的命令以根用户身份运行且按名称的字母顺序进行处理。默认情况下，该命令在根目录中运行。要从另一个目录运行命令，请使用 `cwd` 选项。

要使用您的命令排查问题，您可以在[实例日志](using-features.logging.md)中查找其输出。

### 语法
<a name="linux-commands-syntax"></a>

```
commands:
  {{command name}}: 
    command: {{command to run}}
    cwd: {{working directory}}
    env: 
      {{variable name}}: {{variable value}}
    test: {{conditions for command}} 
    ignoreErrors: true
```

### 选项
<a name="linux-commands-options"></a>

`command`  
一个数组（YAML 语法中的[数据块序列集合](http://yaml.org/spec/1.2/spec.html#id2759963)）或一个用于指定要运行的命令的字符串。一些重要说明：  
+ 如果您使用了字符串，则不需要用引号将整个字符串引起来。如果您确实使用了引号，请对相同类型的引号的文本匹配项进行转义。
+ 如果您使用了数组，则不需要对空格字符进行转义或用引号将命令参数引起来。每个数组元素都是一个命令参数。请勿使用数组指定多个命令。
以下示例具有完全相同的效果：  

```
commands:
  command1:
    command: git commit -m "This is a comment."
  command2:
    command: "git commit -m \"This is a comment.\""
  command3:
    command: 'git commit -m "This is a comment."'
  command4:
    command:
      - git
      - commit
      - -m
      - This is a comment.
```
要指定多个命令，请使用[文本数据块标量](http://yaml.org/spec/1.2/spec.html#id2760844)，如以下示例所示。  

```
commands:
  command block:
    command: |
      git commit -m "This is a comment."
      git push
```

`env`  
(可选) 设置该命令的环境变量。这个属性会覆盖而不是追加到现有的环境。

`cwd`  
(可选) 工作目录。如果未指定，命令将从根目录 (/) 运行。

`test`  
（可选）一个命令，此命令必须返回值 `true`（退出代码为 0），以便 Elastic Beanstalk 处理 `command` 键中包含的命令，例如 shell 脚本。

`ignoreErrors`  
(可选) 一个布尔值，该值确定在 `command` 密钥中包含的命令失败时 (返回非零值) 是否应该运行其他命令。如果要在命令失败后继续运行其他命令，请将该值设置为 `true`。否则，请将该值设置为 `false`。默认值为 `false`。

### 示例代码段
<a name="linux-commands-snippet"></a>

以下示例代码段运行 Python 脚本。

```
commands:
  python_install:
    command: myscript.py
    cwd: /home/ec2-user
    env:
      myvarname: myvarvalue
    test: "[ -x /usr/bin/python ]"
```

## Services
<a name="linux-services"></a>

您可以使用 `services` 键定义哪些服务应该在实例启动时启动或者停止。`services` 键还可让您在源、包和文件上指定依赖项，以便在由于文件安装而需要重启时，让 Elastic Beanstalk 负责服务的重启。

### 语法
<a name="linux-services-syntax"></a>

```
services:
  sysvinit:
    {{name of service}}:
      enabled: "true"
      ensureRunning: "true"
      files: 
        - "{{file name}}"
      sources: 
        - "{{directory}}"	
      packages: 
        {{name of package manager}}:
          "{{package name}}[: {{version}}]"
      commands: 
        - "{{name of command}}"
```

### 选项
<a name="linux-services-options"></a>

`ensureRunning`  
设置为 `true` 可确保在 Elastic Beanstalk 完成后服务能够运行。  
设置为 `false` 可确保该服务在 Elastic Beanstalk 完成后不运行。  
忽略该密钥，将不更改服务状态。

`enabled`  
设置为 `true`，可确保该服务在启动时自动启动。  
设置为 `false`，可确保该服务在启动时不会自动启动。  
忽略该密钥，将不更改这个属性。

`files`  
一系列文件。如果 Elastic Beanstalk 直接通过文件块更改一个文件，则该服务会重启。

`sources`  
一系列目录。如果 Elastic Beanstalk 将存档展开到这些目录中的一个，则该服务会重启。

`packages`  
包管理器与一系列包名的映射。如果 Elastic Beanstalk 安装或者更新了这些包中的一个，则该服务会重启。

`commands`  
一系列命令名称。如果 Elastic Beanstalk 运行指定的命令，则服务将重新启动。

### 示例代码段
<a name="linux-services-snippet"></a>

以下是示例代码段：

```
services: 
  sysvinit:
    myservice:
      enabled: true
      ensureRunning: true
```

## 容器命令
<a name="linux-container-commands"></a>

您可以使用 `container_commands` 键执行将影响应用程序源代码的命令。容器命令将在设置应用程序和 Web 服务器并提取应用程序版本存档后，但在部署应用程序版本前运行。非容器命令和其他自定义操作将在提取应用程序源代码之前执行。

指定的命令以根用户身份运行且按名称的字母顺序进行处理。容器命令从暂存目录运行，您的源代码在部署到应用程序服务器前在这里提取。当源部署到其最终位置时，将包含您在暂存目录中使用容器命令对源代码所做的任何更改。

**注意**  
您的容器命令的输出记录在 `cfn-init-cmd.log` 实例日志中。有关检索和查看实例日志的更多信息，请参阅[查看来自 Amazon EC2 实例的日志](using-features.logging.md)。

可以使用 `leader_only` 仅对单个实例运行此命令，也可以配置 `test` 以仅在测试命令的评估结果为 `true` 时运行此命令。仅领导容器命令只在创建和部署环境期间执行，而其他命令和服务器自定义操作将在预配置或更新实例时执行。由于启动配置发生更改 (例如 AMI Id 或实例类型的更改)，未执行仅领导容器命令。

### 语法
<a name="linux-container-commands-syntax"></a>

```
container_commands:
  {{name of container_command}}:
    command: "{{command to run}}"
    leader_only: true
  {{name of container_command}}:
    command: "{{command to run}}"
```

### 选项
<a name="linux-container-commands-options"></a>

`command`  
要运行的字符串或字符串数组。

`env`  
(可选) 在运行命令之前设置环境变量，并覆盖任何现有值。

`cwd`  
(可选) 工作目录。默认情况下，这是解压缩应用程序的暂存目录。

`leader_only`  
（可选）仅对 Elastic Beanstalk 选定的单个实例运行命令。仅领导容器命令将在其他容器命令之前运行。命令可以是仅领导命令或具有 `test`，但不能同时具备这两个特性 (`leader_only` 优先)。

`test`  
(可选) 运行必须返回 `true` 的测试命令以便运行容器命令。命令可以是仅领导命令或具有 `test`，但不能同时具备这两个特性 (`leader_only` 优先)。

`ignoreErrors`  
(可选) 不在容器命令返回 0 以外的值 (成功) 时导致部署失败。设置为 `true` 可实现这一点。

### 示例代码段
<a name="linux-container-commands-snippet"></a>

以下是示例代码段。

```
container_commands:
  collectstatic:
    command: "django-admin.py collectstatic --noinput"
  01syncdb:
    command: "django-admin.py syncdb --noinput"
    leader_only: true
  02migrate:
    command: "django-admin.py migrate"
    leader_only: true
  99customize:
    command: "scripts/customize.sh"
```