按照
启动实例
的程序进行操作。
User data
(用户数据)字段位于启动实例向导的
高级详细信息
部分。在
User data
(用户数据)字段中输入您的 cloud-init 指令文本,然后完成实例启动程序。
在以下示例中,这些指令在 Amazon Linux 2 上创建并配置 Web 服务器。要将命令标识为 cloud-init 指令,顶部的
#cloud-config
行是必需的。
#cloud-config
repo_update: true
repo_upgrade: all
packages:
- httpd
- mariadb-server
runcmd:
- [ sh, -c, "amazon-linux-extras install -y lamp-mariadb10.2-php7.2 php7.2" ]
- systemctl start httpd
- sudo systemctl enable httpd
- [ sh, -c, "usermod -a -G apache ec2-user" ]
- [ sh, -c, "chown -R ec2-user:apache /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' ]
让实例有足够的时间启动和运行用户数据中的指令,然后查看指令是否完成了预期的任务。
对于此示例,在 Web 浏览器中输入指令创建的 PHP 测试文件的 URL。此 URL 是实例的公用 DNS 地址,后接正斜杠和文件名。
http://my.public.dns.amazonaws.com
/phpinfo.php
您应该会看到 PHP 信息页面。如果您无法看到 PHP 信息页,请检查所用的安全组是否包含允许 HTTP (端口 80) 通信的规则。有关更多信息,请参阅
配置安全组规则
。
(可选)如果您的指令没有完成您期望的任务,或者如果您只是想验证您的指令是否已完成且没有错误,
请连接到实例
,检查输出日志文件 (
/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 指定、修改和查看实例的用户数据。有关使用实例元数据从实例查看用户数据的信息,请参阅
从实例检索实例用户数据
。
在 Windows 上,您可以使用 AWS Tools for Windows PowerShell 而不是使用 AWS CLI。有关更多信息,请参阅
用户数据和 Tools for 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 编码。
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
使用
--attribute
和
--value
参数可通过编码的文本文件指定用户数据。请务必使用
file://
前缀指定该文件。
aws ec2 modify-instance-attribute --instance-id i-1234567890abcdef0
--attribute userData --value file://my_script_base64.txt
示例:清除停止的实例的用户数据
要删除现有的用户数据,请按以下方式使用
modify-instance-attribute
命令:
aws ec2 modify-instance-attribute --instance-id i-1234567890abcdef0
--user-data Value=
示例:查看用户数据
要检索实例的用户数据,请使用
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
将 Shell 脚本和 cloud-init 指令组合使用
默认情况下,一次只能在用户数据中包含一个内容类型。不过,您可以在 mime-multi part 文件中使用
text/cloud-config
和
text/x-shellscript
,以便在用户数据中同时包含 Shell 脚本和 cloud-init 指令。
下面显示了 mime-multi part 的格式。
Content-Type: multipart/mixed; boundary="//"
MIME-Version: 1.0
Content-Type: text/cloud-config; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment; filename="cloud-config.txt"
#cloud-config
cloud-init directives
Content-Type: text/x-shellscript; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment; filename="userdata.txt"
#!/bin/bash
shell script commands
--//--
例如,以下用户数据包含了 cloud-init 指令和 bash Shell 脚本。cloud-init 指令会创建一个文件(
/test-cloudinit/cloud-init.txt
),然后将
Created by cloud-init
写入该文件。bash Shell 脚本会创建一个文件(
/test-userscript/userscript.txt
),然后将
Created by bash shell script
写入该文件。
Content-Type: multipart/mixed; boundary="//"
MIME-Version: 1.0
Content-Type: text/cloud-config; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment; filename="cloud-config.txt"
#cloud-config
runcmd:
- [ mkdir, /test-cloudinit ]
write_files:
- path: /test-cloudinit/cloud-init.txt
content: Created by cloud-init
Content-Type: text/x-shellscript; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment; filename="userdata.txt"
#!/bin/bash
mkdir test-userscript
touch /test-userscript/userscript.txt
echo "Created by bash shell script" >> /test-userscript/userscript.txt
--//--
Amazon EC2 如何处理 Windows 实例的用户数据
在 Windows 实例上,启动代理会执行与用户数据相关的任务。有关更多信息,请参阅下列内容:
有关
UserData
模板中 AWS CloudFormation 属性的程序集示例,请参阅
Base64 编码 UserData 属性
和
带 AccessKey 和 SecretKey 的 Base64 编码 UserData 属性
。
有关在使用生命周期挂钩的自动扩缩组中实例上运行命令的示例,请参阅《Amazon EC2 Auto Scaling User Guide》
中的
Tutorial: Configure user data to retrieve the target lifecycle state through instance metadata
。
用户数据脚本
要让
EC2Config
或
EC2Launch
运行脚本,在将脚本添加到用户数据中时,您必须将脚本封装在特殊标签中。您使用的标签取决于命令是在命令提示符窗口(批处理命令)中还是使用 Windows PowerShell 运行。
如果同时指定批处理脚本和 Windows PowerShell 脚本,则批处理脚本先运行,然后运行 Windows PowerShell 脚本,不论这些脚本在实例用户数据中的显示顺序如何。
如果您在用户数据脚本中使用 AWS API(包括 AWS CLI),则在启动实例时必须使用实例配置文件。实例配置文件提供用户数据脚本执行 API 调用所需的适当 AWS 凭证。有关更多信息,请参阅
实例配置文件
。您分配给 IAM 角色的权限取决于您使用 API 调用的服务。有关更多信息,请参阅
适用于 Amazon EC2 的 IAM 角色
。
批处理脚本的语法
使用
script
标签指定批处理脚本。使用换行符分隔命令,如以下示例所示。
<script>
echo Current date and time >> %SystemRoot%\Temp\test.log
echo %DATE% %TIME% >> %SystemRoot%\Temp\test.log
</script>
默认情况下,用户数据脚本在您启动实例时运行一次。要在每次重新引导或启动实例时运行用户数据脚本,请将
<persist>true</persist>
添加到用户数据。
<script>
echo Current date and time >> %SystemRoot%\Temp\test.log
echo %DATE% %TIME% >> %SystemRoot%\Temp\test.log
</script>
<persist>true</persist>
EC2Launch v2 代理
要在 EC2Launch v2
executeScript
任务处于
UserData
阶段时将 XML 用户数据脚本作为分离的进程运行,请向用户数据添加
<detach>true</detach>
。
<script>
echo Current date and time >> %SystemRoot%\Temp\test.log
echo %DATE% %TIME% >> %SystemRoot%\Temp\test.log
</script>
<detach>true</detach>
Windows PowerShell 脚本的语法
AWS Windows AMI 包括
AWS Tools for Windows PowerShell
,因此您可在用户数据中指定这些 cmdlet。如果您将一个 IAM 角色与实例相关联,那么您不必为 cmdlet 指定凭证,因为实例上运行的应用程序可以使用该角色的凭证访问AWS资源(例如 Amazon S3 存储桶)。
使用
<powershell>
标签指定 Windows PowerShell 脚本。使用换行符分隔命令。
<powershell>
标签区分大小写。
<powershell>
$file = $env:SystemRoot + "\Temp\" + (Get-Date).ToString("MM-dd-yy-hh-mm")
New-Item $file -ItemType file
</powershell>
默认情况下,用户数据脚本会在您启动实例时运行一次。要在每次重新引导或启动实例时运行用户数据脚本,请将
<persist>true</persist>
添加到用户数据。
<powershell>
$file = $env:SystemRoot + "\Temp\" + (Get-Date).ToString("MM-dd-yy-hh-mm")
New-Item $file -ItemType file
</powershell>
<persist>true</persist>
您可以使用
<powershellArguments>
标签来指定一个或多个 PowerShell 参数。如果未传递任何参数,则默认情况下,EC2Launch 和 EC2Launch v2 会添加以下参数:
-ExecutionPolicy Unrestricted
。
<powershell>
$file = $env:SystemRoot + "\Temp" + (Get-Date).ToString("MM-dd-yy-hh-mm")
New-Item $file -ItemType file
</powershell>
<powershellArguments>-ExecutionPolicy Unrestricted -NoProfile -NonInteractive</powershellArguments>
EC2Launch v2 代理
要在 EC2Launch v2
executeScript
任务处于
UserData
阶段时将 XML 用户数据脚本作为分离的进程运行,请向用户数据添加
<detach>true</detach>
。
<powershell>
$file = $env:SystemRoot + "\Temp\" + (Get-Date).ToString("MM-dd-yy-hh-mm")
New-Item $file -ItemType file
</powershell>
<detach>true</detach>
YAML 配置脚本的语法
如果使用 EC2Launch v2 运行脚本,则可以使用 YAML 格式。要查看 EC2Launch v2 的配置任务、详细信息和示例,请参阅
EC2Launch v2 任务配置
。
使用
executeScript
任务指定 YAML 脚本。
运行 PowerShell 脚本的 YAML 语法示例
version: 1.0
tasks:
- task: executeScript
inputs:
- frequency: always
type: powershell
runAs: localSystem
content: |-
$file = $env:SystemRoot + "\Temp\" + (Get-Date).ToString("MM-dd-yy-hh-mm")
New-Item $file -ItemType file
运行批处理脚本的 YAML 语法示例
version: 1.1
tasks:
- task: executeScript
inputs:
- frequency: always
type: batch
runAs: localSystem
content: |-
echo Current date and time >> %SystemRoot%\Temp\test.log
echo %DATE% %TIME% >> %SystemRoot%\Temp\test.log
Base64 编码
如果使用的是 Amazon EC2 API 或不对用户数据执行 base64 编码的工具,则您必须自行对用户数据进行编码。否则,系统会记录找不到要运行的
script
或
powershell
标签的错误。下面是使用 Windows PowerShell 进行编码的示例。
$UserData = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes($Script))
下面是一个使用 PowerShell 进行解码的示例。
$Script = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($UserData))
有关 base64 编码的更多信息,请参阅
https://www.ietf.org/rfc/rfc4648.txt
。
用户数据执行
默认情况下,所有 AWS Windows AMI 均已为初次启动启用了用户数据执行。您可以指定用户数据脚本在下次实例重新引导或重启时运行。此外,您可以指定用户数据脚本在每次实例重新引导或重启时运行。
默认情况下不会使用户数据在首次启动后运行。要使用户数据在实例重启或启动时运行,请参阅
后续重新引导或启动
。
生成随机密码之后,从本地管理员账户运行用户数据脚本。否则,从系统账户运行用户数据脚本。
实例用户数据中的脚本在实例的初次启动期间运行。如果找到
persist
标签,则为后续重新引导或启动启用用户数据执行。EC2Launch v2、EC2Launch 和 EC2Config 的日志文件包含源自标准输出和标准错误流的输出。
EC2Launch v2
EC2Launch v2 的日志文件为
C:\ProgramData\Amazon\EC2Launch\log\agent.log
。
C:\ProgramData
文件夹可能已隐藏。要查看该文件夹,您必须显示隐藏的文件和文件夹。
执行用户数据时将记录以下信息:
Info: Converting user-data to yaml format
– 如果用户数据是以 XML 格式提供的
Info: Initialize user-data state
– 用户数据执行开始
Info: Frequency is: always
– 如果每次启动时都运行用户数据任务
Info: Frequency is: once
– 如果用户数据任务只运行一次
Stage: postReadyUserData execution completed
– 用户数据执行结束
EC2Launch
EC2Launch 的日志文件为
C:\ProgramData\Amazon\EC2-Windows\Launch\Log\UserdataExecution.log
。
C:\ProgramData
文件夹可能已隐藏。要查看该文件夹,您必须显示隐藏的文件和文件夹。
执行用户数据时将记录以下信息:
<script> tag was provided.. running script content
– 如果找到脚本标签
Message: The output from user scripts
– 如果运行用户数据脚本,则会记录其输出
EC2Config
EC2Config 的日志文件为
C:\Program
Files\Amazon\Ec2ConfigService\Logs\Ec2Config.log
。执行用户数据时将记录以下信息:
Ec2HandleUserData: Message: Start running user scripts
– 用户数据执行开始
Ec2HandleUserData: Message: Re-enabled userdata execution
– 找到持久标签时
Ec2HandleUserData: Message: Could not find <persist> and
</persist>
– 如果未找到持久标签
Ec2HandleUserData: Message: The output from user scripts
– 如果运行用户数据脚本,则会记录其输出
后续重新引导或启动
在您更新实例用户数据后,重新引导或启动实例时不会自动运行用户数据脚本。不过,您可以启用用户数据执行,这样用户数据脚本在您重新引导或启动实例时运行一次,或者在每次重新引导或启动实例时执行。
如果您选择
使用 Sysprep 关闭
选项,则用户数据脚本将在下一次实例启动或重新引导时运行,即使您没有为后续的重新引导或启动启用用户数据执行,也是如此。在后续重新引导或启动时,将不执行用户数据脚本。
使用 EC2Launch v2 启用用户数据执行
打开 PowerShell 命令窗口,并运行以下命令:
C:\ProgramData\Amazon\EC2-Windows\Launch\Scripts\InitializeInstance.ps1 -Schedule
从 Windows 实例断开连接。要在下次实例启动时运行更新后的脚本,请停止实例并更新用户数据。
使用 EC2Config 启用用户数据执行
-
连接到您的 Windows 实例。
打开
C:\Program
Files\Amazon\Ec2ConfigService\Ec2ConfigServiceSetting.exe
。
对于
用户数据
,选择
Enable UserData execution for next service start
(为下次服务启动启用用户数据执行)。
从 Windows 实例断开连接。要在下次实例启动时运行更新后的脚本,请停止实例并更新用户数据。
启动时指定实例用户数据
按照
启动实例
的程序进行操作。
User data
(用户数据)字段位于启动实例向导的
高级详细信息
部分。在
用户数据
字段中输入您的 PowerShell 脚本,然后完成实例启动程序。
在
用户数据
字段的屏幕截图中,示例脚本在 Windows 临时文件夹中创建文件,在文件名中使用当前日期和时间。当您包括
<persist>true</persist>
时,每次重新引导或启动实例时将运行脚本。如果将
用户数据已执行 base64 编码
复选框保留为空,Amazon EC2 控制台将执行 base64 编码。
您可以查看任何实例的实例用户数据,也可以更新已停止实例的实例用户数据。
使用控制台更新实例的用户数据
-
通过以下网址打开 Amazon EC2 控制台:
https://console.aws.amazon.com/ec2/
。
-
在导航窗格中,选择
实例
。
选择所需实例,然后依次选择
操作
、
实例状态
、
停止实例
。
当您停止某个实例时,任何实例存储卷上的数据都将被擦除。要保留实例存储卷中的数据,请确保将其备份到持久性存储中。
-
当系统提示您确认时,选择
Stop
。停止实例可能需要几分钟时间。
在实例仍被选中的情况下,依次选择
操作
、
实例设置
和
编辑用户数据
。如果实例正在运行,您不能更改用户数据,但是可以查看。
在
Edit user data (编辑用户数据)
对话框中,更新用户数据,然后选择
Save (保存)
。要在每次重新引导或启动实例时运行用户数据脚本,请添加
<persist>true</persist>
,如下例中所示。
用户数据和 Tools for Windows PowerShell
您可以使用 Tools for Windows PowerShell 指定、修改和查看实例的用户数据。有关使用实例元数据从实例查看用户数据的信息,请参阅
从实例检索实例用户数据
。有关用户数据和 AWS CLI 的信息,请参阅
用户数据和 AWS CLI
。
示例:启动时指定实例用户数据
使用实例用户数据创建一个文本文件。要在每次重新引导或启动实例时运行用户数据脚本,请添加
<persist>true</persist>
,如下例中所示。
<powershell>
$file = $env:SystemRoot + "\Temp\" + (Get-Date).ToString("MM-dd-yy-hh-mm")
New-Item $file -ItemType file
</powershell>
<persist>true</persist>
要在启动实例时指定实例用户数据,请使用
New-EC2Instance
命令。该命令不会对用户数据进行 base64 编码。使用以下命令在名为
script.txt
的文本文件中对用户数据进行编码。
PS C:\>
$Script = Get-Content -Raw script.txt
PS C:\>
$UserData = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes($Script))
使用
-UserData
参数可将用户数据传递到
New-EC2Instance
命令。
PS C:\>
New-EC2Instance -ImageId ami-abcd1234
-MinCount 1
-MaxCount 1
-InstanceType m3.medium
\
-KeyName my-key-pair
-SubnetId subnet-12345678
-SecurityGroupIds sg-1a2b3c4d
\
-UserData $UserData
示例:更新已停止实例的实例用户数据
您可以使用
Edit-EC2InstanceAttribute
命令修改已停止的实例的用户数据。
使用新脚本创建一个文本文件。使用以下命令在名为
new-script.txt
的文本文件中对用户数据进行编码。
PS C:\>
$NewScript = Get-Content -Raw new-script.txt
PS C:\>
$NewUserData = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes($NewScript))
使用
-UserData
和
-Value
参数可指定用户数据。
PS C:\>
Edit-EC2InstanceAttribute -InstanceId i-1234567890abcdef0
-Attribute userData -Value $NewUserData
示例:查看实例用户数据
要检索实例的用户数据,请使用
Get-EC2InstanceAttribute
命令。
PS C:\>
(Get-EC2InstanceAttribute -InstanceId i-1234567890abcdef0
-Attribute userData).UserData
下面是示例输出。请注意,用户数据已编码。
PHBvd2Vyc2hlbGw+DQpSZW5hbWUtQ29tcHV0ZXIgLU5ld05hbWUgdXNlci1kYXRhLXRlc3QNCjwvcG93ZXJzaGVsbD4=
使用以下命令可将已编码的用户数据存储在变量中,然后对其进行编码。
PS C:\>
$UserData_encoded = (Get-EC2InstanceAttribute -InstanceId i-1234567890abcdef0
-Attribute userData).UserData
PS C:\>
[System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($UserData_encoded))
下面是示例输出。
<powershell>
$file = $env:SystemRoot + "\Temp\" + (Get-Date).ToString("MM-dd-yy-hh-mm")
New-Item $file -ItemType file
</powershell>
<persist>true</persist>
示例:重命名实例以匹配标签值
要读取标签值、在首次启动时重命名实例以匹配标签值并重新启动,您可以使用
Get-EC2Tag
命令。要成功运行此命令,您必须将具有
ec2:DescribeTags
权限的角色附加到实例上,因为标签信息通过 API 调用检索。有关使用 IAM 角色的设置权限的更多信息,请参阅
将 IAM 角色附加到实例
。
<powershell>
$instanceId = (invoke-webrequest http://169.254.169.254/latest/meta-data/instance-id -UseBasicParsing).content
$nameValue = (get-ec2tag -filter @{Name="resource-id";Value=$instanceid},@{Name="key";Value="Name"}).Value
$pattern = "^(?![0-9]{1,15}$)[a-zA-Z0-9-]{1,15}$"
#Verify Name Value satisfies best practices for Windows hostnames
If ($nameValue -match $pattern)
{Try
{Rename-Computer -NewName $nameValue -Restart -ErrorAction Stop}
Catch
{$ErrorMessage = $_.Exception.Message
Write-Output "Rename failed: $ErrorMessage"}}
{Throw "Provided name not a valid hostname. Please ensure Name value is between 1 and 15 characters in length and contains only alphanumeric or hyphen characters"}
</powershell>
您还可以使用实例元数据中的标签对实例进行重命名,前提是您的实例配置为从实例元数据访问标签。有关更多信息,请参阅
使用实例元数据来查看实例的标签
。
<powershell>
$nameValue = Get-EC2InstanceMetadata -Path /tags/instance/Name
$pattern = "^(?![0-9]{1,15}$)[a-zA-Z0-9-]{1,15}$"
#Verify Name Value satisfies best practices for Windows hostnames
If ($nameValue -match $pattern)
{Try
{Rename-Computer -NewName $nameValue -Restart -ErrorAction Stop}
Catch
{$ErrorMessage = $_.Exception.Message