

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

# S3 DistCp (s3-dist-cp)
<a name="UsingEMR_s3distcp"></a>

Apache DistCp 是一个开源工具，你可以用来复制大量数据。S3 与 *DistCpAmazon S3* 类似 DistCp，但经过了优化 AWS，尤其是 Amazon S3。DistCp 在 Amazon EMR 4.0 及更高版本中，S3 的命令是`s3-dist-cp`，您可以将其作为集群中的一个步骤或在命令行中添加。使用 S3DistCp，您可以高效地将大量数据从 Amazon S3 复制到 HDFS 中，然后通过您的 Amazon EMR 集群中的后续步骤进行处理。您也可以使用 S3 DistCp 在亚马逊 S3 存储桶之间复制数据，或者从 HDFS 复制数据到 Amazon S3。S3 DistCp 在跨存储桶和跨 AWS 账户并行复制大量对象方面更具可扩展性和效率。

有关在现实场景中演示 S3DistCp 灵活性的特定命令，请参阅 AWS 大数据博客DistCp上[的 S3 使用七个技巧](https://aws.amazon.com/blogs/big-data/seven-tips-for-using-s3distcp-on-amazon-emr-to-move-data-efficiently-between-hdfs-and-amazon-s3/)。

比如 DistCp，S3 DistCp MapReduce 使用分布式方式进行复制。它在几个服务器之间共享复制、错误处理、恢复和报告任务。有关 Apache DistCp 开源项目的更多信息，请参阅 Apache Hadoop 文档中的[DistCp指南](http://hadoop.apache.org/docs/stable/hadoop-distcp/DistCp.html)。

如果 DistCp S3 无法复制部分或全部指定文件，则集群步骤将失败并返回非零错误代码。如果发生这种情况，S3 DistCp 不会清理部分复制的文件。

**重要**  
S3 DistCp 不支持包含下划线字符的 Amazon S3 存储桶名称。  
S3 DistCp 不支持 Parquet 文件的串联。 PySpark 改用。有关更多信息，请参阅[在 Amazon EMR 中串连 parquet 文件](https://aws.amazon.com/premiumsupport/knowledge-center/emr-concatenate-parquet-files/)。  
为避免在使用 S3DistCP 将单个文件（而不是目录）从 S3 复制到 HDFS 时出现复制错误，请使用 Amazon EMR 版本 5.33.0 或更高版本或 Amazon EMR 6.3.0 或更高版本。

## S3 DistCp 选项
<a name="UsingEMR_s3distcp.options"></a>

尽管与之类似 DistCp，但 S3 DistCp 支持一组不同的选项来更改其复制和压缩数据的方式。

调用 S3 时DistCp，您可以指定下表中描述的选项。选项是用参数列表添加到步骤的。下表显示了 S3 DistCp 参数的示例。


| 选项  | 描述  | 必填  | 
| --- | --- | --- | 
| ‑‑src=LOCATION  |  待复制数据的位置。可以是 HDFS 或 Amazon S3 位置。 示例：`‑‑src=s3://amzn-s3-demo-bucket/logs/j-3GYXXXXXX9IOJ/node`  S3 DistCp 不支持包含下划线字符的 Amazon S3 存储桶名称。   | 是  | 
| ‑‑dest=LOCATION  |  数据的目标位置。可以是 HDFS 或 Amazon S3 位置。 示例：`‑‑dest=hdfs:///output`  S3 DistCp 不支持包含下划线字符的 Amazon S3 存储桶名称。   | 是  | 
| ‑‑srcPattern=PATTERN  |  该[正则表达式](http://en.wikipedia.org/wiki/Regular_expression)会筛选 `‑‑src` 的部分数据的复制操作。如果指定的既不是 `‑‑srcPattern` 也不是 `‑‑groupBy`，那么会将 `‑‑src` 的所有数据复制到 `‑‑dest`。 如果正则表达式参数包含特殊字符，如星号（\$1），那么必须将正则表达式或整个 `‑‑args` 字符串括在单引号（'）中。 示例：`‑‑srcPattern=.*daemons.*-hadoop-.*`  | 否  | 
| ‑‑groupBy=PATTERN  |  一种[正则表达式](http://en.wikipedia.org/wiki/Regular_expression)，它使 S3 DistCp 连接与该表达式匹配的文件。例如，您可以使用此选项把一个小时内写入的所有日志文件组合成为单个文件。已连接文件的文件名是与该分组的正则表达式相匹配的值。 圆括号表明文件应使用的分组方式，与圆括号内的语句匹配的所有项目都组合成单个输出文件。如果正则表达式不包含带括号的语句，则集群将在 S3 DistCp 步骤上失败并返回错误。 如果正则表达式参数包含特殊字符，如星号（\$1），那么必须将正则表达式或整个 `‑‑args` 字符串括在单引号（'）中。 如果指定 `‑‑groupBy`，则仅复制与指定的模式匹配的文件。您不需要同时指定 `‑‑groupBy` 和 `‑‑srcPattern`。 示例：`‑‑groupBy=.*subnetid.*([0-9]+-[0-9]+-[0-9]+-[0-9]+).*`  | 否  | 
| ‑‑targetSize=SIZE  |  要根据 `‑‑groupBy` 选项创建的文件的大小，以兆字节 (MiB) 为单位。此值必须是整数。设置后`‑‑targetSize`，S3 DistCp 会尝试匹配此大小；复制文件的实际大小可能大于或小于此值。基于数据文件大小聚合任务，因此目标文件大小将可能匹配源数据文件大小。 如果由 `‑‑groupBy` 连接的文件大于 `‑‑targetSize` 的值，则将这些文件分解成部分文件，并在末尾附加一个数值按顺序命名。例如，连接组成 `myfile.gz` 的一个文件将被分解成部分文件，如：`myfile0.gz`、`myfile1.gz` 等。 示例：`‑‑targetSize=2`  | 否  | 
| ‑‑appendToLastFile |  指定 S3 在从 Amazon S3 复制到 HDFS 中已存在的文件DistCp 时的行为。它向现有文件附加新文件数据。如果将 `‑‑appendToLastFile` 与 `‑‑groupBy` 结合使用，则将新数据附加到与相同的组匹配的文件。与 `‑‑targetSize` 结合使用时，此选项也具有 `‑‑groupBy.` 行为  | 否  | 
| ‑‑outputCodec=CODEC  |  指定用于所复制文件的压缩编解码器。取值可以是：`gzip`、`gz`、`lzo`、`snappy` 或 `none`。您可以使用此选项，例如，把 Gzip 压缩的输入文件转换为 LZO 压缩的输出文件，或对文件进行解压缩，作为复制操作的一部分。如果选择输出编解码器，则系统会在文件名末尾追加适当的扩展名 (例如，对于 `gz` 和 `gzip`，将追加扩展名 `.gz`)。如果不为 `‑‑outputCodec` 指定值，则复制的文件不会出现压缩方面的变化。 示例：`‑‑outputCodec=lzo`  | 否  | 
| ‑‑s3ServerSideEncryption  |  确保使用 SSL 传输目标数据，并使用 AWS 服务端密钥在 Amazon S3 中自动加密。使用 S3 检索数据时DistCp，对象会自动解密。如果尝试将未加密的对象复制到需要加密的 Amazon S3 存储桶，则操作将失败。有关更多信息，请参阅[使用数据加密](https://docs.aws.amazon.com/AmazonS3/latest/userguide/UsingEncryption.html)。 示例：`‑‑s3ServerSideEncryption`  | 否  | 
| ‑‑deleteOnSuccess  |  如果复制操作成功，则此选项会导致 S3 DistCp 从源位置删除复制的文件。如果您以计划任务的形式将输出文件 (如日志文件) 从一个位置复制到另一个位置，又不想复制两次相同的文件，那么这个选项会非常有用。 示例：`‑‑deleteOnSuccess`  | 否  | 
| ‑‑disableMultipartUpload  |  禁用分段上载。 示例：`‑‑disableMultipartUpload`  | 否  | 
| ‑‑multipartUploadChunkSize=SIZE  |  Amazon S3 分段上传中每个分段的大小，以 MiB 为单位。当 S3 复制的数据大于时，它会DistCp 使用分段上传。`multipartUploadChunkSize`要提高作业性能，可以增加每个分段的大小。默认大小为 128 MiB。 示例：`‑‑multipartUploadChunkSize=1000`  | 否  | 
| ‑‑numberFiles  |  在输出文件之前加上序号。计数从 0 开始，除非 `‑‑startingIndex` 指定一个不同的值。 示例：`‑‑numberFiles`  | 否  | 
| ‑‑startingIndex=INDEX  |  使用 `‑‑numberFiles` 指定序列中的第一个数字。 示例：`‑‑startingIndex=1`  | 否  | 
| ‑‑outputManifest=FILENAME  |  创建使用 Gzip 压缩的文本文件，其中包含 S3 DistCp 复制的所有文件的列表。 示例：`‑‑outputManifest=manifest-1.gz`  | 否  | 
| ‑‑previousManifest=PATH  |  DistCp 使用`‑‑outputManifest`标志读取上次调用 S3 期间创建的清单文件。设置该`‑‑previousManifest`标志后，S3 会将清单中列出的文件DistCp 排除在复制操作之外。如果同时指定 `‑‑outputManifest` 和 `‑‑previousManifest`，则之前清单中列出的文件也会出现在新的清单文件中，但不会复制这些文件。 示例：`‑‑previousManifest=/usr/bin/manifest-1.gz`  | 否  | 
| ‑‑requirePreviousManifest |  需要先前在调用 S3 时创建的清单DistCp。如果将它设置为 false，则不指定之前的清单也不会生成错误。默认值为 true。  | 否  | 
| ‑‑copyFromManifest  |  反转的行为`‑‑previousManifest`，使 S3 DistCp 使用指定的清单文件作为要复制的文件列表，而不是要从复制中排除的文件列表。 示例：`‑‑copyFromManifest ‑‑previousManifest=/usr/bin/manifest-1.gz`  | 否  | 
| ‑‑s3Endpoint=ENDPOINT |  指定上载文件时要使用的 Amazon S3 终端节点。此选项会同时设置源位置和目标位置的终端节点。如果未设置，则默认终端节点是 `s3.amazonaws.com`。有关 Amazon S3 终端节点的列表，请参阅[区域和终端节点](https://docs.aws.amazon.com/general/latest/gr/rande.html#s3_region)。 示例：`‑‑s3Endpoint=s3.eu-west-1.amazonaws.com`  | 否  | 
| ‑‑storageClass=CLASS |  目标为 Amazon S3 时要使用的存储类。有效值是 STANDARD 和 REDUCED\$1REDUNDANCY。如果未指定此选项，S3 将DistCp 尝试保留存储类别。 示例：`‑‑storageClass=STANDARD`  | 否  | 
| ‑‑srcPrefixesFile=PATH |  Amazon S3（s3://）、HDFS（hdfs:///）或本地文件系统（file:/）中包含 `src` 前缀的文本文件（每行一个前缀）。 如果提供`srcPrefixesFile`，S3 DistCp 将不会列出 src 路径。相反，它将生成一个源列表，以作为列出在此文件中指定的所有前缀的组合结果。与 src 相比较的相对路径 (而不是这些前缀) 将用于生成目标路径。如果还指定了 `srcPattern`，则会将它应用于源前缀的组合列表结果以进一步筛选输入。如果使用了 `copyFromManifest`，则会复制清单中的对象并忽略 `srcPrefixesFile`。 示例：`‑‑srcPrefixesFile=PATH`  | 否  | 

除了上述选项外，S3 还DistCp 实现了[工具接口](https://hadoop.apache.org/docs/current/api/org/apache/hadoop/util/Tool.html)，这意味着它支持通用选项。

## 将 S3 DistCp 作为集群中的步骤添加
<a name="UsingEMR_s3distcp.step"></a>

您可以DistCp 通过将 S3 作为步骤添加到集群中来调用 S3。可以使用控制台、CLI 或 API 在启动时向集群或是向正在运行的集群添加步骤。以下示例演示如何向正在运行的集群添加 S3 DistCp 步骤。有关向集群添加步骤的更多信息，请参阅《Amazon EMR 管理指南》**中的[向集群提交工作](https://docs.aws.amazon.com/emr/latest/ManagementGuide/emr-work-with-steps.html)。

**要向正在运行的集群添加 S3 DistCp 步骤，请使用 AWS CLI**

有关在中使用 Amazon EMR 命令的更多信息 AWS CLI，请参阅[AWS CLI 命令](https://docs.aws.amazon.com/cli/latest/reference/emr)参考。
+ 要向调用 S3 的集群添加步骤DistCp，请将指定 S3 DistCp 应如何执行复制操作的参数作为参数传递。

  以下示例将守护进程日志从 Amazon S3 复制到 `hdfs:///output`。在以下命令中：
  + `‑‑cluster-id` 指定集群
  + `Jar`是 S3 DistCp JAR 文件的位置。如需有关如何使用 command-runner.jar 在群集上运行命令的示例，请参阅[提交自定义 JAR 步骤以运行脚本或命令](https://docs.aws.amazon.com/emr/latest/ReleaseGuide/emr-commandrunner.html#emr-commandrunner-examples)。
  + `Args`是要传入 S3 的选项名称/值对的逗号分隔列表。DistCp有关可用选项的完整列表，请参阅[S3 DistCp 选项](#UsingEMR_s3distcp.options)。

  要向正在运行的集群添加 S3 DistCp 复制步骤，请将以下内容放入保存在 Amazon S3 或本地文件系统中的 JSON 文件中，如`myStep.json`本示例所示。*j-3GYXXXXXX9IOK*替换为您的集群 ID，然后*amzn-s3-demo-bucket*替换为您的 Amazon S3 存储桶名称。

  ```
  [
      {
          "Name":"S3DistCp step",
          "Args":["s3-dist-cp","‑‑s3Endpoint=s3.amazonaws.com","‑‑src=s3://amzn-s3-demo-bucket/logs/j-3GYXXXXXX9IOJ/node/","‑‑dest=hdfs:///output","‑‑srcPattern=.*[a-zA-Z,]+"],
          "ActionOnFailure":"CONTINUE",
          "Type":"CUSTOM_JAR",
          "Jar":"command-runner.jar"        
      }
  ]
  ```

  ```
  aws emr add-steps ‑‑cluster-id j-3GYXXXXXX9IOK ‑‑steps file://./myStep.json
  ```

**Example 从 Amazon S3 向 HDFS 复制日志文件**  
此示例还说明如何通过向正在运行的集群添加步骤来将 Amazon S3 存储桶中存储的日志文件复制到 HDFS 中。在此示例中，`‑‑srcPattern` 选项用于限制复制到守护程序日志的数据。  
要使用 `‑‑srcPattern` 选项将日志文件从 Amazon S3 复制到 HDFS，请在某个 JSON 文件（本例中为 `myStep.json`）中输入以下内容并保存到 Amazon S3 或本地文件系统中。*j-3GYXXXXXX9IOK*替换为您的集群 ID，然后*amzn-s3-demo-bucket*替换为您的 Amazon S3 存储桶名称。  

```
[
    {
        "Name":"S3DistCp step",
        "Args":["s3-dist-cp","‑‑s3Endpoint=s3.amazonaws.com","‑‑src=s3://amzn-s3-demo-bucket/logs/j-3GYXXXXXX9IOJ/node/","‑‑dest=hdfs:///output","‑‑srcPattern=.*daemons.*-hadoop-.*"],
        "ActionOnFailure":"CONTINUE",
        "Type":"CUSTOM_JAR",
        "Jar":"command-runner.jar"        
    }
]
```