

# 使用 EC2Rescue 对受损的 Amazon EC2 Linux 实例进行问题排查
<a name="Linux-Server-EC2Rescue"></a>

EC2Rescue for Linux 是一种易于使用的开源工具，可在 Amazon EC2 Linux 实例上运行此工具以通过其包含 100 多个*模块*的库来诊断、排查和修复常见问题。模块是包含 BASH 或 Python 脚本以及必要元数据的 YAML 文件。

EC2Rescue for Linux 实例的一些通用使用案例包括：
+ 收集系统日志和软件包管理器日志
+ 收集资源利用率数据
+ 诊断和修复已知有问题的内核参数和常见 OpenSSH 问题

**注意**  
`AWSSupport-TroubleshootSSH` AWS Systems Manager Automation 运行手册安装了 EC2Rescue for Linux，然后使用该工具检查或尝试修复阻止 SSH 连接到 Linux 实例的常见问题。有关更多信息，请参阅 [AWSSupport-TroubleshootSSH](https://docs.aws.amazon.com/systems-manager-automation-runbooks/latest/userguide/automation-awssupport-troubleshootssh.html)。

如果您使用的是 Windows 实例，则请参阅 [使用 EC2Rescue 对受损的 Amazon EC2 Windows 实例进行问题排查](Windows-Server-EC2Rescue.md)。

**Topics**
+ [安装 EC2Rescue](ec2rl_install.md)
+ [运行 EC2Rescue 命令](ec2rl_working.md)
+ [开发 EC2Rescue 模块](ec2rl_moduledev.md)

# 在 Amazon EC2 Linux 实例上安装 EC2Rescue
<a name="ec2rl_install"></a>

EC2Rescue for Linux 工具可以安装在满足以下先决条件的 Amazon EC2 Linux 实例上。

**先决条件**
+ 支持的操作系统：
  + Amazon Linux 2
  + Amazon Linux 2016.09\$1
  + SUSE Linux Enterprise Server 12\$1
  + RHEL 7\$1
  + Ubuntu 16.04\$1
+ 软件要求：
  + Python 2.7.9\$1 或 3.2\$1

## 安装 EC2Rescue
<a name="ec2rl-install"></a>

`AWSSupport-TroubleshootSSH` 运行手册安装了 EC2Rescue for Linux，使用该工具检查或尝试修复阻止通过 SSH 远程连接到 Linux 计算机的常见问题。有关详细信息以及要运行此自动化，请参阅 [支持-TroubleshootSSH](https://docs.aws.amazon.com/systems-manager-automation-runbooks/latest/userguide/automation-awssupport-troubleshootssh.html)。

如果您的系统具有所需的 Python 版本，可以安装标准构建过程。否则，您可以安装捆绑构建过程，其中包括 Python 的最小副本。

**安装标准构建过程**

1. 从正常工作的 Linux 实例下载 [EC2Rescue for Linux](https://s3.amazonaws.com/ec2rescuelinux/ec2rl.tgz) 工具：

   ```
   curl -O https://s3.amazonaws.com/ec2rescuelinux/ec2rl.tgz
   ```

1. （*可选*）验证 EC2Rescue for Linux 安装文件的签名。有关更多信息，请参阅 [（可选）验证 EC2Rescue for Linux 的签名](#ec2rl_verify)。

1. 下载 sha256 哈希文件：

   ```
   curl -O https://s3.amazonaws.com/ec2rescuelinux/ec2rl.tgz.sha256
   ```

1. 验证 tarball 的完整性：

   ```
   sha256sum -c ec2rl.tgz.sha256
   ```

1. 解压缩 tarball：

   ```
   tar -xzvf ec2rl.tgz
   ```

1. 通过列出帮助文件来验证安装：

   ```
   cd ec2rl-<version_number>
   ./ec2rl help
   ```

**安装捆绑构建过程**  
有关指向下载和限制列表的链接，请参阅 github 上的 [EC2Rescue for Linux](https://github.com/awslabs/aws-ec2rescue-linux/blob/master/README.md)。

## （可选）验证 EC2Rescue for Linux 的签名
<a name="ec2rl_verify"></a>

下面是验证基于 Linux 的操作系统的 EC2Rescue for Linux 软件包是否有效的推荐过程。

当您从 Internet 下载应用程序时，我们建议您验证软件发行商的身份，并检查应用程序在发行后是否已遭更改或损坏。这会保护您免于安装含有病毒或其他恶意代码的应用程序版本。

如果您在执行本主题中的步骤后确定适用于 EC2Rescue for Linux 的软件已遭更改或损坏，请不要运行安装文件。否则，可联系 Amazon Web Services。

适用于基于 Linux 的操作系统的 EC2Rescue for Linux 文件是使用 GnuPG（安全数字签名的 Pretty Good Privacy 的开源式执行 (OpenPGP) 标准）进行签名的。GnuPG（也称为 GPG）通过数字签名进行身份验证和完整性检查。AWS 发布了公有密钥和签名，可供您用于验证下载的 EC2Rescue for Linux 程序包。有关 PGP 和 GnuPG (GPG) 的更多信息，请访问 [https://www.gnupg.org/](https://www.gnupg.org/)。

第一步是与软件发行商建立信任。下载软件发行商的公有密钥，检查公有密钥的所有人是否真为其人，然后将该公有密钥添加到您的密钥环。密钥环是已知公有密钥的集合。验证公有密钥的真实性后，您可以使用它来验证应用程序的签名。

**Topics**
+ [验证并导入公有密钥](#ec2rl_authenticate)
+ [验证软件包的签名](#ec2rl_verify_signature)

### 验证并导入公有密钥
<a name="ec2rl_authenticate"></a>

本流程的下一步是验证 EC2Rescue for Linux 公有密钥，并在 GPG 密钥环中将其添加为可信任密钥。

**验证并导入 EC2Rescue for Linux 公有密钥**

1. 在命令提示符处，使用以下命令获取我们的公共 GPG 生成密钥的副本：

   ```
   curl -O https://s3.amazonaws.com/ec2rescuelinux/ec2rl.key
   ```

1. 在保存 `ec2rl.key` 的目录中的命令提示符处，使用以下命令将 EC2Rescue for Linux 公有密钥导入密钥环：

   ```
   gpg2 --import ec2rl.key
   ```

   该命令返回的结果类似于下方内容：

   ```
   gpg: /home/ec2-user/.gnupg/trustdb.gpg: trustdb created
   gpg: key 2FAE2A1C: public key "ec2autodiag@amazon.com <EC2 Rescue for Linux>" imported
   gpg: Total number processed: 1
   gpg:               imported: 1  (RSA: 1)
   ```
**提示**  
如果您看到指示找不到该命令的错误，请使用 `apt-get install gnupg2`（基于 Debian 的 Linux）或 `yum install gnupg2`（基于 Red Hat 的 Linux）安装 GnuPG 实用程序。

### 验证软件包的签名
<a name="ec2rl_verify_signature"></a>

在安装 GPG 工具、验证并导入 EC2Rescue for Linux 公有密钥以及确认 EC2Rescue for Linux 公有密钥可信后，便可以验证 EC2Rescue for Linux 安装脚本的签名。

**验证 EC2Rescue for Linux 安装脚本签名**

1. 在命令提示符处，运行以下命令以下载安装脚本的签名文件：

   ```
   curl -O https://s3.amazonaws.com/ec2rescuelinux/ec2rl.tgz.sig
   ```

1. 通过在保存 `ec2rl.tgz.sig` 和 EC2Rescue for Linux 安装文件的目录中的命令提示符处运行以下命令来验证签名。这两个文件都必须存在。

   ```
   gpg2 --verify ./ec2rl.tgz.sig
   ```

   输出应与以下内容类似：

   ```
   gpg: Signature made Thu 12 Jul 2018 01:57:51 AM UTC using RSA key ID 6991ED45
   gpg: Good signature from "ec2autodiag@amazon.com <EC2 Rescue for Linux>"
   gpg: WARNING: This key is not certified with a trusted signature!
   gpg:          There is no indication that the signature belongs to the owner.
   Primary key fingerprint: E528 BCC9 0DBF 5AFA 0F6C  C36A F780 4843 2FAE 2A1C
        Subkey fingerprint: 966B 0D27 85E9 AEEC 1146  7A9D 8851 1153 6991 ED45
   ```

   如果输出包含短语 `Good signature from "ec2autodiag@amazon.com <EC2 Rescue for Linux>"`，则意味着已成功验证签名，您可以继续运行 EC2Rescue for Linux 安装脚本。

   如果输出包含短语 `BAD signature`，则检查是否正确执行了此过程。如果您持续获得此响应，请联系 Amazon Web Services，而不要运行之前下载的安装文件。

下面是有关您可能看到的警告的详细信息：
+ **WARNING: This key is not certified with a trusted signature\$1 There is no indication that the signature belongs to the owner.**这表示您坚信自己拥有 EC2Rescue for Linux 的可信公有密钥的个人信任级别。理想情况下，您将前往 Amazon Web Services 办公室并亲自接收此密钥。但更常见的情况是，从网站下载此密钥。在这种情况下，该网站是 Amazon Web Services 网站。
+ **gpg2: no ultimately trusted keys found.** 这意味着您 (或您信任的其他人) 对特定密钥不是“绝对信任”。

有关更多信息，请参阅 [https://www.gnupg.org/](https://www.gnupg.org/)。

# 在 Amazon EC2 Linux 实例上运行 EC2Rescue 命令
<a name="ec2rl_working"></a>

EC2Rescue 是一个命令行工具。在 Linux 实例上安装 EC2Rescue 后，您可以通过运行 `./ec2rl help` 获得有关如何使用该工具的一般帮助。您可以通过运行 `./ec2rl list` 查看可用模块，也可以通过运行 `./ec2rl help module_name` 获得有关特定模块的帮助。

下面是您可以执行以便开始使用此工具的常见任务。

**Topics**
+ [运行 EC2Rescue 模块](#ec2rl_running_module)
+ [上传 EC2Rescue 模块结果](#ec2rl_uploading_results)
+ [创建 Amazon EC2 Linux 实例的备份](#ec2rl_creating_backups)

## 运行 EC2Rescue 模块
<a name="ec2rl_running_module"></a>

**运行所有 EC2Rescue 模块**  
使用 **./ec2rl run** 命令而不指定任何附加参数。有些模块需要根访问权限。如果您不是根用户，请在运行命令时使用 **sudo**。

```
./ec2rl run
```

**运行特定的 EC2Rescue 模块**  
使用 **./ec2rl run** 命令并为 `--only-modules` 指定要运行的模块的名称。有些模块需要*参数*才能使用。

```
./ec2rl run --only-modules=module_name --arguments
```

例如，要运行 **dig** 模块查询 `amazon.com` 域，请使用以下命令。

```
./ec2rl run --only-modules=dig --domain=amazon.com
```

**查看 EC2Rescue 模块的结果**  
运行该模块，然后查看 `cat /var/tmp/ec2rl/logfile_location` 中的日志文件。例如，可在以下位置找到 **dig** 模块的日志文件：

```
cat /var/tmp/ec2rl/timestamp/mod_out/run/dig.log
```

## 上传 EC2Rescue 模块结果
<a name="ec2rl_uploading_results"></a>

如果 支持 请求 EC2Rescue 模块的结果，则可以使用 EC2Rescue 工具上传日志文件。您可以将结果上传到 支持 提供的位置或您自己的 Amazon S3 存储桶。

**将结果上传到 支持 提供的位置**  
使用 **./ec2rl upload** 命令。对于 `--upload-directory`，指定日志文件的位置。对于 `--support-url`，请指定 支持 提供的 URL。

```
./ec2rl upload --upload-directory=/var/tmp/ec2rl/logfile_location --support-url="url_provided_by_aws_support"
```

**将结果上传到 Amazon S3 存储桶**  
使用 **./ec2rl upload** 命令。对于 `--upload-directory`，指定日志文件的位置。对于 `--presigned-url`，为 S3 存储桶指定预签名 URL。有关为 Amazon S3 生成预签名 URL 的更多信息，请参阅[使用预签名 URL 上传对象](https://docs.aws.amazon.com/AmazonS3/latest/userguide/PresignedUrlUploadObject.html)。

```
./ec2rl upload --upload-directory=/var/tmp/ec2rl/logfile_location --presigned-url="presigned_s3_url"
```

## 创建 Amazon EC2 Linux 实例的备份
<a name="ec2rl_creating_backups"></a>

您可以使用 EC2Rescue 通过创建 AMI 或创建其附加卷的快照来备份您的 Linux 实例。

**创建 AMI**  
使用 `./ec2rl run` 命令，并为 --`backup` 指定 `ami`。

```
./ec2rl run --backup=ami
```

**创建所有附加卷的多卷快照**  
使用 `./ec2rl run` 命令，并为 --`backup` 指定 `allvolumes`。

```
./ec2rl run --backup=allvolumes
```

**创建特定附加卷的快照**  
使用 `./ec2rl run` 命令，并为 --`backup` 指定要备份的卷的 ID。

```
./ec2rl run --backup=vol-01234567890abcdef
```

# 为 Amazon EC2 Linux 实例开发 EC2Rescue 模块
<a name="ec2rl_moduledev"></a>

模块使用 YAML 编写，这是一种数据序列化标准。模块的 YAML 文件包括一个文档，用于表示模块及其属性。

## 添加模块属性
<a name="ec2rl-adding-modules"></a>

下表列出了可用的模块属性。


| 属性 | 说明 | 
| --- | --- | 
| name | 模块的名称。该名称长度应少于或等于 18 个字符。 | 
| 版本 | 模块的版本号。 | 
| 删除实例快照 | 模块的简短说明性标题。此值的长度应少于或等于 50 个字符。 | 
| helptext |  模块的详细说明。每一行的长度应少于或等于 75 个字符。如果模块使用必需或可选参数，请在 helptext 值中包括这些参数。 例如： <pre>helptext: !!str |<br />  Collect output from ps for system analysis<br />  Consumes --times= for number of times to repeat<br />  Consumes --period= for time period between repetition</pre> | 
| placement | 运行模块的阶段。支持的值： [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/AWSEC2/latest/UserGuide/ec2rl_moduledev.html)  | 
| language | 编写模块代码使用的语言。支持的值： [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/AWSEC2/latest/UserGuide/ec2rl_moduledev.html)  Python 代码必须同时兼容 Python 2.7.9\$1 和 Python 3.2\$1。   | 
| 修复 |  指示模块是否支持修正。支持的值为 `True` 或 `False`。 模块默认为 `False`（如果不存在），这使其成为那些不支持修正的模块的可选属性。  | 
| content | 整个脚本代码。 | 
| constraint | 包含限制值的对象的名称。 | 
| 域 | 说明如何分组或分类模块的描述符。所包括的模块组使用以下域： [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/AWSEC2/latest/UserGuide/ec2rl_moduledev.html) | 
| class | 由模块执行的任务类型的描述符。所包括的模块组使用以下类： [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/AWSEC2/latest/UserGuide/ec2rl_moduledev.html) | 
| distro | 此模块支持的 Linux 发行版的列表。所包含的模块组使用以下发行版： [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/AWSEC2/latest/UserGuide/ec2rl_moduledev.html) | 
| 必需 | 模块从 CLI 选项使用的必需参数。 | 
| optional | 模块可使用的可选参数。 | 
| 软件 | 模块中使用的软件可执行文件。此属性用于指定默认情况下未安装的软件。EC2Rescue for Linux 逻辑在运行模块之前确保这些程序存在并且可执行。 | 
| 程序包 | 可执行文件的源软件包。此属性用于随软件提供软件包的详细信息，包括用于下载或者获取更多信息的 URL。 | 
| sudo | 指示运行模块是否需要根访问权限。 您无需在模块脚本中实施 sudo 检查。如果值为 true，则 EC2Rescue for Linux 逻辑仅在执行用户具有根访问权限时才运行模块。 | 
| perfimpact | 指示模块对其运行环境是否会产生重大性能影响。如果值为 true 并且没有 `--perfimpact=true` 参数，则跳过模块。 | 
| parallelexclusive | 指定需要互斥的程序。例如，所有指定“bpf”的模块以串行方式运行。 | 

## 设置环境变量
<a name="ec2rl_adding_envvars"></a>

下表列出了可用的环境变量。


| 环境变量 | 说明 | 
| --- | --- | 
|  `EC2RL_CALLPATH`  | ec2rl.py 的路径。此路径可用于定位 lib 目录和使用分发的 Python 模块。 | 
|  `EC2RL_WORKDIR`  |  诊断工具的主 tmp 目录。 默认值：`/var/tmp/ec2rl`。 | 
|  `EC2RL_RUNDIR`  |  用于存储所有输出的目录。 默认值：`/var/tmp/ec2rl/<date&timestamp>`。  | 
|  `EC2RL_GATHEREDDIR`  |  用于放置收集的模块数据的根目录。 默认值:`/var/tmp/ec2rl/<date&timestamp>/mod_out/gathered/`。  | 
|  `EC2RL_NET_DRIVER`  |  为实例上第一个 (按照字母顺序排序) 非虚拟网络接口使用的驱动程序。 示例： [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/AWSEC2/latest/UserGuide/ec2rl_moduledev.html)  | 
|  `EC2RL_SUDO`  |  如果 EC2Rescue for Linux 以根身份运行，则为 true；否则为 false。  | 
|  `EC2RL_VIRT_TYPE`  |  由实例元数据提供的虚拟化类型。 示例： [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/AWSEC2/latest/UserGuide/ec2rl_moduledev.html)  | 
|  `EC2RL_INTERFACES`  |  系统上的接口枚举列表。该值为包含名称的字符串，例如 `eth0`、`eth1` 等。这通过 `functions.bash` 生成，仅对其来源模块可用。  | 

## 使用 YAML 语法
<a name="ec2rl_yamlsyntax"></a>

在您构建模块 YAML 文件时，应注意以下事项：
+ 三个连字符 (`---`) 表示文档的明确开始位置。
+ `!ec2rlcore.module.Module` 标签指示 YAML 分析器在从数据流创建对象时调用哪个构造函数。您可在 `module.py` 文件内部查找构造函数。
+ `!!str` 标签告知 YAML 解析器不尝试确定数据的类型，而是将内容解释为字符串文本。
+ 竖线字符 (`|`) 告知 YAML 解析器该值为文字类型的标量。在这种情况下，解析器包括所有空格。对于模块而言这非常重要，因为保留了缩进和换行字符。
+ YAML 标准缩进为两个空格，在下例中可以看到。请确保您为脚本保留了标准缩进 (例如，对于 Python 为四个空格)，然后在模块文件中将全部内容缩进两个空格。

## 模块示例
<a name="ec2rl_example"></a>

示例 1 (`mod.d/ps.yaml`)：

```
--- !ec2rlcore.module.Module
# Module document. Translates directly into an almost-complete Module object
name: !!str ps
path: !!str
version: !!str 1.0
title: !!str Collect output from ps for system analysis
helptext: !!str |
  Collect output from ps for system analysis
  Requires --times= for number of times to repeat
  Requires --period= for time period between repetition
placement: !!str run
package: 
  - !!str
language: !!str bash
content: !!str |
  #!/bin/bash
  error_trap()
  {
      printf "%0.s=" {1..80}
      echo -e "\nERROR:	"$BASH_COMMAND" exited with an error on line ${BASH_LINENO[0]}"
      exit 0
  }
  trap error_trap ERR

  # read-in shared function
  source functions.bash
  echo "I will collect ps output from this $EC2RL_DISTRO box for $times times every $period seconds."
  for i in $(seq 1 $times); do
      ps auxww
      sleep $period
  done
constraint:
  requires_ec2: !!str False
  domain: !!str performance
  class: !!str collect
  distro: !!str alami ubuntu rhel suse
  required: !!str period times
  optional: !!str
  software: !!str
  sudo: !!str False
  perfimpact: !!str False
  parallelexclusive: !!str
```