Amazon Elastic Compute Cloud
Linux 实例用户指南
AWS 文档中描述的 AWS 服务或功能可能因区域而异。要查看适用于中国区域的差异,请参阅 Amazon AWS 入门

启动时在 Linux 实例上运行命令

当您在 Amazon EC2 中启动实例时,您可以选择将用户数据传递到可用于执行常见自动配置任务甚至在实例启动后运行脚本的实例。您可以将两类用户数据传递到 Amazon EC2:Shell 脚本和 cloud-init 指令。您还可以将这些数据以纯文本、文件 (这非常适合通过命令行工具启动实例) 或者 base64 编码文本 (用于 API 调用) 的形式传递到启动向导中。

如果您对更复杂的自动方案感兴趣,可以考虑使用 AWS CloudFormation 和 AWS OpsWorks。有关更多信息,请参阅 AWS CloudFormation 用户指南AWS OpsWorks 用户指南

有关在启动时在 Windows 实例上运行命令的信息,请参阅 Amazon EC2 用户指南(适用于 Windows 实例) 中的启动时在您的 Windows 实例上运行命令管理 Windows 实例配置

在以下示例中,安装 LAMP Web 服务器教程 中的命令转换成了 Shell 脚本和一组 cloud-init 指令,在实例启动时执行。在每个示例中,以下任务都根据用户数据执行:

  • 更新发布版软件包。

  • 安装必要的 Web 服务器、phpmysql 程序包。

  • 通过 chkconfig 启动和打开 httpd 服务。

  • 添加 www 组,将 ec2-user 添加到该组。

  • 为 Web 目录以及其中的文件设置适当的所有权和文件权限。

  • 创建简单网页来测试 Web 服务器和 PHP 引擎。

默认情况下,用户数据和 cloud-init 指令仅在您启动实例时的首次启动循环过程中运行。但是,AWS Marketplace 供应商和第三方 AMI 的所有者可能会提供自己的自定义项来确定脚本运行的方式和时间。

先决条件

以下示例假设实例具有可从 Internet 访问的公用 DNS 名称。有关更多信息,请参阅 步骤 1:启动实例。您还必须将安全组配置为允许 SSH (端口 22)、HTTP (端口 80) 和 HTTPS (端口 443) 连接。有关这些先决条件的更多信息,请参阅 Amazon EC2 的设置

此外,这些指令适用于 Amazon Linux,这些命令和指令可能不适用于其他 Linux 发布版。有关其他分发版本的更多信息,如它们对 cloud-init 的支持,请参阅其具体文档。

用户数据和 Shell 脚本

如果您熟悉 Shell 脚本编写,要在启动时将指令发送到实例,这是最简单、最完整的方式,cloud-init 输出日志文件 (/var/log/cloud-init-output.log) 捕获控制台输出,因此,如果实例出现意外行为,可在启动后方便地调试脚本。

重要

启动实例时,用户数据脚本和 cloud-init 指令仅在首次引导循环过程中运行。

用户数据 Shell 脚本必须以 #! 字符以及指向要读取脚本的解释器的路径 (通常为 /bin/bash) 开头。有关 Shell 脚本的精彩介绍,请参阅 Linux 文档项目 (tldp.org) 的 BASH 编程方法

作为用户数据输入的脚本是作为 root 用户加以执行的,因此在脚本中不使用 sudo 命令。请注意,您创建的任何文件都将归 root 所有;如果您需要非根用户具有文件访问权,应在脚本中相应地修改权限。此外,这是因为脚本不交互运行,所以无法包含要求用户反馈的命令 (如 yum update,无 -y 标志)。

在启动时添加这些任务会增加启动实例所需的时间。您应多等待几分钟让这些任务完成,然后测试用户脚本是否已成功完成。

用户数据和控制台

您可在启动实例时指定实例用户数据。如果实例的根卷是 EBS 卷,您还可以停止实例并更新其用户数据。

启动时指定实例用户数据

按照从 AMI 启动实例中介绍的实例启动过程操作,但在进行到该过程中的步骤 6时,在用户数据字段中复制 shell 脚本,然后完成启动过程。

在下面的示例脚本中,脚本将创建并配置我们的 Web 服务器。

#!/bin/bash yum update -y yum install -y httpd24 php56 mysql55-server php56-mysqlnd service httpd start chkconfig httpd on groupadd www usermod -a -G www ec2-user chown -R root:www /var/www chmod 2775 /var/www find /var/www -type d -exec chmod 2775 {} + find /var/www -type f -exec chmod 0664 {} + echo "<?php phpinfo(); ?>" > /var/www/html/phpinfo.php

