在您的 Windows 執行個體啟動時執行命令 - Amazon Elastic Compute Cloud

在您的 Windows 執行個體啟動時執行命令

當您在 Amazon EC2 中啟動 Windows 執行個體時,您可以將使用者資料傳遞給執行個體,以便在執行個體啟動後執行自動化設定工作或執行指令碼。執行個體的使用者資料將被視為不透明的資料,並由執行個體來解譯。使用者資料是由 EC2Launch v2 (支援的預覽 AMI 和下載)、在 Windows Server 2016 及更新版本上的 EC2Launch,以及在 Windows Server 2012 R2 及更早版本上的 EC2Config 來處理。

如需 UserData 範本中 AWS CloudFormation 屬性組件的範例,請參閱 Base64 編碼 UserData 屬性Base64 編碼 UserData 屬性與 AccessKey 和 SecretKey

如需有關啟動時在 Linux 執行個體上執行命令的資訊,請參閱 Linux 執行個體的 Amazon EC2 使用者指南啟動時,在您的 Linux 執行個體上執行命令

使用者資料指令碼

若要讓 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>

Windows PowerShell 指令碼的語法

AWS Windows AMI 包括 AWS Tools for Windows PowerShell,因此您可以在使用者資料中指定這些 cmdlet。如果您將 IAM 角色與執行個體建立關聯,就不需要向 cmdlet 指定憑證,因為在該執行個體上執行的應用程式會使用角色的憑證來存取 AWS 資源 (例如 Simple Storage Service (Amazon S3) 儲存貯體)。

使用 <powershell> 標籤指定 Windows PowerShell 指令碼。使用分行符號來區隔命令。<powershell> 標籤區分大小寫。

para>例如:

<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>

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.0 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

使用者資料執行

在預設情況下,所有 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: Initializing 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 - 如果找到 persist 標籤

  • Running userdata on every boot - 如果找到 persist 標籤

  • <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 - 如果找到 persist 標籤

  • Ec2HandleUserData: Message: Could not find <persist> and </persist> - 如果沒有找到 persist 標籤

  • Ec2HandleUserData: Message: The output from user scripts - 如果執行使用者資料指令碼,則會記錄其輸出

後續的重新開機或啟動

當您更新執行個體使用者資料時,使用者資料指令碼並未在您重新開機或啟動執行個體時自動執行。不過,您可以啟用使用者資料執行,以讓使用者資料指令碼在您重新開機或啟動執行個體時執行一次,或每次重新開機或啟動執行個體時都執行。

如果您選擇 Shutdown with Sysprep (使用 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. Open C:\Program Files\Amazon\Ec2ConfigService\Ec2ConfigServiceSetting.exe.

  3. 針對 User Data (使用者資料),選取 Enable UserData execution for next service start (啟用下一次服務啟動時的使用者資料執行)

  4. 中斷連線您的 Windows 執行個體。若要在下一次啟動執行個體時執行更新的指令碼,請停止執行個體並更新使用者資料。如需詳細資訊,請參閱 檢視及更新執行個體使用者資料

使用者資料與主控台

您可以在啟動執行個體時指定執行個體使用者資料。若執行個體的根磁碟區為 EBS 磁碟區,您也可以停止執行個體並更新其使用者資料。

在啟動時指定執行個體使用者資料

當您啟動執行個體時,請於啟動執行個體精靈的 Step 3: Configure Instance Details (步驟 3:設定執行個體詳細資訊) 頁面的 Advanced Details (進階詳細資訊)User data (使用者資料) 中指定指令碼。下圖中的範例會在 Windows 暫時資料夾中建立一個檔案,並在檔名中使用目前日期和時間。當您包括 <persist>true</persist> 時,指令碼會在您每次重新開機或啟動執行個體時執行。選取 As text (以文字) 時,Amazon EC2 主控台會為您執行 base64 編碼。

檢視及更新執行個體使用者資料

您可以檢視任何執行個體的執行個體使用者資料,並更新已終止之執行個體的執行個體使用者資料。

使用主控台更新執行個體的使用者資料

  1. https://console.aws.amazon.com/ec2/ 開啟 Amazon EC2 主控台。

  2. 在導覽窗格中,選擇 Instances (執行個體)。

  3. 選取執行個體,並選擇 Actions (動作)Instance state (執行個體狀態)Stop instance (停止執行個體)

    警告

    停止執行個體時,在任何執行個體存放區磁碟區的資料都會清除。若要保留執行個體存放區磁碟區的資料,請將資料備份至持久性儲存。

  4. 出現確認提示時,請選擇 Stop (停止)。停止執行個體可能需要幾分鐘。

  5. 在仍然選取執行個體的情況下,選擇動作 > 執行個體設定 > 編輯使用者資料。您無法在執行個體仍在執行中時變更使用者資料,但您可以檢視它。

  6. Edit user data (編輯使用者資料) 對話方塊中,更新使用者資料,然後選擇 Save (儲存)。若要在每次重新開機或啟動執行個體時執行使用者資料指令碼,請新增 <persist>true</persist>,如下範例所示:

  7. 啟動實例。若您已為後續的重新開機或啟動啟用使用者資料執行,即會在執行個體啟動程序期間執行更新的使用者資料指令碼。

使用者資料與 Tools for Windows PowerShell

您可以使用 Tools for Windows PowerShell 指定、修改和檢視您執行個體的使用者資料。如需使用執行個體中繼資料檢視您執行個體中使用者資料的資訊,請參閱擷取執行個體使用者資料。如需使用者資料和 AWS CLI 的資訊,請參閱 Linux 執行個體的 Amazon EC2 使用者指南中的使用者資料與 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 角色連接至執行個體

注意

此指令碼在 2008 以前的 Windows Server 版本上失敗。

<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>

如果您的執行個體設定為從執行個體中繼資料存取標籤,則還可以使用執行個體中繼資料中的標籤重新命名執行個體,。

注意

此指令碼在 2008 以前的 Windows Server 版本上失敗。

<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>