启动时在 Windows 实例上运行命令 - Amazon Elastic Compute Cloud
Amazon Web Services 文档中描述的 Amazon Web Services 服务或功能可能因区域而异。要查看适用于中国区域的差异,请参阅 中国的 Amazon Web Services 服务入门 (PDF)

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

当您使用 Amazon EC2 启动 Windows 实例时,可以将用户数据传递到可用于执行自动配置任务或在实例启动后运行脚本的实例。实例用户数据被视为不透明数据;需要由实例来解释。在 Windows Server 2022 上,用户数据由 EC2Launch v2 处理;在 Windows Server 2016 及 2019 上,用户数据由 EC2Launch 处理;在 Windows Server 2012 R2 及更早版本上,用户数据由 EC2Config 处理。

有关 UserData 模板中 Amazon CloudFormation 属性的程序集示例,请参阅 Base64 编码 UserData 属性带 AccessKey 和 SecretKey 的 Base64 编码 UserData 属性

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

有关在使用生命周期挂钩的 Auto Scaling 中的实例上运行命令的示例,请参阅《Amazon EC2 Auto Scaling 用户指南》中的教程:配置用户数据以通过实例元数据检索目标生命周期状态

用户数据脚本

要让 EC2Config 或 EC2Launch 运行脚本,在将脚本添加到用户数据中时,您必须将脚本封装在特殊标签中。您使用的标签取决于命令是在命令提示符窗口(批处理命令)中还是使用 Windows PowerShell 运行。

如果同时指定批处理脚本和 Windows PowerShell 脚本,则批处理脚本先运行,然后运行 Windows PowerShell 脚本,不论这些脚本在实例用户数据中的显示顺序如何。

如果您在用户数据脚本中使用 Amazon API(包括 Amazon CLI),则在启动实例时必须使用实例配置文件。实例配置文件提供用户数据脚本执行 API 调用所需的适当 Amazon 凭证。有关更多信息,请参阅实例配置文件。您分配给 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 脚本的语法

Amazon Windows AMI 包括 Amazon Tools for Windows PowerShell,因此您可在用户数据中指定这些 cmdlet。如果您将一个 IAM 角色与实例相关联,那么您不必为 cmdlet 指定凭证,因为实例上运行的应用程序可以使用该角色的凭证访问Amazon资源(例如 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>
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 编码的工具,则您必须自行对用户数据进行编码。否则,系统会记录找不到要运行的 scriptpowershell 标签的错误。下面是使用 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

用户数据执行

默认情况下,所有 Amazon 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 文件夹可能已隐藏。要查看该文件夹,您必须显示隐藏的文件和文件夹。

执行用户数据时将记录以下信息:

  • Userdata execution begins – 用户数据执行开始

  • <persist> tag was provided: true – 找到持久标签时

  • Running userdata on every boot – 找到持久标签时

  • <powershell> tag was provided.. running powershell content – 如果找到 PowerShell 标签

  • <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(预览 AMI)支持用户数据执行
  • 要在首次启动时对用户数据运行任务,请将 frequency 设置为 once

  • 要在每次启动时都对用户数据运行任务,请将 frequency 设置为 always

使用 EC2Launch(Windows Server 2016 或更高版本)支持用户数据执行
  1. 连接到您的 Windows 实例。

  2. 打开 PowerShell 命令窗口,并运行以下命令:

    C:\ProgramData\Amazon\EC2-Windows\Launch\Scripts\InitializeInstance.ps1 -Schedule
  3. 从 Windows 实例断开连接。要在下次实例启动时运行更新后的脚本,请停止实例并更新用户数据。有关更多信息,请参阅查看和更新实例用户数据

使用 EC2Config(Windows Server 2012 R2 及更低版本)支持用户数据执行
  1. 连接到您的 Windows 实例。

  2. 打开 C:\Program Files\Amazon\Ec2ConfigService\Ec2ConfigServiceSetting.exe

  3. 对于用户数据,选择 Enable UserData execution for next service start (为下次服务启动启用用户数据执行)。

  4. 从 Windows 实例断开连接。要在下次实例启动时运行更新后的脚本,请停止实例并更新用户数据。有关更多信息,请参阅查看和更新实例用户数据

用户数据和控制台

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

启动时指定实例用户数据

按照启动实例的程序进行操作。User data(用户数据)字段位于启动实例向导的 高级详细信息 部分。在用户数据字段中输入您的 PowerShell 脚本,然后完成实例启动程序。

用户数据字段的屏幕截图中,示例脚本在 Windows 临时文件夹中创建文件,在文件名中使用当前日期和时间。当您包括 <persist>true</persist> 时,每次重新引导或启动实例时将运行脚本。如果将用户数据已执行 base64 编码复选框保留为空,Amazon EC2 控制台将执行 base64 编码。


					Advanced Details(高级详细信息)用户数据文本字段。

查看和更新实例用户数据

您可以查看任何实例的实例用户数据,也可以更新已停止实例的实例用户数据。

使用控制台更新实例的用户数据
  1. 通过以下网址打开 Amazon EC2 控制台:https://console.aws.amazon.com/ec2/

  2. 在导航窗格中,选择实例

  3. 选择所需实例,然后依次选择操作实例状态停止实例

    警告

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

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

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

  6. Edit user data (编辑用户数据) 对话框中,更新用户数据,然后选择 Save (保存)。要在每次重新引导或启动实例时运行用户数据脚本,请添加 <persist>true</persist>,如下例中所示。

    
							编辑 User Data(用户数据)对话框。
  7. 启动实例。如果为后续重新引导或启动启用了用户数据运行,则在实例启动过程中执行更新后的用户数据脚本。

用户数据和 Tools for Windows PowerShell

您可以使用 Tools for Windows PowerShell 指定、修改和查看实例的用户数据。有关使用实例元数据从实例查看用户数据的信息,请参阅从实例检索实例用户数据。有关用户数据和 Amazon CLI 的信息,请参阅 Amazon EC2 用户指南(适用于 Linux 实例)中的用户数据和 Amazon 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 角色附加到实例

注意

此脚本在 Windows Server 2008 之前的版本上将失败。

<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"}} Else {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>

您还可以使用实例元数据中的标签对实例进行重命名,前提是您的实例配置为从实例元数据访问标签

注意

此脚本在 Windows Server 2008 之前的版本上将失败。

<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 Write-Output "Rename failed: $ErrorMessage"}} Else {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>