让实例有足够的时间启动和执行脚本中的命令,然后查看脚本是否完成了预期的任务。

对于我们的示例,在 Web 浏览器中输入脚本创建的 PHP 测试文件的 URL。此 URL 是实例的公用 DNS 地址,后接正斜杠和文件名。

http://my.public.dns.amazonaws.com/phpinfo.php

您应该可以看到 PHP 信息页面。如果您无法看到 PHP 信息页,请检查所用的安全组是否包含允许 HTTP (端口 80) 通信的规则。有关更多信息,请参阅 向安全组添加规则

(可选) 如果脚本没有完成预期执行的任务,或者您要验证脚本是否正确完成,请检查 /var/log/cloud-init-output.log 上的 cloud-init 输出日志文件,在输出中查找错误消息。

对于其他调试信息,您可以使用以下指令创建包含 cloud-init 数据部分的 Mime 分段存档:

output : { all : '| tee -a /var/log/cloud-init-output.log' }

此指令将您脚本的命令输出发送到 /var/log/cloud-init-output.log。有关 cloud-init 数据格式以及创建 Mime 分段存档的更多信息,请参阅 cloud-init 格式

查看和更新实例用户数据

修改实例用户数据

  1. 打开 Amazon EC2 控制台 https://console.amazonaws.cn/ec2/

  2. 在导航窗格中,选择 Instances

  3. 选择所需实例,然后依次选择 ActionsInstance StateStop

    警告

    当您停止某个实例时,任何实例存储卷上的数据都将被擦除。因此,如果实例存储卷上有任何您要保留的数据,请确保将其备份到持久性存储。

  4. 当系统提示您确认时,选择 Yes, Stop。停止实例可能需要几分钟时间。

  5. 保持实例选定的情况下,依次选择操作实例设置查看/更改用户数据。如果实例正在运行,您不能更改用户数据,但是可以查看。

  6. View/Change User Data 对话框中,更新用户数据,然后选择 Save

  7. 重新启动实例。重新启动实例后,新的用户数据将在实例上可见;但不会执行用户数据脚本。

用户数据和 cloud-init 指令

cloud-init 程序包配置新 Amazon Linux 实例在启动时的特定方面;最值得注意的是,它为 ec2-user 配置 .ssh/authorized_keys 文件,以便您使用自己的私有密钥登录。有关更多信息,请参阅 cloud-init

可在启动时将 cloud-init 用户指令传递给实例,方式与传递脚本相同,只是语法不同。有关 cloud-init 的更多信息,请转到 http://cloudinit.readthedocs.org/en/latest/index.html

重要

启动实例后,用户数据脚本和 cloud-init 指令仅在首次启动循环过程中运行。

cloud-init 的 Amazon Linux 版本并不支持基程序包中的所有可用指令,其中一些指令已重命名 (如 repo_update,而不是 apt-upgrade)。

在启动时添加这些任务会增加启动实例所需的时间。您应多等待几分钟让这些任务完成,然后测试用户数据指令是否已完成。

使用用户数据将 cloud-init 指令传递给实例

  1. 按照从 AMI 启动实例中介绍的实例启动过程操作,但在进行到该过程中的步骤 6 时,在 User data 字段中输入 cloud-init 指令文本,然后完成启动过程。

    在下面的示例中,这些指令将创建并配置 Web 服务器。要将命令标识为 cloud-init 指令,顶部的 #cloud-config 行是必需的。

    #cloud-config repo_update: true repo_upgrade: all packages: - httpd24 - php56 - mysql55-server - php56-mysqlnd runcmd: - service httpd start - chkconfig httpd on - groupadd www - [ sh, -c, "usermod -a -G www ec2-user" ] - [ sh, -c, "chown -R root:www /var/www" ] - chmod 2775 /var/www - [ find, /var/www, -type, d, -exec, chmod, 2775, {}, + ] - [ find, /var/www, -type, f, -exec, chmod, 0664, {}, + ] - [ sh, -c, 'echo "<?php phpinfo(); ?>" > /var/www/html/phpinfo.php' ]
  2. 让实例有足够的时间启动和执行用户数据中的指令,然后查看指令是否完成了预期的任务。

    对于我们的示例,在 Web 浏览器中输入指令创建的 PHP 测试文件的 URL。此 URL 是实例的公用 DNS 地址,后接正斜杠和文件名。

    http://my.public.dns.amazonaws.com/phpinfo.php

    您应该可以看到 PHP 信息页面。如果您无法看到 PHP 信息页,请检查所用的安全组是否包含允许 HTTP (端口 80) 通信的规则。有关更多信息,请参阅 向安全组添加规则

  3. (可选) 如果指令没有完成预期执行的任务,或者如果您要验证指令是否正确完成,请检查 /var/log/cloud-init-output.log 上的输出日志文件,在输出中查找错误消息。对于其他调试信息,您可以将以下行添加到指令:

    output : { all : '| tee -a /var/log/cloud-init-output.log' }

    此指令将 runcmd 输出发送到 /var/log/cloud-init-output.log

用户数据和 AWS CLI

您可以使用 AWS CLI 指定、修改和查看实例的用户数据。有关使用实例元数据从实例查看用户数据的信息,请参阅检索实例用户数据

在 Windows 上,您可以使用 适用于 Windows PowerShell 的 AWS 工具 而不是使用 AWS CLI。有关更多信息,请参阅 Amazon EC2 用户指南(适用于 Windows 实例) 中的用户数据和 Windows PowerShell 工具

示例:启动时指定用户数据

要在启动实例时指定用户数据,请结合使用 run-instances 命令与 --user-data 参数。使用 run-instances 时,AWS CLI 会为您对用户数据执行 base64 编码。

以下示例显示如何在命令行上指定字符串形式的脚本:

aws ec2 run-instances --image-id ami-abcd1234 --count 1 --instance-type m3.medium \ --key-name my-key-pair --subnet-id subnet-abcd1234 --security-group-ids sg-abcd1234 \ --user-data echo user data

以下示例显示如何使用文本文件指定脚本。请务必使用 file:// 前缀指定该文件。

aws ec2 run-instances --image-id ami-abcd1234 --count 1 --instance-type m3.medium \ --key-name my-key-pair --subnet-id subnet-abcd1234 --security-group-ids sg-abcd1234 \ --user-data file://my_script.txt

以下是具有 Shell 脚本的示例文本文件。

#!/bin/bash yum update -y service httpd start chkconfig httpd on

示例:修改已停止的实例的用户数据

您可以使用 modify-instance-attribute 命令修改已停止的实例的用户数据。使用 modify-instance-attribute 时,AWS CLI 不会为您对用户数据执行 base64 编码。

在 Linux 上,使用 base64 命令对用户数据进行编码。

base64 my_script.txt >my_script_base64.txt

在 Windows 上,使用 certutil 命令可对用户数据进行编码。您必须先删除第一行 (BEGIN CERTIFICATE) 和最后一行 (END CERTIFICATE),然后才能将此文件用于 AWS CLI。

certutil -encode my_script.txt my_script_base64.txt notepad my_script_base64.txt

使用 --user-data--value 参数可通过编码的文本文件指定用户数据。请务必使用 file:// 前缀指定该文件。

aws ec2 modify-instance-attribute --instance-id i-1234567890abcdef0 --attribute userData --value file://my_script_base64.txt

示例:查看用户数据

要检索实例的用户数据,请使用 describe-instance-attribute 命令。使用 describe-instance-attribute 时,AWS CLI 不会为您对用户数据执行 base64 解码。

aws ec2 describe-instance-attribute --instance-id i-1234567890abcdef0 --attribute userData

以下是具有已进行 base64 编码的用户数据的示例输出。

{ "UserData": { "Value": "IyEvYmluL2Jhc2gKeXVtIHVwZGF0ZSAteQpzZXJ2aWNlIGh0dHBkIHN0YXJ0CmNoa2NvbmZpZyBodHRwZCBvbg==" }, "InstanceId": "i-1234567890abcdef0" }

在 Linux 上,使用 --query 选项获取编码的用户数据和用于对该数据进行解码的 base64 命令。

aws ec2 describe-instance-attribute --instance-id i-1234567890abcdef0 --attribute userData --output text --query "UserData.Value" | base64 --decode

在 Windows 上,使用 --query 选项获取编码的用户数据和用于对该数据进行解码的 certutil 命令。请注意,编码的输出存储在一个文件中,解码的输出存储在另一个文件中。

aws ec2 describe-instance-attribute --instance-id i-1234567890abcdef0 --attribute userData --output text --query "UserData.Value" >my_output.txt certutil -decode my_output.txt my_output_decoded.txt type my_output_decoded.txt

下面是示例输出。

#!/bin/bash yum update -y service httpd start chkconfig httpd on